如何使用 python 从多个维基百科页面抓取数据?
How to scrape data from multiple wikipedia pages with python?
我想获取参议员的年龄、出生地和以前的职业。
每个参议员的信息都可以在维基百科上找到,在他们各自的页面上,还有另一个页面 table 按名字列出所有参议员。
我怎样才能浏览该列表,通过链接访问每位参议员的各自页面,并获取我想要的信息?
这是我到目前为止所做的。
1。 (no python) 发现 DBpedia 存在并编写了一个查询来搜索参议员。不幸的是,DBpedia 没有对其中的大部分(如果有的话)进行分类:
SELECT ?senator, ?country WHERE {
?senator rdf:type <http://dbpedia.org/ontology/Senator> .
?senator <http://dbpedia.org/ontology/nationality> ?country
}
查询 results 不满意。
2。发现有一个名为 wikipedia
的 python 模块允许我从各个 wiki 页面搜索和检索信息。通过查看超链接,使用它从 table 中获取参议员姓名列表。
import wikipedia as w
w.set_lang('pt')
# Grab page with table of senator names.
s = w.page(w.search('Lista de Senadores do Brasil da 55 legislatura')[0])
# Get links to senator names by removing links of no interest
# For each link in the page, check if it's a link to a senator page.
senators = [name for name in s.links if not
# Senator names don't contain digits nor ,
(any(char.isdigit() or char == ',' for char in name) or
# And full names always contain spaces.
' ' not in name)]
此时我有点迷茫。这里的列表 senators
包含所有参议员姓名,但也包含其他姓名,例如党派姓名。 wikipidia
模块(至少从我在 API 文档中可以找到的)也没有实现跟踪链接或搜索 tables.
的功能
我在 Whosebug 上看到了两个相关的条目,它们似乎很有帮助,但它们 (here and here) 都从一个页面中提取信息。
任何人都可以指出我的解决方案吗?
谢谢!
好的,所以我想通了(感谢指向我 BeautifulSoup 的评论)。
实现我想要的其实没有什么大秘密。我只需要用 BeautifulSoup 遍历列表并存储所有 link,然后用 urllib2
打开每个存储的 link,调用 BeautifulSoup响应,和.. 完成。这是解决方案:
import urllib2 as url
import wikipedia as w
from bs4 import BeautifulSoup as bs
import re
# A dictionary to store the data we'll retrieve.
d = {}
# 1. Grab the list from wikipedia.
w.set_lang('pt')
s = w.page(w.search('Lista de Senadores do Brasil da 55 legislatura')[0])
html = url.urlopen(s.url).read()
soup = bs(html, 'html.parser')
# 2. Names and links are on the second column of the second table.
table2 = soup.findAll('table')[1]
for row in table2.findAll('tr'):
for colnum, col in enumerate(row.find_all('td')):
if (colnum+1) % 5 == 2:
a = col.find('a')
link = 'https://pt.wikipedia.org' + a.get('href')
d[a.get('title')] = {}
d[a.get('title')]['link'] = link
# 3. Now that we have the links, we can iterate through them,
# and grab the info from the table.
for senator, data in d.iteritems():
page = bs(url.urlopen(data['link']).read(), 'html.parser')
# (flatten list trick: [a for b in nested for a in b])
rows = [item for table in
[item.find_all('td') for item in page.find_all('table')[0:3]]
for item in table]
for rownumber, row in enumerate(rows):
if row.get_text() == 'Nascimento':
birthinfo = rows[rownumber+1].getText().split('\n')
try:
d[senator]['birthplace'] = birthinfo[1]
except IndexError:
d[senator]['birthplace'] = ''
birth = re.search('(.*\d{4}).*\((\d{2}).*\)', birthinfo[0])
d[senator]['birthdate'] = birth.group(1)
d[senator]['age'] = birth.group(2)
if row.get_text() == 'Partido':
d[senator]['party'] = rows[rownumber + 1].getText()
if 'Profiss' in row.get_text():
d[senator]['profession'] = rows[rownumber + 1].getText()
很简单。 BeautifulSoup 创造奇迹 =)
我想获取参议员的年龄、出生地和以前的职业。 每个参议员的信息都可以在维基百科上找到,在他们各自的页面上,还有另一个页面 table 按名字列出所有参议员。 我怎样才能浏览该列表,通过链接访问每位参议员的各自页面,并获取我想要的信息?
这是我到目前为止所做的。
1。 (no python) 发现 DBpedia 存在并编写了一个查询来搜索参议员。不幸的是,DBpedia 没有对其中的大部分(如果有的话)进行分类:
SELECT ?senator, ?country WHERE { ?senator rdf:type <http://dbpedia.org/ontology/Senator> . ?senator <http://dbpedia.org/ontology/nationality> ?country }
查询 results 不满意。
2。发现有一个名为 wikipedia
的 python 模块允许我从各个 wiki 页面搜索和检索信息。通过查看超链接,使用它从 table 中获取参议员姓名列表。
import wikipedia as w
w.set_lang('pt')
# Grab page with table of senator names.
s = w.page(w.search('Lista de Senadores do Brasil da 55 legislatura')[0])
# Get links to senator names by removing links of no interest
# For each link in the page, check if it's a link to a senator page.
senators = [name for name in s.links if not
# Senator names don't contain digits nor ,
(any(char.isdigit() or char == ',' for char in name) or
# And full names always contain spaces.
' ' not in name)]
此时我有点迷茫。这里的列表 senators
包含所有参议员姓名,但也包含其他姓名,例如党派姓名。 wikipidia
模块(至少从我在 API 文档中可以找到的)也没有实现跟踪链接或搜索 tables.
我在 Whosebug 上看到了两个相关的条目,它们似乎很有帮助,但它们 (here and here) 都从一个页面中提取信息。
任何人都可以指出我的解决方案吗?
谢谢!
好的,所以我想通了(感谢指向我 BeautifulSoup 的评论)。
实现我想要的其实没有什么大秘密。我只需要用 BeautifulSoup 遍历列表并存储所有 link,然后用 urllib2
打开每个存储的 link,调用 BeautifulSoup响应,和.. 完成。这是解决方案:
import urllib2 as url
import wikipedia as w
from bs4 import BeautifulSoup as bs
import re
# A dictionary to store the data we'll retrieve.
d = {}
# 1. Grab the list from wikipedia.
w.set_lang('pt')
s = w.page(w.search('Lista de Senadores do Brasil da 55 legislatura')[0])
html = url.urlopen(s.url).read()
soup = bs(html, 'html.parser')
# 2. Names and links are on the second column of the second table.
table2 = soup.findAll('table')[1]
for row in table2.findAll('tr'):
for colnum, col in enumerate(row.find_all('td')):
if (colnum+1) % 5 == 2:
a = col.find('a')
link = 'https://pt.wikipedia.org' + a.get('href')
d[a.get('title')] = {}
d[a.get('title')]['link'] = link
# 3. Now that we have the links, we can iterate through them,
# and grab the info from the table.
for senator, data in d.iteritems():
page = bs(url.urlopen(data['link']).read(), 'html.parser')
# (flatten list trick: [a for b in nested for a in b])
rows = [item for table in
[item.find_all('td') for item in page.find_all('table')[0:3]]
for item in table]
for rownumber, row in enumerate(rows):
if row.get_text() == 'Nascimento':
birthinfo = rows[rownumber+1].getText().split('\n')
try:
d[senator]['birthplace'] = birthinfo[1]
except IndexError:
d[senator]['birthplace'] = ''
birth = re.search('(.*\d{4}).*\((\d{2}).*\)', birthinfo[0])
d[senator]['birthdate'] = birth.group(1)
d[senator]['age'] = birth.group(2)
if row.get_text() == 'Partido':
d[senator]['party'] = rows[rownumber + 1].getText()
if 'Profiss' in row.get_text():
d[senator]['profession'] = rows[rownumber + 1].getText()
很简单。 BeautifulSoup 创造奇迹 =)