【问题标题】:Can SoupStrainer have two arguments?SoupStrainer 可以有两个参数吗?
【发布时间】:2015-02-27 02:39:58
【问题描述】:

好吧,这开始是一个问题,但到了一半我想通了。我在 stackoverflow 或 Google 上找不到这样的问题,所以无论如何我都会发布它以帮助任何偶然发现它的人。

我想使用 BeautifulSoup 中的 SoupStrainer 来解析两个标签,而不是 html 文档中的一个。

我知道我可以做到:

soup = BeautifulSoup(content.text, 'lxml', parse_only=SoupStrainer('p'))  

这将获得<p> 标签。我还想获得<h3> 标签。所以我尝试了这个:

soup = BeautifulSoup(content.text, 'lxml', parse_only=SoupStrainer('h3', 'p'))

但这行不通,因为 SoupStrainer 只接受一个参数。

答案如下。

【问题讨论】:

  • 如果您要自行回答,请将回答部分放在单独的回答帖中。

标签: python python-3.x beautifulsoup


【解决方案1】:

要让 SoupStrainer 解析多个标签,你需要将它们放在一个列表中。像这样:

soup = BeautifulSoup(content.text, 'lxml', parse_only=SoupStrainer(['h3', 'p']))

both解析content.text 中的<h3><p> 标签,即使它们是同级的(即一个标签不在另一个标签内)。

您也可以使用两个以上的标签来执行此操作,只要您将它们作为一个列表传递给 SoupStrainer。

一个标签:

soup = BeautifulSoup(content.text, 'lxml', parse_only=SoupStrainer('p'))

多个标签:

soup = BeautifulSoup(content.text, 'lxml', parse_only=SoupStrainer(['h1', 'h3', 'p', 'h4']))

【讨论】:

  • 我知道这已经很长时间了,但也可以解析多个标签,但只能解析具有特定属性的标签。我试着把 soup = BeautifulSoup(content.text, 'lxml', parse_only=SoupStrainer([('h1', {class="foo"}), 'h3', 'p', 'h4'])) 但是这不起作用
【解决方案2】:

regex 有更多的权力。使用re 模块。

这将获得<p> 标签。我也想得到<h3> 标签。

soup = BeautifulSoup(content.text, 'lxml', parse_only=SoupStrainer(re.compile(r"p|h3")))

@Martijn 对于属性,您可以使用attrs

soup = BeautifulSoup(content.text, 'lxml', parse_only=SoupStrainer(re.compile(r"p|h3")), class_="foo")
soup = BeautifulSoup(content.text, 'lxml', parse_only=SoupStrainer(re.compile(r"p|h3")), attrs={"class": "foo"})

但您显然不能为每个 HTML tag 应用 class。您可以使用css 选择器来解决它。

soup = BeautifulSoup(content.text, 'lxml', parse_only=SoupStrainer(["h1", "h2", "h3", "p"])).select("h1.foo, h2, h3, p")

【讨论】:

    【解决方案3】:

    下面是SoupStrainer的构造函数在bs4中的定义:

    class SoupStrainer(object):
        """Encapsulates a number of ways of matching a markup element (tag or
        text)."""
    
        def __init__(self, name=None, attrs={}, text=None, **kwargs):
    
    ...
    

    因此,添加到@JohnStrood 的答案,您可以使用attrs 参数(字典)来限制一个或多个属性的匹配:

    attrs_dict = { "class": "foo", "other_attr": ["value1", "value2"] }
    strainer = SoupStrainer([h3, p], attrs=attrs_dict)
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2011-04-15
      • 2016-03-25
      • 2012-06-30
      • 2011-08-01
      • 1970-01-01
      • 2014-05-11
      • 2011-08-06
      相关资源
      最近更新 更多