我正在尝试使用Beautiful Soup来搜索html文档。有没有办法在文档中搜索包含某些关键字字符串的表?例如,如果我有一张表:
<table>
<tr>
<td> 'abc' </td>
<td> 'other data' </td>
</tr>
<tr>
<td> 'def' </td>
<td> 'other data' </td>
</tr>
<tr>
<td> '123' </td>
<td> 'other data' </td>
</tr>
<tr>
<td> '456' </td>
<td> 'other data' </td>
</tr>
</table>
在一个有许多其他表的html文档中,但这是唯一一个包含字符串"abc“、"def”和"456“的表,有没有办法搜索这个表?
我的一个想法是使用for循环来搜索所有的表、行和数据,但这似乎是不必要的步骤(文档非常大)。有没有一种方法可以使用BeautifulSoup来构造问题,比如(显然这不会起作用,但它可能会给出一个我想要写什么的想法):
.find('table', string=('abc'), string=('def'), string=re.compile('456'))
edit:是的,表需要所有这些字符串。html文件还包含其他表,这些表可能包含这些字符串中的任何一个,但只有1个表同时包含所有3个字符串。是的,我只会在标签中寻找字符串(可能是'text‘而不是'string',我不确定有什么区别)。
发布于 2018-07-03 07:57:54
一种解决方案是pass a function to soup.find()
。该函数必须且只有一个参数( bs4.element.Tag
对象),其目的是仅返回True或False:如果表符合您设置的条件,则返回True。
如果您想测试不同的字符串,可以从一个带有两个参数的函数开始,然后使用functools.partial()
将其缩减为一个:
from functools import partial
def _table_contains_strs(tag, strings):
"""Return True if `tag` has <td> tags that contain `strings`."""
if tag.name != 'table':
return False
tds = tag.find_all('td')
if not tds:
return False
test = {s: False for s in strings}
for tag in tds:
for s in strings:
if s in tag:
test[s] = True
if all(test.values()):
# You can return early (without full iteration)
# if all strings already matched.
return True
return False
def _make_single_arg_function(func, *args, **kwargs):
return partial(_table_contains_strs, *args, **kwargs)
table_contains_strs = _make_single_arg_function(
_table_contains_strs,
strings=('abc', 'def', '456')
)
现在,table_contains_strs
是一个只接受单个参数的函数,即一个Tag
。
下面是一个示例:
from bs4 import BeautifulSoup
# Add some text to other tags to make sure you're
# finding only in <td>s
html = """\
<table>
<th>field1</th>
<th>field2</th>
<tr>
<td>abc</td>
<td>other data</td>
</tr>
<tr>
<td>def</td>
<td>other data</td>
</tr>
<tr>
<td>123</td>
<td>other data</td>
</tr>
<tr>
<td>456</td>
<td>other data</td>
</tr>
</table>"""
soup = BeautifulSoup(html, 'html.parser')
soup.find(table_contains_strs)
# Should return the table above
注意:我不能说这会有特别好的伸缩性,因为它使用嵌套的for循环来检查每个<td>
标记中的每个字符串。但希望它能完成这项工作。只使用.text
可能不是一个好主意,因为这也会捕获您指定的不需要的其他嵌套标记。另一种优化是创建find_all()
的惰性generator version。
https://stackoverflow.com/questions/51143295
复制相似问题