Python для извлечения данных из интернета

Раздел: Python -> Сбор данных из интернета

Обзор способов получения данных с веб-сайтов

Как получить статическую веб-страницу и извлечь из неё данные с помощью Python?

Базовое решение: библиотеки requests и BeautifulSoup

Этот подход подходит для сайтов, где весь контент отдаётся в исходном HTML без динамической подгрузки через JavaScript. Цель - быстро и просто спарсить страницу.

import requests
from bs4 import BeautifulSoup

url = 'https://example.com'
response = requests.get(url)
soup = BeautifulSoup(response.text, 'html.parser')
title = soup.find('h1').text
print(title)

Python данные с сайта (получение данных с веб-сайта на python)

Example Domain

Сначала отправляется GET-запрос с помощью requests.get(). Затем полученный HTML передаётся в BeautifulSoup для парсинга. Можно искать элементы по тегам, классам, id.

Типичные проблемы:

  • Ошибка 403 (доступ запрещён) - добавляйте заголовок User-Agent.
  • Кодировка текста - используйте response.encoding = 'utf-8' или определите автоматически.
  • Сайт блокирует частые запросы - добавьте задержки time.sleep().

Как извлечь данные с сайта, который динамически загружает контент с помощью JavaScript?

Вариант: Selenium WebDriver

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

from selenium import webdriver
from selenium.webdriver.chrome.options import Options

options = Options()
options.headless = True
driver = webdriver.Chrome(options=options)
driver.get('https://example.com')
source = driver.page_source
driver.quit()

soup = BeautifulSoup(source, 'html.parser')
print(soup.find('h1').text)
Example Domain

Запускается драйвер в фоновом режиме (headless). После загрузки страницы извлекается её HTML через page_source. Далее парсится с BeautifulSoup.

Возможные сложности:

  • Необходимость установки драйвера (chromedriver) и соответствие версии браузера.
  • Медленная работа по сравнению с прямыми запросами.
  • Потребление памяти. Для снижения нагрузки используйте headless-режим.

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

Вариант: асинхронный парсинг с aiohttp и asyncio

Если нужно обработать десятки или сотни URL, последовательные запросы будут медленными. Асинхронный подход позволяет отправлять запросы параллельно. Цель - сократить время сбора.

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 html in pages:
            soup = BeautifulSoup(html, 'html.parser')
            print(soup.find('h1').text if soup.find('h1') else 'No h1')

asyncio.run(main())

Создаётся сессия aiohttp.ClientSession, для каждого URL формируется задача на скачивание. asyncio.gather запускает их одновременно. Результаты обрабатываются после завершения всех запросов.

Проблемы и решения:

  • Сайт может не выдержать пиковой нагрузки - ограничьте количество одновременных запросов через семафор.
  • Ошибки соединения - обрабатывайте исключения в каждой задаче.
  • Не все библиотеки поддерживают асинхронность (BeautifulSoup работает синхронно, но это не критично).
Как организовать масштабный сбор данных с паутиной ссылок и обработкой ошибок?

Вариант: фреймворк Scrapy

Для серьёзных проектов с тысячами страниц, следованием по ссылкам, автоматической обработкой дубликатов и паузами лучше использовать специализированный инструмент. Цель - промышленный парсинг.

# spider.py
import scrapy

class MySpider(scrapy.Spider):
    name = 'example'
    start_urls = ['https://example.com']

    def parse(self, response):
        # Извлечение данных
        yield {
            'title': response.css('h1::text').get(),
            'url': response.url
        }
        # Следование по ссылкам
        for link in response.css('a::attr(href)'):
            yield response.follow(link, self.parse)

Запуск: scrapy runspider spider.py -o output.json. Фреймворк сам управляет запросами, обрабатывает ошибки, поддерживает паузы и прокси.

Сложности при использовании Scrapy:

  • Кривая обучения - нужно понять архитектуру пауков и конвейеров.
  • Избыточен для простых одноразовых задач.
  • Требует настройки обработчиков для JavaScript (Splash или Selenium).

Расширенные примеры сбора данных

Пример 1: Парсинг с защитой от блокировок (User-Agent, прокси, сессия)

Пример
import requests
from bs4 import BeautifulSoup

headers = {
    'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36',
    'Accept': 'text/html,application/xhtml+xml,*/*'
}
proxies = {
    'http': 'http://user:pass@proxy:8080',
    'https': 'http://user:pass@proxy:8080'
}
session = requests.Session()
session.headers.update(headers)
session.proxies.update(proxies)

response = session.get('https://httpbin.org/headers')
soup = BeautifulSoup(response.text, 'html.parser')
print(soup.prettify())
{
  "headers": {
    "Accept": "*/*",
    "User-Agent": "Mozilla/5.0 ..."
  }
}

Пример 2: Извлечение данных из API сайта вместо HTML

Многие сайты предоставляют JSON-эндпоинты, которые проще парсить, чем HTML.

Пример
import requests
import json

url_api = 'https://api.github.com/repos/psf/requests'
response = requests.get(url_api)
data = response.json()
print(f"Stars: {data['stargazers_count']}")
print(f"Forks: {data['forks_count']}")
Stars: 51000
Forks: 9500

Пример 3: Асинхронный парсинг с ограничением конкурентности и обработкой ошибок

Пример
import aiohttp
import asyncio
from bs4 import BeautifulSoup

async def fetch_with_limit(sem, session, url):
    async with sem:
        try:
            async with session.get(url, timeout=10) as response:
                return await response.text()
        except Exception as e:
            print(f"Ошибка {url}: {e}")
            return None

async def main():
    urls = [f'https://httpbin.org/delay/{i}' for i in range(1, 6)]
    sem = asyncio.Semaphore(3)  # не более 3 одновременных запросов
    async with aiohttp.ClientSession() as session:
        tasks = [fetch_with_limit(sem, session, url) for url in urls]
        results = await asyncio.gather(*tasks)
        for url, html in zip(urls, results):
            if html:
                soup = BeautifulSoup(html, 'html.parser')
                print(f"{url}: длина HTML = {len(html)}")

asyncio.run(main())
https://httpbin.org/delay/1: длина HTML = 1200
https://httpbin.org/delay/2: длина HTML = 1200
https://httpbin.org/delay/3: длина HTML = 1200
https://httpbin.org/delay/4: длина HTML = 1200
https://httpbin.org/delay/5: длина HTML = 1200

Пример 4: Обработка форм и сессий с Selenium (логин, cookie)

Пример
from selenium import webdriver
from selenium.webdriver.common.by import By

driver = webdriver.Chrome()
driver.get('https://example.com/login')
driver.find_element(By.NAME, 'username').send_keys('user')
driver.find_element(By.NAME, 'password').send_keys('pass')
driver.find_element(By.XPATH, '//button[@type="submit"]').click()

# После логина cookie сохранятся в сессии driver
driver.get('https://example.com/protected')
print(driver.find_element(By.TAG_NAME, 'h1').text)
driver.quit()
Welcome, user!

Пример 5: Использование Scrapy с паутиной и конвейером для обработки данных

Пример
import scrapy

class BlogSpider(scrapy.Spider):
    name = 'blog'
    start_urls = ['https://scrapy.org/blog/']

    def parse(self, response):
        for article in response.css('div.article'):
            yield {
                'title': article.css('h2::text').get(),
                'link': article.css('a::attr(href)').get(),
            }
        next_page = response.css('a.next::attr(href)').get()
        if next_page:
            yield scrapy.Request(response.urljoin(next_page))
(консольный вывод Scrapy с собранными элементами)

После запуска scrapy runspider blog_spider.py -o articles.json все данные сохранятся в JSON.

Получение данных с веб-сайта на Python - comments

En
Python данные с сайта (python)