Можно ли использовать несколько фильтров в одном документе BeautifulSoup? - PullRequest
0 голосов
/ 22 февраля 2019

Я использую Django и Python 3.7.Я хочу ускорить мой анализ HTML.В настоящее время я ищу три типа элементов в своем документе, например:

req = urllib2.Request(fullurl, headers=settings.HDR)
html = urllib2.urlopen(req).read()
comments_soup = BeautifulSoup(html, features="html.parser")

score_elts = comments_soup.findAll("div", {"class": "score"})

comments_elts = comments_soup.findAll("a", attrs={'class': 'comments'})

bad_elts = comments_soup.findAll("span", text=re.compile("low score"))

Я прочитал, что SoupStrainer - это один из способов улучшить производительность - https://www.crummy.com/software/BeautifulSoup/bs4/doc/#parsing-only-part-of-a-document.Тем не менее, все примеры говорят только о разборе документа HTML с одним фильтром.В моем случае у меня их три.Как я могу передать три фильтра в мой синтаксический анализ, или это на самом деле приведет к ухудшению производительности, если я просто сделаю это так, как я делаю это сейчас?

1 Ответ

0 голосов
/ 22 февраля 2019

Не думаю, что вы можете передать несколько фильтров в конструктор BeautifulSoup.Вместо этого вы можете обернуть все свои условия в один фильтр и передать его конструктору BeautifulSoup.

Для простых случаев, таких как только имена тегов, вы можете передать список в SoupStrainer

html="""
<a>yes</a>
<p>yes</p>
<span>no</span>
"""
from bs4 import BeautifulSoup
from bs4 import SoupStrainer
custom_strainer = SoupStrainer(["a","p"])
soup=BeautifulSoup(html, "lxml", parse_only=custom_strainer)
print(soup)

Выходные данные

<a>yes</a><p>yes</p>

Для указания дополнительной логики вытакже может передавать пользовательскую функцию (возможно, вам придется это сделать).

html="""
<html class="test">
<a class="wanted">yes</a>
<a class="not-wanted">no</a>
<p>yes</p>
<span>no</span>
</html>
"""
from bs4 import BeautifulSoup
from bs4 import SoupStrainer
def my_function(elem,attrs):
    if elem=='a' and attrs['class']=="wanted":
        return True
    elif elem=='p':
        return True
custom_strainer= SoupStrainer(my_function)
soup=BeautifulSoup(html, "lxml", parse_only=custom_strainer)
print(soup)

Вывод

<a class="wanted">yes</a><p>yes</p>

Как указано в документации

Парсингтолько часть документа не сэкономит вам много времени при разборе документа, но может сэкономить много памяти и значительно ускорит поиск документа.

Я думаю, вам следует проверить Улучшение производительности раздел документации.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...