Python HTML получает идентификатор div по тексту

#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)