Scarnox · Blog

Як уникати капчі під час скрапінгу (без порушення правил)

Більшість капч під час скрапінгу — це реакція на трафік, який виглядає автоматизованим. Найдешевший спосіб з ними впоратися — перестати їх провокувати. Для цього спершу шукайте легітимне джерело даних, перевіряйте, що дозволяють правила сайту, надсилайте менше запитів і повільніше, та не завантажуйте одну сторінку двічі. Розв'язання капчі — запасний варіант для випадків, яких не вдається уникнути, а не основний план.

Спершу перевірте наявність офіційного API або стрічки

Багато сайтів, які скрапають, уже пропонують спосіб отримати ті самі дані без капчі: публічний API, експорт даних, RSS- або sitemap-стрічку чи партнерську програму. Офіційне джерело надійніше, рідше змінюється без попередження і дає власнику сайту контроль над тим, як ним користуються. Шукайте:

Якщо один із цих варіантів покриває вашу потребу, користуйтеся ним. Ви уникнете більшості капч, просто не запитуючи HTML.

Дотримуйтесь robots.txt і затримки, яку він просить

robots.txt показує, які шляхи дозволено завантажувати автоматизованим клієнтам і, інколи, скільки чекати між запитами. Стандартна бібліотека Python може прочитати його за вас:

import time
from urllib.robotparser import RobotFileParser
import requests

USER_AGENT = "ExampleBot/1.0 (+https://example.com/bot)"

parser = RobotFileParser()
parser.set_url("https://example.com/robots.txt")
parser.read()

delay = parser.crawl_delay(USER_AGENT) or 5  # запасний варіант: обережні 5 секунд
urls = [
    "https://example.com/products?page=1",
    "https://example.com/products?page=2",
]

last_request = 0.0
for url in urls:
    if not parser.can_fetch(USER_AGENT, url):
        print("skipped by robots.txt:", url)
        continue
    wait = delay - (time.monotonic() - last_request)
    if wait > 0:
        time.sleep(wait)
    resp = requests.get(url, headers={"User-Agent": USER_AGENT}, timeout=30)
    last_request = time.monotonic()
    print(url, resp.status_code)

Якщо robots.txt забороняє шлях, чесна відповідь — не чіпати його або спитати власника. Обхід через браузер не змінює того, що просив сайт.

Сповільнюйте і розподіляйте запити

Стабільний, помірний темп рідко провокує виклик, а сплеск майже завжди провокує. Кілька звичок дають велику різницю:

Кешуйте і не завантажуйте повторно

Кожен запит, який ви не надсилаєте, — це запит, який сайт не мусить обробляти. Зберігайте сторінки, які завантажили, з датою і хешем вмісту, і завантажуйте їх знову лише тоді, коли вміст, імовірно, змінився. Умовні запити з заголовками If-Modified-Since або ETag дозволяють серверу дешево відповісти «не змінилося», якщо він це підтримує.

Повторно використовуйте сесії і надсилайте звичайні заголовки

Сесія, яка зберігає cookie між запитами, поводиться більше як відвідувач, ніж скрипт, що стартує з нуля щоразу. Використовуйте requests.Session() для кожного сайту і надсилайте чесний, зрозумілий User-Agent з назвою вашого бота та контактом. Не маскуйтеся під браузер, щоб обійти правило. Якщо сайту для показу вмісту потрібен JavaScript, використовуйте інструмент браузера для таких сторінок і дотримуйтесь тих самих лімітів частоти.

Коли капча все одно з'являється

Деякі сайти показуватимуть капчу, незалежно від того, наскільки обережно ви поводитеся. Визначте її в коді і зупиніть це завдання, а не долбіть сторінку. Виявлення і необов'язкове розв'язання для PopularCaptcha описані в посібнику про капчу при веб-скрапінгу.

Сплануйте обхід до початку

Обхід, який щодня завантажує все, — найпростіший спосіб спровокувати капчу. Спершу сплануйте роботу:

Такий план зменшує кількість запитів, а це найбільший важіль, який у вас є.

Запишіть план у короткий конфігураційний файл або таблицю: сайти, розділи, інтервал оновлення і денний бюджет запитів для кожного. Коли бюджет вичерпано, завдання зупиняється до наступного вікна. Сприймати бюджет як жорсткий ліміт, а не орієнтир, — це те, що не дає скраперу зсунутися до патерну трафіку, який і провокує капчу. Переглядайте бюджет кожні кілька тижнів, бо сайт, що зростає, може також збільшити трафік, і те, що було ввічливим минулого кварталу, зараз може таким не бути.

Scrape responsibly

Наступні кроки