темный логотип proxyscrape

Руководство по селекторам HTML для веб-скрапинга

Путеводители, Скраппинг, Python, Ноябрь-08-20245 минут чтения

HTML-селекторы являются ключевым элементом веб-скреппинга, позволяя разработчикам выбирать конкретные элементы на веб-странице. Используя эти селекторы, разработчики могут точно извлекать данные.

Веб-скрепинг - это получение данных с веб-сайтов путем навигации по их HTML-структуре. HTML-селекторы играют решающую роль, позволяя вам точно определять конкретные теги, атрибуты или содержимое. Извлекайте цены на товары или заголовки, селекторы - ваш помощник.

Использование селекторов HTML эффективно оптимизирует извлечение данных и сокращает количество ошибок. Они помогают сосредоточиться на важных элементах, экономя время и силы на сбор информации из онлайн-источников.

В этом блоге мы рассмотрим, как использовать приведенные ниже селекторы с помощью Python и библиотеки"Beautifulsoup":

  • Селекторы идентификаторов
  • Селекторы классов
  • Селекторы атрибутов
  • Иерархические селекторы
  • Комбинация этих селекторов вместе

Селекторы идентификаторов

В HTML ID - это уникальные идентификаторы, присваиваемые определенным элементам, благодаря чему ни один из двух элементов не имеет одинакового ID. Эта уникальность делает селекторы ID идеальными для поиска отдельных элементов на веб-странице. Например, если вы собираете информацию с веб-страницы с несколькими разделами, каждый раздел может иметь свой собственный ID, что позволит вам извлекать данные из определенного раздела без помех.

Возьмем для примера этот сайтособенно элемент, расположенный ниже <div id="pages"> ...</div>

Этот элемент содержит другие вложенные HTML-элементы, но главное, что этот элемент уникален для данного сайта, и мы можем воспользоваться этим сценарием, например, когда хотим вырезать определенные разделы сайта. В данном случае этот элемент включает в себя несколько других статей, которые мы объясним с помощью других селекторов ниже. Вот как выглядит этот раздел на странице:

Давайте рассмотрим простой пример с использованием библиотек Python "requests" и "bs4":

import requests
from bs4 import BeautifulSoup
# Step 1: Send a GET request to the website
url = "https://www.scrapethissite.com/pages/"
response = requests.get(url)
if response.status_code == 200:
   # Step 2: Parse the HTML content with BeautifulSoup
   soup = BeautifulSoup(response.text, 'html.parser')
  
   # Step 3: Find the div with id="pages"
   pages_div = soup.find("div", id="pages")
  
   # Step 4: Display the content or handle it as needed
   if pages_div:
       print("Content of the div with id='pages':")
       print(pages_div.text.strip())
   else:
       print("No div with id='pages' found.")
else:
   print(f"Failed to retrieve the webpage. Status code: {response.status_code}")

Объяснение:

  • Отправьте запрос: Библиотека requests отправляет GET-запрос для получения HTML-содержимого с целевого URL.
  • Разбор HTML: BeautifulSoup разбирает HTML, позволяя нам искать в структуре документа.
  • Find Specific <div>: Мы используем soup.find("div", id="pages") чтобы найти <div> элемент с id="pages".
  • Содержание дисплея: Если <div> найден, мы выводим его содержимое. Если нет, то выводится сообщение о его отсутствии.

Ограничения селекторов идентификаторов:

Селекторы идентификаторов являются мощным инструментом, но имеют свои ограничения. Динамические идентификаторы, которые меняются при каждой загрузке страницы, могут затруднить последовательное извлечение данных. В таких ситуациях для получения надежных результатов может потребоваться использование альтернативных селекторов.

Селекторы классов

Селекторы классов являются гибкими, поскольку позволяют нацеливаться на группы элементов, имеющих один и тот же класс. Это делает их незаменимыми для веб-страниц с повторяющимися элементами. Например, на сайте, отображающем список товаров, каждому элементу может быть присвоен один и тот же класс.

Давайте снова рассмотрим пример с использованием этот сайт. Выше мы определили <div id="pages"> элемент с помощью ID Selector и в этом div-элементе есть несколько статей, которые имеют одинаковый класс.

Как видите, у нас есть четыре элемента с одинаковым классом <div class="page">

Вот как они выглядят на сайте:

В приведенном ниже коде мы выберем все элементы с классом "page", что вернет список, который можно использовать для дальнейшего разбора.

import requests
from bs4 import BeautifulSoup
# Step 1: Send a GET request to the website
url = "https://www.scrapethissite.com/pages/"
response = requests.get(url)
if response.status_code == 200:
   # Step 2: Parse the HTML content with BeautifulSoup
   soup = BeautifulSoup(response.text, 'html.parser')
  
   # Step 3: Find all elements with class="page"
   page_elements = soup.find_all("div", class_="page")
  
   # Step 4: Save each element's text content in a list
   pages_list = [page.text.strip() for page in page_elements]
  
   print("Content of elements with class 'page':")
   for i, page in enumerate(pages_list, start=1):
       print(f"Page {i}:")
       print(page)
       print("-" * 20)
else:
   print(f"Failed to retrieve the webpage. Status code: {response.status_code}")

Объяснение:

  • Отправить запрос: Мы используем запросы, чтобы отправить GET-запрос на URL, получая HTML-содержимое веб-страницы.
  • Разбор HTML с помощью BeautifulSoup: Если запрос прошел успешно, BeautifulSoup разбирает HTML, позволяя нам искать и взаимодействовать с элементами.
  • Найдите элементы по классу: Мы используем soup.find_all("div", class_="page") чтобы найти все <div> элементы с классом "page", возвращая их в виде списка.
  • Сохранить в список: Мы извлекаем и очищаем текстовое содержимое каждого элемента, сохраняя его в списке pages_list.

Ограничения селекторов классов

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

Селекторы атрибутов

Селекторы атрибутов позволяют нацеливать элементы на основе наличия, значения или частичного значения определенных атрибутов в HTML-тегах. Это особенно полезно, когда классы или идентификаторы не являются уникальными или когда вам нужно отфильтровать элементы с динамическими атрибутами, такими как данные-* или href значения в ссылках.

В следующем примере мы выберем все изображения на этой странице веб-страница и извлечь их исходные URL-адреса или src атрибуты. Вот как элемент выглядит в структуре html и в виде веб-страницы:

В следующем коде мы используем BeautifulSoup для разбора всех <img> элементы, извлекая их src атрибуты и сохранять их в списке.

import requests
from bs4 import BeautifulSoup
# Step 1: Send a GET request to the website
url = "https://www.scrapethissite.com/pages/frames/"
response = requests.get(url)
if response.status_code == 200:
   # Step 2: Parse the HTML content with BeautifulSoup
   soup = BeautifulSoup(response.text, 'html.parser')
  
   # Step 3: Find all <img> elements with a 'src' attribute
   image_elements = soup.find_all("img", src=True)
  
   # Step 4: Save the 'src' attributes in a list
   images_list = [img['src'] for img in image_elements]
  
   print("Image sources found on the page:")
   for i, src in enumerate(images_list, start=1):
       print(f"Image {i}: {src}")
else:
   print(f"Failed to retrieve the webpage. Status code: {response.status_code}")

Ограничения селекторов классов

Селекторы атрибутов могут выбирать только элементы со статическими атрибутами, что делает их менее эффективными для динамического контента, например элементов, загружаемых с помощью JavaScript. Они зависят от стабильной структуры HTML, поэтому частые изменения макета сайта могут нарушить их работу. Кроме того, они не могут управлять сложной фильтрацией или несколькими условиями, что ограничивает их точность. Кроме того, они могут отлавливать нежелательные элементы, если такие атрибуты, как class или name, являются общими для нескольких элементов.

Иерархические селекторы

Иерархические селекторы позволяют нацеливать HTML-элементы на основе их положения и отношения к другим элементам в структуре HTML. Такой подход особенно полезен при работе с таблицами или вложенными списками, где данные организованы в формате "родитель-ребенок".

В этом примере мы используем иерархические селекторы для извлечения данных из таблицы статистики хоккейных команд, найденной на сайте эта страница.
Таблица содержит строки <tr> представляющих каждую команду, и каждая строка содержит ячейки <td> с такой информацией, как название команды, год, победы и поражения. В каждой строке есть class="team", идентифицируя его как соответствующую запись в наших данных. Перейдя из раздела <table> to each <tr> and then to each <td>Мы можем эффективно собирать данные в структурированном виде.

Ниже вы найдете два изображения, которые помогут вам представить, где эта таблица находится в структуре HTML и как она выглядит на реальной веб-странице.

Теперь давайте посмотрим на приведенный ниже код, чтобы увидеть, как иерархические селекторы могут быть использованы для извлечения этих данных:

import requests
from bs4 import BeautifulSoup

url = "https://www.scrapethissite.com/pages/forms/"

# Step 1: Send a GET request to the website
response = requests.get(url)

if response.status_code == 200:
   # Step 2: Parse the HTML content with BeautifulSoup
   soup = BeautifulSoup(response.text, 'html.parser')
  
   # Step 3: Find all rows in the table with class="team"
   teams_data = []
   team_rows = soup.find_all("tr", class_="team")
  
   # Step 4: Extract and store each team's data
   for row in team_rows:
       team = {
           "name": row.find("td", class_="name").text.strip(),
           "year": row.find("td", class_="year").text.strip(),
           "wins": row.find("td", class_="wins").text.strip(),
           "losses": row.find("td", class_="losses").text.strip(),
           "ot_losses": row.find("td", class_="ot-losses").text.strip(),
           "win_pct": row.find("td", class_="pct").text.strip(),
           "goals_for": row.find("td", class_="gf").text.strip(),
           "goals_against": row.find("td", class_="ga").text.strip(),
           "goal_diff": row.find("td", class_="diff").text.strip(),
       }
       teams_data.append(team)
  
   # Step 5: Display the extracted data
   for team in teams_data:
       print(team)
else:
   print(f"Failed to retrieve the webpage. Status code: {response.status_code}")

Ограничения иерархических селекторов

Иерархические селекторы зависят от структуры HTML, поэтому изменения в макете могут легко нарушить работу скрипта. Они также ограничены статическим содержимым и не могут получить доступ к элементам, динамически загружаемым с помощью JavaScript. Эти селекторы часто требуют точной навигации по отношениям "родитель-ребенок", что может быть затруднительно в глубоко вложенных структурах. Кроме того, они могут быть неэффективны при извлечении разрозненных данных, так как им приходится преодолевать несколько уровней, чтобы добраться до конкретных элементов.

Использование комбинированных селекторов для улучшения таргетинга

Каждый тип селектора служит своей уникальной цели, а их сочетание позволяет нам точно ориентироваться и собирать данные из вложенного или структурированного контента. Например, селектор ID поможет найти основную область контента, селекторы классов - выделить повторяющиеся элементы, селекторы атрибутов - извлечь конкретные ссылки или изображения, а иерархические селекторы - добраться до элементов, вложенных в определенные разделы. В совокупности эти методы обеспечивают мощный подход к поиску структурированных данных.

import requests
from bs4 import BeautifulSoup
# Target URL
url = "https://www.scrapethissite.com/pages/"
response = requests.get(url)
if response.status_code == 200:
   # Step 2: Parse the HTML content with BeautifulSoup
   soup = BeautifulSoup(response.text, 'html.parser')
  
   # Use ID selector to find the main content
   main_content = soup.find(id="pages")
  
   # Use class selector to find each "page" section
   pages = main_content.find_all("div", class_="page") if main_content else []
  
   # Extract details from each "page" section using hierarchical selectors
   for page in pages:
       # Use hierarchical selector to find title link and URL within each "page"
       title_tag = page.find("h3", class_="page-title")
       title = title_tag.text.strip() if title_tag else "No Title"
       link = title_tag.find("a")["href"] if title_tag and title_tag.find("a") else "No Link"
      
       # Use class selector to find the description
       description = page.find("p", class_="lead session-desc").text.strip() if page.find("p", class_="lead session-desc") else "No Description"
      
       print(f"Title: {title}")
       print(f"Link: {link}")
       print(f"Description: {description}")
       print("-" * 40)
else:
   print(f"Failed to retrieve the webpage. Status code: {response.status_code}")

Пояснение к кодексу

  • Селектор идентификаторов: Начнем с того, что найдем область основного контента с id="pages", в которой находятся нужные нам разделы.
  • Селектор классов: Внутри этой основной области мы используем class="page" чтобы найти каждый отдельный блок контента, представляющий интересующий вас раздел.
  • Иерархические селекторы: Внутри каждого блока "страница" мы используем:
    • page.find("h3", class_="page-title") чтобы найти название.
    • title_tag.find("a")["href"] чтобы получить URL ссылки из тега якоря в заголовке.
  • Селектор атрибутов: Мы обращаемся к атрибуту href каждой ссылки, чтобы получить точные URL-адреса, связанные с каждым разделом.
  • Выходные данные: Скрипт выводит заголовок, ссылку и описание каждого раздела, давая структурированное представление о данных, соскобленных со страницы.

Заключение

При веб-скреппинге умение использовать селекторы HTML может значительно улучшить ваши навыки извлечения данных, позволяя точно собирать важную информацию. Такие селекторы, как ID, класс, атрибут и иерархический селектор, имеют специфическое применение для различных задач скрапинга. Используя эти инструменты вместе, вы сможете уверенно справляться с широким спектром задач веб-скрапинга.

Для практики на таких сайтах, как Scrape This Site и Books to Scrape, можно найти отличные примеры, которые помогут вам отточить свои навыки. А если вам нужна помощь или вы хотите пообщаться с другими людьми, интересующимися веб-скрейпингом, присоединяйтесь к нашему каналу Discord по адресу https://discord.com/invite/scrape.

Счастливого скрапбукинга!