如何通过网络抓取从Wikipedia表中提取数字(或字符串)数据?

时间:2019-08-07 08:11:58

标签: python-3.x web-scraping html-table beautifulsoup wikipedia

我想使用BeautifulSoup从Wikipedia文章中收集数据,以创建HR图。在下面的示例中,我选择了名为Arcturus的恒星,尽管代码的目的是使通用性足以(几乎?)为任何恒星工作。维基百科页面上每个星的最右边的表格包含构造该图所需的所有信息。

例如,考虑wikipedia page for Arcturus。光谱类型可以在Characteristics子标题下找到;绝对大小可以在Astrometry子标题下找到;发光度和温度可以在Details子标题下找到。由于所有这些信息都包含在同一个主表中,因此我尝试了以下操作:

import requests
from bs4 import BeautifulSoup
# import numpy as np
# import matplotlib.pyplot as plt

hyperlink = 'https://en.wikipedia.org/wiki/Arcturus'
webdata = requests.get(hyperlink)
soup = BeautifulSoup(webdata.text, 'lxml')
# print("\nPRETTY SOUP:\n{}\n".format(soup.prettify()))

res = []
right_table = soup.find('table', class_='infobox')
for row in right_table.findAll('tr'):
    cells = row.findAll('td')
    print("\n .. CELLS:\n{}\n".format(cells))

此代码将为表的每一行运行一个单独的print命令。我使用ctrl + f查找出现的“温度”一词,从中找到了相关的print语句:

 .. CELLS:
[<td><b><a href="/wiki/Effective_temperature" title="Effective temperature">Temperature</a></b></td>, <td><span class="nowrap"><span data-sort-value="7003428600000000000♠"></span>4286<span style="margin-left:0.3em;margin-right:0.15em;">±</span>30</span><sup class="reference" id="cite_ref-ramirez_prieto_2011_7-3"><a href="#cite_note-ramirez_prieto_2011-7">[7]</a></sup> <a href="/wiki/Kelvin" title="Kelvin">K</a></td>]

实际值为4286 ± 30 K。是否有一种易于概括的方法来解析此html字符串?我想相信提取其他相关参数(例如光谱类型)的方法不会有太大区别。

2 个答案:

答案 0 :(得分:1)

您可以使用

for row in right_table.findAll('tr'):
    cells = ' '.join([i.get_text() for i in row.findAll('td')])
    print(cells)

但是您将获得例如超级脚本和子脚本。

答案 1 :(得分:1)

如果您只想提取特定信息,可以使用此示例(使用CSS selectors获取信息):

import requests
from bs4 import BeautifulSoup

hyperlink = 'https://en.wikipedia.org/wiki/Arcturus'
webdata = requests.get(hyperlink)
soup = BeautifulSoup(webdata.text, 'lxml')

def remove_sup(tag):
    for s in tag.select('sup'):
        s.extract()
    return tag

spectral = remove_sup(soup.select_one(":matches(td, th):contains('Spectral') + td")).get_text(strip=True)
magnitude = remove_sup(soup.select_one(":matches(td, th):contains('Absolute') + td")).get_text(strip=True)
lum = remove_sup(soup.select_one(":matches(td, th):contains('Luminosity') + td")).get_text(strip=True)
temp = remove_sup(soup.select_one(":matches(td, th):contains('Temperature') + td")).get_text(strip=True)

print('{: <25}{}'.format('Spectral type :', spectral))
print('{: <25}{}'.format('Absolute magnitude :', magnitude))
print('{: <25}{}'.format('Luminosity :', lum))
print('{: <25}{}'.format('Temperature :', temp))

打印:

Spectral type :          K0 III
Absolute magnitude :     −0.30±0.02
Luminosity :             170L☉
Temperature :            4286±30K