首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >Python语言中BeautifulSoup中的.find()

Python语言中BeautifulSoup中的.find()
EN

Stack Overflow用户
提问于 2018-07-03 04:26:27
回答 1查看 63关注 0票数 2

我正在尝试使用Beautiful Soup来搜索html文档。有没有办法在文档中搜索包含某些关键字字符串的表?例如,如果我有一张表:

代码语言:javascript
复制
<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来构造问题,比如(显然这不会起作用,但它可能会给出一个我想要写什么的想法):

代码语言:javascript
复制
.find('table', string=('abc'), string=('def'), string=re.compile('456'))

edit:是的,表需要所有这些字符串。html文件还包含其他表,这些表可能包含这些字符串中的任何一个,但只有1个表同时包含所有3个字符串。是的,我只会在标签中寻找字符串(可能是'text‘而不是'string',我不确定有什么区别)。

EN

回答 1

Stack Overflow用户

发布于 2018-07-03 07:57:54

一种解决方案是pass a function to soup.find()。该函数必须且只有一个参数( bs4.element.Tag对象),其目的是仅返回True或False:如果表符合您设置的条件,则返回True。

如果您想测试不同的字符串,可以从一个带有两个参数的函数开始,然后使用functools.partial()将其缩减为一个:

代码语言:javascript
复制
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

下面是一个示例:

代码语言:javascript
复制
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

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/51143295

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档