Парсинг Python: библиотеки, техники, примеры
Основные подходы к парсингу в Python
Как получить HTML страницы и извлечь из него данные?
Наиболее распространенное и эффективное решение для статических сайтов - связка библиотек requests и BeautifulSoup. Она позволяет выполнить HTTP-запрос, получить HTML и разобрать его с помощью удобного API.
import requests
from bs4 import BeautifulSoup
url = 'https://example.com/news'
response = requests.get(url)
soup = BeautifulSoup(response.text, 'html.parser')
for item in soup.select('.news-item'):
title = item.find('h2').text.strip()
print(title)парсинг python (парсинг в python)
Пояснение шагов:
- Библиотека requests отправляет GET-запрос к странице.
- Ответ преобразуется в объект BeautifulSoup с указанием парсера (html.parser).
- Метод select() использует CSS-селекторы для поиска блоков с классом .news-item.
- Для каждого блока извлекается текст заголовка.
- Ошибка HTTP 403 - сайт блокирует запросы без заголовков. Решение: добавить заголовок User-Agent.
- Пустой результат при парсинге - возможно, контент загружается через JavaScript. В таком случае требуется Selenium.
- Кодировка: текст отображается кракозябрами. Решение: установить правильную кодировку через response.encoding или использовать response.content.
Как выполнить парсинг быстрее с помощью lxml?
Если сайт имеет сложную структуру или требуется высокая скорость, вместо BeautifulSoup можно использовать парсер lxml. Он работает намного быстрее и поддерживает XPath.
from lxml import html
import requests
response = requests.get('https://example.com')
tree = html.fromstring(response.content)
titles = tree.xpath('//h2[@class="title"]/text()')
print(titles)Библиотека lxml часто применяется в связке с requests, когда нужна производительность или сложные запросы по XPath.
Как собирать данные с множества страниц (краулинг)?
Для масштабного сбора данных удобен фреймворк Scrapy. Он управляет очередью запросов, обрабатывает пагинацию и сохраняет результаты.
import scrapy
class BlogSpider(scrapy.Spider):
name = 'blog'
start_urls = ['https://blog.example.com']
def parse(self, response):
for post in response.css('article.post'):
yield {
'title': post.css('h2::text').get(),
'link': post.css('a::attr(href)').get()
}
next_page = response.css('a.next::attr(href)').get()
if next_page:
yield response.follow(next_page, self.parse)Scrapy автоматически обрабатывает задержки, повторные запросы и экспорт данных в JSON или CSV.
Как парсить сайты с динамической подгрузкой контента (JavaScript)?
Если данные появляются после выполнения скриптов, необходим браузерный движок Selenium. Он управляет реальным браузером.
from selenium import webdriver
from selenium.webdriver.common.by import By
driver = webdriver.Chrome()
driver.get('https://example.com/tweets')
tweets = driver.find_elements(By.CLASS_NAME, 'tweet-text')
for tweet in tweets:
print(tweet.text)
driver.quit()Также можно использовать Playwright или Puppeteer (через pyppeteer).
Как выполнять асинхронный парсинг для ускорения?
Для одновременных запросов к нескольким страницам применяется aiohttp с BeautifulSoup или lxml.
import aiohttp
import asyncio
from bs4 import BeautifulSoup
async def fetch(session, url):
async with session.get(url) as response:
return await response.text()
async def main():
urls = ['https://example.com/page1', 'https://example.com/page2']
async with aiohttp.ClientSession() as session:
tasks = [fetch(session, url) for url in urls]
pages = await asyncio.gather(*tasks)
for page in pages:
soup = BeautifulSoup(page, 'html.parser')
print(soup.title.text)
asyncio.run(main())Асинхронный подход сильно ускоряет сбор данных при большом количестве страниц.
Расширенные примеры парсинга в Python
Парсинг с пагинацией (постраничный обход)
Часто данные распределены по нескольким страницам. Ниже показан пример с использованием requests и BeautifulSoup, где извлекаются ссылки на страницы и выполняется обход.
import requests
from bs4 import BeautifulSoup
from urllib.parse import urljoin
def scrape_category(base_url):
page = 1
while True:
url = f"{base_url}?page={page}"
response = requests.get(url)
if response.status_code != 200:
break
soup = BeautifulSoup(response.text, 'html.parser')
products = soup.select('.product-item')
if not products:
break
for product in products:
name = product.find('h3').text.strip()
price = product.find('.price').text.strip()
print(f"{name}: {price}")
page += 1
scrape_category('https://shop.example.com/category')Товар 1: 1000 руб. Товар 2: 1500 руб. ...
Пояснение: функция увеличивает номер страницы до тех пор, пока не получит пустой ответ или код 404. Для относительных ссылок используется urljoin.
Извлечение данных из таблиц с помощью pandas
Библиотека pandas предоставляет метод read_html, который автоматически находит таблицы в HTML.
import pandas as pd
tables = pd.read_html('https://en.wikipedia.org/wiki/List_of_countries_by_population')
df = tables[0] # первая таблица на странице
print(df.head())Rank Country Population 0 1 China 1400000000 1 2 India 1380000000 ...
Этот подход удобен для быстрого получения структурированных данных без ручного обхода DOM.
Парсинг API сайта (JSON)
Многие сайты отдают данные через внутренние API. Найти вызовы можно в инструментах разработчика (Network).
import requests
url = 'https://api.example.com/products?limit=10'
headers = {'User-Agent': 'Mozilla/5.0'}
response = requests.get(url, headers=headers)
data = response.json()
for item in data['products']:
print(item['name'], item['price'])Товар A 500 Товар B 750 ...
Изучение сетевых запросов помогает обойти сложный HTML и получить данные напрямую в JSON.
Обработка контента, загружаемого по скроллу (infinite scroll)
Для имитации скролла в Selenium можно выполнить JavaScript.
from selenium import webdriver
from selenium.webdriver.common.by import By
import time
driver = webdriver.Chrome()
driver.get('https://example.com/infinite-scroll')
last_height = driver.execute_script('return document.body.scrollHeight')
while True:
driver.execute_script('window.scrollTo(0, document.body.scrollHeight)')
time.sleep(3)
new_height = driver.execute_script('return document.body.scrollHeight')
if new_height == last_height:
break
last_height = new_height
items = driver.find_elements(By.CLASS_NAME, 'item')
print(len(items))
driver.quit()42
Цикл прокручивает страницу до тех пор, пока высота не перестанет расти, и собирает все элементы.
Парсинг с авторизацией (сессии)
Для закрытых разделов используется сохранение сессии через requests.Session.
import requests
session = requests.Session()
login_url = 'https://example.com/login'
payload = {'username': 'user', 'password': 'pass'}
session.post(login_url, data=payload)
profile = session.get('https://example.com/profile')
soup = BeautifulSoup(profile.text, 'html.parser')
print(soup.find('h1').text)Личный кабинет пользователя
Объект Session автоматически хранит cookies и отправляет их при последующих запросах.