#python #python-3.x #web-scraping #beautifulsoup
#python #python-3.x #очистка веб-страниц #beautifulsoup
Вопрос:
У меня немного необычный запрос; Я хочу получить идентификатор div на основе текста, в котором он отображается на веб-странице. Например, скажем, у меня есть следующий html:
<div class="productTabRightCompatibility">
<h2>
Product Downloads
</h2>
<ul class="listColumn">
<li>
<div class="iconSprite icon16 iconDownloads" id="layoutmain_1_ProductTabs1_rptResources_divResourceImage_0">
</div>
<a href="/-/dummy_link_one_technical_drawing" id="layoutmain_1_ProductTabs1_rptResources_hlResourceLink_0" target="_blank">
ProductOne Technical Drawing
</a>
</li>
<li>
<div class="iconSprite icon16 iconDownloads" id="layoutmain_1_ProductTabs1_rptResources_divResourceImage_1">
</div>
<a href="/-/dummy_link_two_cad_drawing" id="layoutmain_1_ProductTabs1_rptResources_hlResourceLink_1" target="_blank">
ProductOne CAD Drawing
</a>
</li>
<li>
<div class="iconSprite icon16 iconDownloads" id="layoutmain_1_ProductTabs1_rptResources_divResourceImage_2">
</div>
<a href="/-/dummy_link_three_installation_manual" id="layoutmain_1_ProductTabs1_rptResources_hlResourceLink_2" target="_blank">
ProductOne Installation Manual
</a>
</li>
</ul>
</div>
К сожалению, веб-сайт не всегда располагает их в одинаковом порядке, поэтому иногда Технический чертеж представлен идентификатором ResourceLink_0, а иногда чертеж САПР. Единственная константа заключается в том, что нужный мне элемент представлен текстом «[Product #] Технический чертеж». Я хочу иметь возможность просматривать несколько страниц и получать ссылку, соответствующую техническому чертежу, независимо от заказа. На данный момент я перебираю все ссылки и ищу ту, которая содержит «technical_drawing» где-нибудь в адресе ссылки, но мне интересно, есть ли лучший способ получить результат.
Комментарии:
1. Что вы хотите улучшить по сравнению с вашим предыдущим решением? Кажется, он делает то, что вы хотите.
2. @Mr.Yellow Мне просто интересно, есть ли способ найти ссылку на основе текста, который она показывает на странице, а не перебирать все ссылки. Если то, как я это делаю, является наиболее эффективным способом, это нормально, просто пытаюсь убедиться, что я сохраняю все как можно более pythonic.
Ответ №1:
Используя пакеты BeautifulSoup
и re
, вы должны быть в состоянии сделать что-то вроде этого:
from bs4 import BeautifulSoup
import re
html = """<div class="productTabRightCompatibility">
<h2>
Product Downloads
</h2>
<ul class="listColumn">
<li>
<div class="iconSprite icon16 iconDownloads" id="layoutmain_1_ProductTabs1_rptResources_divResourceImage_0">
</div>
<a href="/-/dummy_link_one_technical_drawing" id="layoutmain_1_ProductTabs1_rptResources_hlResourceLink_0" target="_blank">
ProductOne Technical Drawing
</a>
</li>
<li>
<div class="iconSprite icon16 iconDownloads" id="layoutmain_1_ProductTabs1_rptResources_divResourceImage_1">
</div>
<a href="/-/dummy_link_two_cad_drawing" id="layoutmain_1_ProductTabs1_rptResources_hlResourceLink_1" target="_blank">ProductOne CAD Drawing</a>
</li>
<li>
<div class="iconSprite icon16 iconDownloads" id="layoutmain_1_ProductTabs1_rptResources_divResourceImage_2">
</div>
<a href="/-/dummy_link_three_installation_manual" id="layoutmain_1_ProductTabs1_rptResources_hlResourceLink_2" target="_blank">
ProductOne Installation Manual
</a>
</li>
</ul>
</div>"""
soup = BeautifulSoup(html,'html.parser')
a_link = soup.find('a', text=re.compile("ProductOne Technical Drawing"))
print(a_link.get('href'))
ВЫВОД:
/-/dummy_link_one_technical_drawing
Комментарии:
1. Почему вы скопировали мой ответ?
2. 1. Пожалуйста, обратите внимание, что моя правка была написана за минуту до вашего ответа 2. Убедитесь, что у меня есть много дел, прежде чем «копировать ответы SO», пожалуйста
3. Я видел, что вы опубликовали ранее.Ok.Dnt не будьте слишком умны.
Ответ №2:
С помощью re
вы можете выполнить поиск по тексту тега, а затем получить href
значение этого тега. Я использовал find_all
здесь на случай, если у вас на странице присутствует более одного элемента.
import bs4
import re
html_doc='''<html><div class="productTabRightCompatibility">
<h2>
Product Downloads
</h2>
<ul class="listColumn">
<li>
<div class="iconSprite icon16 iconDownloads" id="layoutmain_1_ProductTabs1_rptResources_divResourceImage_0">
</div>
<a href="/-/dummy_link_one_technical_drawing" id="layoutmain_1_ProductTabs1_rptResources_hlResourceLink_0" target="_blank">
ProductOne Technical Drawing
</a>
</li>
<li>
<div class="iconSprite icon16 iconDownloads" id="layoutmain_1_ProductTabs1_rptResources_divResourceImage_1">
</div>
<a href="/-/dummy_link_two_cad_drawing" id="layoutmain_1_ProductTabs1_rptResources_hlResourceLink_1" target="_blank">
ProductOne CAD Drawing
</a>
</li>
<li>
<div class="iconSprite icon16 iconDownloads" id="layoutmain_1_ProductTabs1_rptResources_divResourceImage_2">
</div>
<a href="/-/dummy_link_three_installation_manual" id="layoutmain_1_ProductTabs1_rptResources_hlResourceLink_2" target="_blank">
ProductOne Installation Manual
</a>
</li>
</ul>
</div></html>'''
soup =bs4.BeautifulSoup(html_doc, 'html.parser')
items=soup.find_all('a' , text=re.compile("Technical Drawing"))
for item in items:
print(item['href'])
Вывод:
/-/dummy_link_one_technical_drawing
Комментарии:
1. Правильный ответ, только что получил первый от Maaz.
Ответ №3:
вы можете избежать использования find и regex и использовать более быстрый css attribute = value selector с завершением на $ operator
[href$='technical_drawing']
Код:
from bs4 import BeautifulSoup as bs
html='''<html><div class="productTabRightCompatibility">
<h2>
Product Downloads
</h2>
<ul class="listColumn">
<li>
<div class="iconSprite icon16 iconDownloads" id="layoutmain_1_ProductTabs1_rptResources_divResourceImage_0">
</div>
<a href="/-/dummy_link_one_technical_drawing" id="layoutmain_1_ProductTabs1_rptResources_hlResourceLink_0" target="_blank">
ProductOne Technical Drawing
</a>
</li>
<li>
<div class="iconSprite icon16 iconDownloads" id="layoutmain_1_ProductTabs1_rptResources_divResourceImage_1">
</div>
<a href="/-/dummy_link_two_cad_drawing" id="layoutmain_1_ProductTabs1_rptResources_hlResourceLink_1" target="_blank">
ProductOne CAD Drawing
</a>
</li>
<li>
<div class="iconSprite icon16 iconDownloads" id="layoutmain_1_ProductTabs1_rptResources_divResourceImage_2">
</div>
<a href="/-/dummy_link_three_installation_manual" id="layoutmain_1_ProductTabs1_rptResources_hlResourceLink_2" target="_blank">
ProductOne Installation Manual
</a>
</li>
</ul>
</div></html>'''
soup =bs(html, 'lxml')
link =soup.select_one("[href$='technical_drawing']")['href']
print(link)