Добавить в корзинуПозвонить
Найти в Дзене
RuMicro

Парсинг сайтов на Python

bash pip install requests beautifulsoup4 selenium scrapy lxml python import requests
from bs4 import BeautifulSoup
import time
# Базовый парсинг с заголовками
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36'
}
try:
response = requests.get('https://example.com', headers=headers, timeout=10)
response.raise_for_status() # Проверка на ошибки
soup = BeautifulSoup(response.text, 'html.parser')
# Поиск элементов
titles = soup.find_all('h1')
links = soup.find_all('a', class_='some-class')
text = soup.find('div', id='content').text.strip()
# CSS селекторы
items = soup.select('.item-class')
except requests.exceptions.RequestException as e:
print(f'Ошибка запроса: {e}') python from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdrive
Оглавление

1. Необходимые библиотеки

bash

pip install requests beautifulsoup4 selenium scrapy lxml

2. Простой парсинг с requests + BeautifulSoup

python

import requests
from bs4 import BeautifulSoup
import time

# Базовый парсинг с заголовками
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36'
}

try:
response = requests.get('https://example.com', headers=headers, timeout=10)
response.raise_for_status() # Проверка на ошибки

soup = BeautifulSoup(response.text, 'html.parser')

# Поиск элементов
titles = soup.find_all('h1')
links = soup.find_all('a', class_='some-class')
text = soup.find('div', id='content').text.strip()

# CSS селекторы
items = soup.select('.item-class')

except requests.exceptions.RequestException as e:
print(f'Ошибка запроса: {e}')

3. Работа с динамическим контентом (Selenium)

python

from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.chrome.options import Options

# Настройка headless режима
chrome_options = Options()
chrome_options.add_argument('--headless')
chrome_options.add_argument('--no-sandbox')
chrome_options.add_argument('--disable-dev-shm-usage')

driver = webdriver.Chrome(options=chrome_options)

try:
driver.get('https://example.com')

# Ожидание загрузки элемента
element = WebDriverWait(driver, 10).until(
EC.presence_of_element_located((By.CLASS_NAME, "content"))
)

# Клик по кнопке
button = driver.find_element(By.ID, "load-more")
button.click()

# Парсинг динамического контента
items = driver.find_elements(By.CSS_SELECTOR, ".item")
for item in items:
title = item.find_element(By.TAG_NAME, "h2").text
print(title)

finally:
driver.quit()

4. Полный пример парсинга новостей

python

import requests
from bs4 import BeautifulSoup
import csv
import time
from urllib.parse import urljoin

class NewsParser:
def __init__(self, base_url):
self.base_url = base_url
self.headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36'
}

def parse_article(self, url):
"""Парсинг отдельной статьи"""
try:
response = requests.get(url, headers=self.headers, timeout=10)
soup = BeautifulSoup(response.text, 'html.parser')

title = soup.find('h1').text.strip()
content = soup.find('div', class_='article-content').text.strip()
date = soup.find('time', class_='date').text.strip()

return {
'title': title,
'content': content,
'date': date,
'url': url
}
except Exception as e:
print(f'Ошибка при парсинге {url}: {e}')
return None

def parse_listing(self, page=1):
"""Парсинг списка статей"""
url = f'{self.base_url}/page/{page}'
try:
response = requests.get(url, headers=self.headers)
soup = BeautifulSoup(response.text, 'html.parser')

articles = []
for link in soup.select('.article-link'):
article_url = urljoin(self.base_url, link.get('href'))
articles.append(article_url)

return articles
except Exception as e:
print(f'Ошибка при парсинге списка: {e}')
return []

def save_to_csv(self, data, filename='articles.csv'):
"""Сохранение данных в CSV"""
keys = data[0].keys() if data else []
with open(filename, 'w', newline='', encoding='utf-8') as f:
writer = csv.DictWriter(f, fieldnames=keys)
writer.writeheader()
writer.writerows(data)

# Использование
parser = NewsParser('https://example-news.com')
all_articles = []

for page in range(1, 4): # Парсинг 3 страниц
print(f'Парсинг страницы {page}...')
articles_urls = parser.parse_listing(page)

for url in articles_urls:
print(f'Парсинг: {url}')
article_data = parser.parse_article(url)
if article_data:
all_articles.append(article_data)
time.sleep(1) # Задержка между запросами

time.sleep(2) # Задержка между страницами

# Сохранение результатов
parser.save_to_csv(all_articles)
print(f'Сохранено {len(all_articles)} статей')

5. Продвинутый парсинг с пагинацией и прокси

python

import requests
from bs4 import BeautifulSoup
import random
import time
from fake_useragent import UserAgent

class AdvancedParser:
def __init__(self):
self.session = requests.Session()
self.ua = UserAgent()
self.proxies = [
'http://proxy1:port',
'http://proxy2:port',
]

def get_random_headers(self):
return {
'User-Agent': self.ua.random,
'Accept-Language': 'ru-RU,ru;q=0.9,en-US;q=0.8,en;q=0.7',
'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8',
'Referer': 'https://www.google.com/',
}

def make_request(self, url, retries=3):
for attempt in range(retries):
try:
proxy = {'http': random.choice(self.proxies)} if self.proxies else None
response = self.session.get(
url,
headers=self.get_random_headers(),
proxies=proxy,
timeout=15
)
response.raise_for_status()
return response
except Exception as e:
print(f'Попытка {attempt + 1} не удалась: {e}')
if attempt < retries - 1:
time.sleep(2 ** attempt) # Экспоненциальная задержка
return None

def parse_with_pagination(self, base_url, max_pages=10):
all_data = []

for page in range(1, max_pages + 1):
url = f'{base_url}?page={page}'
print(f'Парсинг страницы {page}...')

response = self.make_request(url)
if not response:
break

soup = BeautifulSoup(response.text, 'html.parser')

# Проверка на последнюю страницу
if not soup.find_all('div', class_='item'):
break

# Парсинг данных страницы
page_data = self.parse_page(soup)
all_data.extend(page_data)

# Случайная задержка между запросами
time.sleep(random.uniform(1, 3))

return all_data

def parse_page(self, soup):
data = []
# Ваша логика парсинга страницы
return data

6. Использование Scrapy (фреймворк)

python

# items.py
import scrapy

class ArticleItem(scrapy.Item):
title = scrapy.Field()
content = scrapy.Field()
url = scrapy.Field()
date = scrapy.Field()

# spiders/news_spider.py
import scrapy
from ..items import ArticleItem

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

def parse(self, response):
for article in response.css('div.article'):
item = ArticleItem()
item['title'] = article.css('h2::text').get()
item['url'] = article.css('a::attr(href)').get()
item['date'] = article.css('span.date::text').get()

yield response.follow(item['url'], self.parse_article, meta={'item': item})

# Пагинация
next_page = response.css('a.next::attr(href)').get()
if next_page:
yield response.follow(next_page, self.parse)

def parse_article(self, response):
item = response.meta['item']
item['content'] = response.css('div.content::text').get()
yield item

7. Обработка ошибок и best practices

python

import logging
import time
from functools import wraps

def retry(max_attempts=3, delay=1):
"""Декоратор для повторных попыток"""
def decorator(func):
@wraps(func)
def wrapper(*args, **kwargs):
for attempt in range(max_attempts):
try:
return func(*args, **kwargs)
except Exception as e:
if attempt == max_attempts - 1:
raise
logging.warning(f'Попытка {attempt + 1} не удалась: {e}')
time.sleep(delay * (2 ** attempt))
return None
return wrapper
return decorator

class SafeParser:
def __init__(self):
logging.basicConfig(level=logging.INFO)

@retry(max_attempts=3)
def safe_request(self, url):
response = requests.get(url, timeout=10)
response.raise_for_status()
return response

def safe_extract(self, soup, selector, default=''):
try:
element = soup.select_one(selector)
return element.text.strip() if element else default
except Exception as e:
logging.error(f'Ошибка при извлечении {selector}: {e}')
return default

Важные советы:

  1. Соблюдайте robots.txt - проверяйте разрешения на парсинг
  2. Добавляйте задержки между запросами (time.sleep)
  3. Используйте User-Agent для имитации браузера
  4. Обрабатывайте исключения для устойчивости
  5. Сохраняйте промежуточные результаты для отладки
  6. Учитывайте изменения структуры сайта - используйте CSS селекторы
  7. Применяйте многопоточность с осторожностью для массового парсинга

Выберите подход в зависимости от ваших задач: BeautifulSoup для статичных сайтов, Selenium для динамических, Scrapy для масштабных проектов.