在BeautifulSoup

时间:2016-02-17 22:54:55

标签: python beautifulsoup

我正在尝试从网页上抓取一些数据,这些数据包含具有多个部分标记的div个标记。例如。 <div class="A"><div class="A B"><div class="A X Y">。我想收集前两种类型的标签,但不是最后一种。

我认为使用BeautifulSoup这很简单:

from bs4 import BeautifulSoup
import re
from urllib import request

url_request = request.Request(url)
html = request.urlopen(url_request)
soup = BeautifulSoup(html, "lxml")

divs = soup.find_all("div", {"class": re.compile("A( B)?$")})

但是,当我查看divs时,我发现所有<div class="A X Y">标签也都存在。

问题似乎是BeautifulSoup认为该类是一个列表,而不是一个字符串:

>> div['class']
>> ['A', 'X', 'Y']

我可以使用正则表达式(或其他任何东西)删除不需要的标签吗?我宁愿忽略它们,而不是选择我想要的标签。

2 个答案:

答案 0 :(得分:1)

问题是class多值属性。在类似问题的背景下,这是一个非常详细的故事:BeautifulSoup returns empty list when searching by compound class names

作为解决方法,您可以创建过滤功能

def filter_function(elm):
    return elm and "class" in elm.attrs and "A" in elm["class"] and "Y" not in elm["class"]

完整示例:

from bs4 import BeautifulSoup

html = """
<div>
     <div class="A">test1</div>
     <div class="A B">test2</div>
     <div class="A X Y">test3</div>
</div>
"""

soup = BeautifulSoup(html, "lxml")

def filter_function(elm):
    return elm and "class" in elm.attrs and "A" in elm["class"] and "Y" not in elm["class"]

for div in soup.find_all(filter_function):
    print(div.text)

打印:

test1
test2

答案 1 :(得分:0)

您可以使用过滤功能请求BeautifulSoup选择标记。

html = '<html><body><div class="A"/><div class="A B"/><div class="A X Y"/></body></html>'
soup = BeautifulSoup(html, "lxml")
soup.find_all('div', {'class':'A'})
[<div class="A"></div>, <div class="A B"></div>, <div class="A X Y"></div>]

def f(tag):
    return tag.has_attr('class') and 'X' not in tag['class']

soup.find_all(f)
[<div class="A"></div>, <div class="A B"></div>]

您可以在该过滤函数中编写任意复杂的规则,以获得您想要的任何结果。