使用BeautifulSoup(Python)解析HTML表格
##### 更新 ###### : 使用 renderContents() 而不是 contents[0] 解决了问题。如果有人能提供更好、更优雅的解决方案,我会继续保持这个问题开放!
我正在尝试从多个网页中提取所需的数据。这个表格没有类名或ID标签。所以我必须在 tr 的内容中搜索“网站”。
当前问题: 显示 td.contents 的文本没问题,但不知道为什么超链接却不行?我哪里做错了?有没有更好的方法可以在 Python 中使用 BeautifulSoup 来实现这个?
那些建议使用 lxml 的朋友,我在这里有一个正在进行的讨论 这里,在 centOS 上安装 lxml 而没有管理员权限现在有点麻烦。所以我在探索使用 BeautifulSoup 的选项。
HTML 示例:
<table border="2" width="100%">
<tbody><tr>
<td width="33%" class="BoldTD">Website</td>
<td width="33%" class="BoldTD">Last Visited</td>
<td width="34%" class="BoldTD">Last Loaded</td>
</tr>
<tr>
<td width="33%">
<a href="http://google.com"></a>
</td>
<td width="33%">01/14/2011
</td>
<td width="34%">
</td>
</tr>
<tr>
<td width="33%">
stackoverflow.com
</td>
<td width="33%">01/10/2011
</td>
<td width="34%">
</td>
</tr>
<tr>
<td width="33%">
<a href="http://stackoverflow.com"></a>
</td>
<td width="33%">01/10/2011
</td>
<td width="34%">
</td>
</tr>
</tbody></table>
到目前为止的 Python 代码:
f1 = open(PATH + "/" + FILE)
pageSource = f1.read()
f1.close()
soup = BeautifulSoup(pageSource)
alltables = soup.findAll( "table", {"border":"2", "width":"100%"} )
print "Number of tables found : " , len(alltables)
for table in alltables:
rows = table.findAll('tr')
for tr in rows:
cols = tr.findAll('td')
for td in cols:
print td.contents[0]
2 个回答
1
我在这里回答过一个类似的问题 这里。希望对你有帮助。
一个简单易懂的解决方案:
alltables = soup.findAll( "table", {"border":"2", "width":"100%"} )
t = [x for x in soup.findAll('td')]
[x.renderContents().strip('\n') for x in t]
输出结果:
['Website',
'Last Visited',
'Last Loaded',
'<a href="http://google.com"></a>',
'01/14/2011\n ',
'',
' stackoverflow.com\n ',
'01/10/2011\n ',
'',
'<a href="http://stackoverflow.com"></a>',
'01/10/2011\n ',
'']
1
from BeautifulSoup import BeautifulSoup
pageSource='''...omitted for brevity...'''
soup = BeautifulSoup(pageSource)
alltables = soup.findAll( "table", {"border":"2", "width":"100%"} )
results=[]
for table in alltables:
rows = table.findAll('tr')
lines=[]
for tr in rows:
cols = tr.findAll('td')
for td in cols:
text=td.renderContents().strip('\n')
lines.append(text)
text_table='\n'.join(lines)
if 'Website' in text_table:
results.append(text_table)
print "Number of tables found : " , len(results)
for result in results:
print(result)
产生
Number of tables found : 1
Website
Last Visited
Last Loaded
<a href="http://google.com"></a>
01/14/2011
stackoverflow.com
01/10/2011
<a href="http://stackoverflow.com"></a>
01/10/2011
这是不是你想要的结果?问题在于 td.contents
返回的是一个包含 NavigableStrings
和 soup 标签
的列表。例如,运行 print(td.contents)
可能会得到
['', '<a href="http://stackoverflow.com"></a>', '']
所以直接取列表的第一个元素会让你错过 <a>
标签。