Парсинг защищённых сайтов

Рейтинг: 1Ответов: 1Опубликовано: 11.05.2023

Недавно мне по работе появилась необходимость парсинга объявлений авито своего города. Для этого можно использовать selenium, но по тестам он достаточно медленный, при этом синхронный, что в проекте довольно нежелательно, поэтому я бы хотел использовать внутренние api сайта.

Однако никак не могу понять почему через postman запрос проходит, а через мой код нет. Вот сам запрос:

https://www.avito.ru/web/1/main/items?forceLocation=false&locationId=653040&lastStamp=1683836667&limit=30&offset=30&categoryId=4

А вот мой код, этот запрос пытающийся сделать:

import requests


cookie = ''  # Тут должны быть куки, но они длинные и потому я их в вопросе уберу

headers = {
        "accept": "text/css,*/*;q=0.1",
        "accept-encoding": "gzip, deflate, br",
        "accept-language": "ru,en;q=0.9,ru-RU;q=0.8,en-US;q=0.7",
        "if-modified-since": "Wed, 10 May 2023 14:32:37 GMT",
        "referer": "https://www.avito.ru/",
        "sec-ch-ua": "\"Google Chrome\";v=\"113\", \"Chromium\";v=\"113\", \"Not-A.Brand\";v=\"24\"",
        "sec-ch-ua-mobile": "?0",
        "sec-ch-ua-platform": "\"Windows\"",
        "sec-fetch-dest": "style",
        "sec-fetch-mode": "no-cors",
        "sec-fetch-site": "cross-site",
        "user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 ]"
                      "(KHTML, like Gecko) Chrome/113.0.0.0 Safari/537.36",
        "x-client-data": "CJC2yQEIorbJAQipncoBCOfaygEIlqHLAQiFoM0BCIunzQEIx6rNAQ==",
        "cookie": cookie
    }


link2 = "https://www.avito.ru/web/1/main/items?forceLocation=false&locationId=653040&" \
        "lastStamp=1683748131&limit=30&offset=89&categoryId=4"


def get_page():
    session = requests.session()
    test = session.get(link2, headers=headers)

    print(test.text)


get_page()

Что я делаю не так? Подскажите, пожалуйста. Заранее просто огромнейшее спасибо!

Ответы

▲ 2Принят

Авито возвращает 403 при таком запросе. В информации пишется, что "ваш ip временно заблокирован", однако это стандартный ответ авито при неправильном запросе

Нет, это не стандартный ответ Авито при неправильном запросе…
Смотрите что он вам выдаёт:

{
    "status": "too-many-requests",
    "result": {
        "message": "Доступ с вашего IP-адреса временно ограничен",
        "link": "ru.avito://1/firewall/captcha/show"
    }
}

Ключевое слово в link — это captcha, при этом браузер никакую не запрашивает. Очень похоже на то что cloudflare делает, и про такие защиты уже отвечал тут и‥ могу с уверенностью сказать, что замечательный cloudscraper здесь работает не хуже:

import cloudscraper
s = cloudscraper.create_scraper(delay=10, browser={'custom': 'ScraperBot/1.0'})

url = 'https://www.avito.ru/web/1/main/items'
params = {
    'forceLocation': False,
    'locationId': 653040,
    'lastStamp': 1683748131,
    'limit': 30,
    'offset': 89,
    'categoryId': 4
}
r = s.get(url, params=params)
print(r)

Вывод:

<Response [200]>

Как распознать, что защита именно та, которую можно обойти данной библиотекой? Запрос занимает значительно больше времени чем в браузере, как раз из-за проверки, которая не может увенчаться успехом. При пройденной проверке запрос отрабатывает моментально.

И ещё, пожалуйста, не делайте длинные ссылки переносимые через \, параметры можно без проблем упаковывать в параметры.

Headers для успешного выполнения не потребовались, но лучше с ними, чем без них.