Парсинг 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)

Пояснение шагов:

  1. Библиотека requests отправляет GET-запрос к странице.
  2. Ответ преобразуется в объект BeautifulSoup с указанием парсера (html.parser).
  3. Метод select() использует CSS-селекторы для поиска блоков с классом .news-item.
  4. Для каждого блока извлекается текст заголовка.
Типичные ошибки:
  • Ошибка 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.

Проблема: установка lxml может требовать компиляции на Windows. Решение: использовать предварительно собранные колёса (wheel) через pip install lxml.

Как собирать данные с множества страниц (краулинг)?

Для масштабного сбора данных удобен фреймворк 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.

Ошибка: сайт блокирует частые запросы. Решение: настроить DOWNLOAD_DELAY и использовать ротацию User-Agent через промежуточное ПО.

Как парсить сайты с динамической подгрузкой контента (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).

Проблема: Selenium медленный, требует установленного браузера. Решение: использовать headless-режим и оптимизировать ожидание элементов (explicit waits).

Как выполнять асинхронный парсинг для ускорения?

Для одновременных запросов к нескольким страницам применяется 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 и отправляет их при последующих запросах.

Парсинг в Python - comments

En
парсинг python (python)