如何从不同的表条目中提取信息:Text vs. DIV vs. SPAN
Posted
技术标签:
【中文标题】如何从不同的表条目中提取信息:Text vs. DIV vs. SPAN【英文标题】:How to extract info from varying table entries: Text vs. DIV vs. SPAN 【发布时间】:2015-06-18 14:43:21 【问题描述】:我是 python 新手,在网上搜索了我的问题的答案,但到目前为止我失败了......
问题:我的目标是从网站中提取数据。更具体地说,来自这些网站中的表格。您在我的 python 代码示例中的“data”中找到的网站代码中的相关 sn-p:
from bs4 import BeautifulSoup
data = '''<table class="ds-table">
<tr>
<td class="data-label">year of birth:</td>
<td class="data-value">1994</td>
</tr>
<tr>
<td class="data-label">reporting period:</td>
<td class="data-value">
<span class="editable" id="c-scope_beginning_date">
? </span>
-
<span class="editable" id="c-scope_ending_date">
? </span>
</td>
</tr>
<tr>
<td class="data-label">reporting cycle:</td>
<td class="data-value">
<span class="editable" id="c-periodicity">
- </span>
</td>
</tr>
<tr>
<td class="data-label">grade:</td>
<td class="data-value">1.3, upper 10% of class</td>
</tr>
<tr>
<td class="data-label">status:</td>
<td class="data-value"></td>
</tr>
</table>
<table class="ds-table">
<tr>
<td class="data-label">economics:</td>
<td class="data-value"><span class="positive-value"></span></td>
</tr>
<tr>
<td class="data-label">statistics:</td>
<td class="data-value"><span class="negative-value"></span></td>
</tr>
<tr>
<td class="data-label">social:</td>
<td class="data-value"><div id="music_id" class="trigger"><span class="negative-value"></span></div></td>
</tr>
<tr>
<td class="data-label">misc:</td>
<td class="data-value">
<div id="c_assurance" class="">
<span class="positive-value"></span> </div>
</td>
</tr>
<tr>
<td class="data-label">recommendation:</td>
<td class="data-value">
<span class="negative-value"></span> </td>
</tr>
</table>'''
soup = BeautifulSoup(data)
对于class="data-label"到目前为止我成功实现了...
box_cdl = []
for i, cdl in enumerate(soup.findAll('td', attrs='class': 'data-label')):
box_cdl.append(cdl.contents[0])
print box_cdl
...从列中提取文本,在(对我来说令人满意的)输出中:
[u'year of birth:',
u'reporting period:',
u'reporting cycle:',
u'grade:',
u'status:',
u'economics:',
u'statistics:',
u'social:',
u'misc:',
u'recommendation:']
我卡住的地方是 class="data-value"
的部分,带有 div- 和 span- 字段,并且一些相关信息隐藏在 跨度类。此外,tr-rows 的数量可能会因网站而异,例如“状态”出现在“报告周期”之后(而不是“等级”)。
但是,当我这样做时......
box_cdv = []
for j, cdv in enumerate(soup.findAll('td', attrs='class': 'data-value')):
box_cdv.append(cdv.contents[0])
print box_cdv
...我收到错误:
Traceback (most recent call last):
File "<ipython-input-53-7d5c095cf647>", line 3, in <module>
box_cdv.append(cdv.contents[0])
IndexError: list index out of range
我想得到的是这样的东西(对应于上面的“data”-example):
[u'1994',
u'? - ?',
u'-',
u'1.3, upper 10% of class',
u'',
u'positive-value',
u'negative-value',
u'negative-value',
u'positive-value',
u'negative-value']
问题:鉴于适当的提取代码取决于类别(出生年份、报告期、...、推荐)?
或者,问不同:什么代码提取我,取决于类别(出生年份,报告期,...,推荐),相应的值(1994,...,负-值)?
由于不同网站的表格条目的数量和类型可能不同,简单的“在第 i 个条目上执行以下操作”程序不适用。我想我正在寻找的东西类似于“如果你找到文本“推荐:”,然后从跨度字段中提取类类型”,我猜。但不幸的是,我不知道如何将其翻译成 python 语言。
非常感谢任何帮助。
【问题讨论】:
【参考方案1】:您收到该错误是因为其中一个标签没有任何children
,因此contents
列表在搜索该索引时会出错。
您可以通过以下方式解决此问题:
1) 搜索data-label
标签;
2) 找到下一个TD
兄弟;
3 A) 检查同级是否有文本;
3 A) 1) 如果是这样,则创建一个以data-label
为键、兄弟文本为其值的字典条目;
3 A) B) 如果没有,则检查同级第一个孩子是否有一个包含-value`的类
4) 解析数据。
例子:
soup = BeautifulSoup(data, 'lxml')
result =
for tag in soup.find_all("td", "class" : "data-label" ):
NextSibling = tag.find_next("td", "class" : "data-value" ).get_text(strip = True)
if not NextSibling and len(tag.find_next("td").select('span[class*=-value]')) > 0:
NextSibling = tag.find_next("td").select('span[class*=-value]')[0]["class"][0]
result[tag.get_text(strip = True)] = NextSibling
print (result)
结果:
'出生年份:': '1994', '报告期:': '?-?', '报告周期:':'-', 'grade:': '1.3, 班级前 10%', '状态:': '', '经济学:':'正值', '统计:':'负值', '社会:':'负值', 'misc:': '正值', '推荐:':'负值'
【讨论】:
以上是关于如何从不同的表条目中提取信息:Text vs. DIV vs. SPAN的主要内容,如果未能解决你的问题,请参考以下文章
如何从 SQLite 中的表中选择最新的 100 个不同条目?
Logstash RSS Feed(重复数据删除并提取某些数据)