我正在尝试从网页上抓取一些数据,这些数据包含具有多个部分标记的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']
我可以使用正则表达式(或其他任何东西)删除不需要的标签吗?我宁愿忽略它们,而不是选择我想要的标签。
答案 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>]
您可以在该过滤函数中编写任意复杂的规则,以获得您想要的任何结果。