#python #html #web-scraping #beautifulsoup #html-sanitizing
#python #HTML #очистка веб-страниц #beautifulsoup #html-очистка
Вопрос:
Я написал следующий простой HTML-фильтр, используя requests
и BeautifulSoup
, который должен принимать список разрешенных тегов и атрибутов и удаляет любые теги, которых нет в списке:
def filter_tags(soup, tags_to_keep, allowed_attrs=None):
for tag in soup.body.descendants:
if tag.name in tags_to_keep:
new_attrs = dict()
for k,v in tag.attrs.items():
if allowed_attrs and k in allowed_attrs:
new_attrs[k] = v
tag.attrs = new_attrs
elif isinstance(tag, NavigableString):
continue
else:
# insert one whitespace char so words on either side of tag aren't concat'ed together
tag.insert_before(" ")
tag.decompose()
return soup
Я вызываю функцию следующим образом: soup = filter_tags(soup, tags_to_keep=['html', 'body', 'div', 'a'], allowed_attrs=['href'])
.
Эта функция, похоже, работает для простых входных данных, подобных этому:
<body>
<div id="cats">
This is a test
<a href="http://www.google.com">Google!</a>
More text
</div>
<div>
More text
<script>...oh javascript...</script>
</div>
</body>
Под «работает» я подразумеваю, что оно корректно удаляет теги <script>
и <img>
и id=
атрибут, сохраняя при этом указанные теги и href=
attr), поэтому впоследствии это выглядит так:
<body>
<div>
This is a test
<a href="http://www.google.com">Google!</a>
More text
</div>
<div>
More text
</div>
</body>
Однако для более сложного HTML он полностью завершается ошибкой (примером страницы, которая завершается ошибкой, является http://www.cnn.com
), И <script>
Теги, атрибуты тегов и т.д. Не Удаляются из HTML. Я получаю вывод, подобный этому:
import requests
from bs4 import BeautifulSoup
soup = BeautifulSoup(requests.get('http://www.cnn.com').text, 'lxml')
filter_tags(soup, tags_to_keep=['body', 'a', 'div'], allowed_attrs=['href'])
|
|
V
... <li class="m-legal__list__item last-child">
<a class="m-legal__links" data-analytics="footer_cnn-newsource" href="http://cnnnewsource.com">CNN Newsource</a></li>
</ul></div></div></div></div></div></footer>
<div class="OUTBRAIN" data-ob-template="cnn" data-src="" data-widget-id="TR_1"></div>
<script>(function (d) ...
Как вы можете видеть, он не удаляет ни один из тегов / атрибутов, таких как <script>
или class=
в более сложном HTML, подобном этому, но я не могу понять, почему, основываясь на моих простых тестах, где это, кажется, работает нормально…
Что не так с моей функцией выше, из-за чего ей не удается удалить теги / атрибуты для сложного HTML? Моя интуиция заключается в том, что это может быть как-то связано с изменением дерева DOM с помощью .decompose()
по мере прохождения .descendants
, но я не могу сказать наверняка. Если проблема в этом, какова альтернатива методу, который я пытаюсь использовать здесь?
Комментарии:
1. какую библиотеку вы используете для получения HTML-содержимого CNN? запросы?
2. Да, я использую
requests
иBeautifulSoup
. Извините, я уточню это в основном сообщении. Однако я вручную проверил HTML изwww.cnn.com
, и requests правильно загружает его.filter_html()
Функция просто не удаляет из нее другие подобные<script>
теги, хотя она удаляет их для простого примера выше.3. да, только что протестировал его на своем компьютере, и я получаю ту же проблему. Надеюсь, кто-нибудь сможет помочь.
4. Кажется,
.descendants
что оно не возвращает дочерние теги глубже одного уровня, попробуйте.find_all()
.5. т.М. Адам — Из документов bs4 для .descendants : » Атрибут .descendants позволяет вам рекурсивно перебирать все дочерние элементы тега: его прямые дочерние элементы, дочерние элементы его прямых дочерних элементов и так далее «.