SoupStrainer可以有两个参数吗?

时间:2014-12-30 22:59:19

标签: python python-3.x beautifulsoup

嗯,这开始是一个问题,但我想通了一半。我无法在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只接受一个参数。

答案如下。

3 个答案:

答案 0 :(得分:3)

要使SoupStrainer解析多个标记,您需要将它们放在列表中。像这样:

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

这解析了<h3><p>content.text标记的 ,即使它们是兄弟姐妹(即一个标记不在另一个标记内)。

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

一个标签:

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

多个标签:

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

答案 1 :(得分:1)

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 class应用tag。您可以使用css选择器来解决它。

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

答案 2 :(得分:0)

这是在bs4中定义SoupStrainer的构造函数的方法:

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)