我有一些非常糟糕的HTML,长话短说,阻止我使用普通的嵌套<table>, <tr>, <td>
结构,这样可以很容易地重建表格。
这是一个带行号的片段供参考:
1 <td valign="top"> <!-- closing </td> should be on 6 -->
2 <font face="arial" size="1">
3 <center>
4 06-30-95
5 </center>
6 <tr valign="top">
7 <td>
8 <center>
9 <font ,="" arial,="" face="arial" sans="" serif"="" size="1">
10 1382
11 <p>
12 (23)
13 </p>
14 </font>
15 </center>
16 </td>
17 <td>
18 <font ,="" arial,="" face="arial" sans="" serif"="" size="1">
19 <center>
20 06-18-14
21 </center>
22 </font>
23 </td>
24 </tr>
25 </td> <!-- this should should be on 6 -->
tr
内td
s内tr
s的嵌套没有任何方案,并且与未关闭的标签相关联以进行引导。 HTML树绝不像它在结构上呈现的方式。 (在这种情况下,我认为技术上没有缺少结束标记,但页面的实际呈现表明应该没有嵌套的td
。)
但是,在这种情况下,按照以下规则进行播放
<td>
之前有一个开头<td>
的任何</td>
,(即任何嵌套的td
)都假设后者开放<td>
(第7行)作为第一行(第1行)的闭包; <td> ... </td>
标签(开启者和附近人员之间没有<td>
;例如上面的第17和23行。这里的期望结果将是:
['06-30-95', '1382\n(23)', '06-18-14']
如何在BeautifulSoup中解决这个问题?我会展示一个尝试,但已经选择了文档和一些来源,但根本没有找到。
目前,这将解析为:
html = """
<td valign="top">
<font face="arial" size="1">
<center>
06-30-95
</center>
<tr valign="top">
<td>
<center>
<font ,="" arial,="" face="arial" sans="" serif"="" size="1">
1382
<p>
(23)
</p>
</font>
</center>
</td>
<td>
<font ,="" arial,="" face="arial" sans="" serif"="" size="1">
<center>
06-18-14
</center>
</font>
</td>
</tr>
</td>
"""
from bs4 import BeautifulSoup, SoupStrainer
strainer = SoupStrainer('td')
soup = BeautifulSoup(html, 'html.parser', parse_only=strainer)
[tag.text.replace('\n', '') for tag in soup.find_all('td')]
[' 06-30-95 1382 (23) 06-18-14 ',
' 1382 (23) ',
' 06-18-14 ']
我对这个结果的问题不是空白;它是子串的重复。看起来我似乎需要递归地从最里面的标签向上工作,弹出每个标签并向外工作。但我必须猜测还有更多内置功能来处理缺少的结束标记(handle_endtag
从BeautifulSoup
构造函数中脱颖而出?)。
答案 0 :(得分:2)
对于非常破碎的HTML,有两种方法可以解决这个问题。首先是在最里面的嵌套级别找到最一致的打开/关闭标签集,并且只使用第一个。在这个有限的示例中,只要>>> from bs4 import BeautifulSoup
>>> soup = BeautifulSoup(html, 'html.parser')
>>> [t.find('center').text.strip() for t in soup.find_all('td')]
['06-30-95', '1382\n \n (23)', '06-18-14']
标签满足此要求即可。请考虑以下事项:
lxml
或者,使用>>> soup2 = BeautifulSoup(html, 'lxml')
>>> [t.text.strip() for t in soup2.find_all('td')]
['06-30-95', '1382\n \n (23)', '06-18-14']
代替(作为方法列出的Gulp Error)实际上可以更好地整体运作:
{{1}}
此主题涵盖了其他方法:documentation
答案 1 :(得分:2)
试试这个。它会获取您请求的输出:
from bs4 import BeautifulSoup
soup = BeautifulSoup(content, 'html5lib')
item = [' '.join(items.text.split()) for items in soup.select("center")]
print(item)
输出:
['06-30-95', '1382 (23)', '06-18-14']