Skip to content

Conversation

@InvisibleRain
Copy link
Contributor

@InvisibleRain InvisibleRain commented Jan 4, 2026

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

Описание

Данный патч добавляет возможность практически полностью обойти rate-limit авито при работе без прокси. Успешно протестирована продолжительная работа парсера без прокси с интервалами pause_general и pause_between_links в одну секунду.

Детали работы

Для активации обхода rate-limit требуется войти в аккаунт Авито на системе с графическим интерфейсом через скрипт prompt_user_login.py или кнопку "Войти в аккаунт Авито". После успешного входа сессия пользователя будет сохранена в файл (по умолчанию state.json), после чего будет переиспользована в запросах через Playwright, в том числе и на серверах без графического интерфейса. Был существенно переработан сетевой код. Теперь для запросов к urls и для парсинга просмотров используется Playwright вместо requests.

Дополнительные изменения

Также в патче присутствуют мелкие изменения, которые было бы трудно мержить отдельно от данного PR:

  1. Обновлена версия библиотеки flet до 0.80.1 в AvitoParser.py. Это необходимо для работы GUI на современном линуксе.
  2. Исправлен некорректный путь до Playwright на линуксе и маке в методе ensure_playwright_installed
  3. Добавлен файл .gitignore во избежание случайного добавления чувствительных файлов в гит

Тестирование

Данный патч был протестирован на десктопном Debian 13, а также в контейнере из #224. На винде протестирован в чистом venv на Python 3.13.7; Win 11 25H2. Тестирование на macos не осуществлялось.

Технический долг

На данном этапе из кода не были удалены рудиментарные функции, такие как get_cookies, load_cookies, а также функции для работы с прокси в requests. Рудиментарные функции для работы с прокси в requests предлагаю оставить т.к. они могут пригодиться в случае недоступности телеграма в РФ.

В файлах get_cookies.py, parser_cls.py и prompt_user_login.py есть повторяющийся либо крайне похожий код для работы с Playwright, в том числе с его прокси. Предлагаю вынести весь функционал связанный с Playwright в отдельный класс, и при необходимости наследовать и переопределять методы из данного класса. Это упростит поддержку кода в будущем, а также упростит добавление новых фич, связанных с Playwright.

This is intended to fix "Не удалось получить HTML" error
E.g. this will pop up a graphical browser and then ask a user for
the password to their Avito account:
import asyncio
import prompt_user_login
asyncio.run(prompt_user_login.wrapper())
The leak happens when page.goto throws an error, but
the page is not closed properly.
After adding support for the playwright client from parser_cls there's a
lot of similar code being shared between get_cookies and parser_cls. It
would be a good idea to move proxy functionality into a separate class.
Methods from the new class can then be inherited and tailored for a
specific need.
Similar code exists in prompt_user_login and should probably be moved
into a separate file
@PhotikLed
Copy link
Contributor

При запуске на Windows AvitoParser.py не открывает окна и сразу завершается с кодом 0

@InvisibleRain
Copy link
Contributor Author

@PhotikLed Гляну на днях. Скинь пока версию винды, питона и flet. Ну и плюсом, запуск parser_cls.py в консоли работает?

@PhotikLed
Copy link
Contributor

@InvisibleRain Python 3.13.7; Flet: Version: 0.80.1; Win 11 25H2

parser_cls.py при использовании state.json при инициализации AvitoParse выдает предупреждение:

2026-01-05 02:44:33.546 | WARNING | playwright_setup:ensure_playwright_installed:47 - Ошибка при установке\проверке Playwright: module 'os' has no attribute 'uname'

А так да, работает

@PhotikLed
Copy link
Contributor

Ан, нет. При запросе уже второй страницы появляется ошибка:

2026-01-05 03:03:45.579 | ERROR | main:parse:233 - При валидации объявлений произошла ошибка: 1 validation error for ItemsResponse
items
Field required [type=missing, input_value={}, input_type=dict]
For further information visit https://errors.pydantic.dev/2.9/v/missing

@PhotikLed
Copy link
Contributor

app.log
Полный лог после захода под другим ip адресом.

@PhotikLed
Copy link
Contributor

Судя по всему бан по айпи все-таки прилетает, несмотря на использование state.json. Ведь поначалу работало.

@InvisibleRain
Copy link
Contributor Author

InvisibleRain commented Jan 4, 2026

бан по айпи все-таки прилетает, несмотря на использование state.json

Через prompt_user_login.py в аккаунт Авито входил или использовал дефолтный state.json?

module 'os' has no attribute 'uname'

Похоже мой косяк, поправлю

@PhotikLed
Copy link
Contributor

Через prompt_user_login.py в аккаунт Авито входил или использовал дефолтный state.json?

Да, входил

This fixes the `module 'os' has no attribute 'uname'` error on Windows
because we don't know whether the user has logged in into an Avito
accountor is using an empty playwright state file
@InvisibleRain
Copy link
Contributor Author

InvisibleRain commented Jan 5, 2026

С последними коммитами работает на винде (25H2) без проблем с домашнего айпи. Устанавливал через PowerShell без админских прав:

Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope CurrentUser
Invoke-RestMethod -Uri https://get.scoop.sh | Invoke-Expression
scoop install git
scoop install python@3.13.7 
git clone https://github.com/InvisibleRain/parser_avito.git
cd parser_avito
git checkout origin/playwright-html-code
python -m venv venv
.\venv\Scripts\Activate.ps1
python -m pip install -r requirements.txt
python .\prompt_user_login.py #вводим логин и пароль
findstr sessid state.json # Проверяем наличие куки сессии
python .\parser_cls.py

Для наглядности прилагаю лог и скриншот:
изображение

За всё время работы пару запросов отвалилсь по таймауту, но это скорее всего баг в самом Playwright.
app.log

Raise a warning when the playwright state file doesn't contain an
account session
@Duff89
Copy link
Owner

Duff89 commented Jan 5, 2026

Привет. Хороший (пусть и большой) PR. Но т.к. еще не вернулся полноценно к работе, то нормально проверить прямо сейчас не получится, немного затянется процесс

raise requests.RequestsError(f"Слишком много запросов: {response.status}. Включите прокси либо войдите в аккаунт Авито")
elif response.status >= 500:
raise requests.RequestsError(f"Ошибка сервера: {response.status}")
self.bad_request_count += 1
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

код до счётчика не дойдет

@Duff89
Copy link
Owner

Duff89 commented Jan 15, 2026

Извините за долгое отсутствие, никак времени не хватает. Теперь к делу:
Сама идея использовать реальный аккаунт для стабильного парсинга замечательная - двумя руками за. Но!
Это явно должна быть опциональная штука, не каждый захочет это делать (а у меня к примеру и аккаунта даже нет)).
Сейчас же без входа в аккаунт (даже при наличии прокси) мы получаем стабильные 429 коды. Если же вместо state.json передать пустое значение - получим FileNotFoundError: [Errno 2] No such file or directory: '' .
Еще непонятна логика замена requests на playwright - в чём практический смысл? Те же куки могут работать и с requests же.
Мне кажется в идеале сделать примерно так:

  • к старому функционалу добавляем функцию получения cookies через логин в реальный аккаунт (уже есть в этом PR). Опция необязательная
  • делаем запросы (requests) с этим cookies. Т.к. там создается сессия - они будут обновляться если необходимо
  • Если куки реальные (а их можно отличить от инкогнито кук), то при получении 429 кода прислать уведомление пользователю в ТГ, что его куки протухли и нужно было бы опять зайти в аккаунт
  • Продолжить работу без реальных авторизационных кук, а с тем что есть (как было раньше)
    В таком варианте пользователь сам решает, что ему лучше: работать с прокси и без авторизации или сэкономить, но авторизоваться.

Давайте в общем обсуждать

Fallback to using a Windows path to make sure ms_playwright_dir is initialized
@InvisibleRain
Copy link
Contributor Author

Еще непонятна логика замена requests на playwright - в чём практический смысл?

Причины его использования вместо requests ровно две. Первая - возможность использовать и обновлять Playwright state file без предварительной конвертации в кастомный формат для requests. Вторая - возможность использовать playwright-stealth, что в теории позволит работать даже без аккаунта. На днях посмотрю как он будет работать на практике.

Если куки реальные (а их можно отличить от инкогнито кук), то при получении 429 кода прислать уведомление пользователю в ТГ, что его куки протухли и нужно было бы опять зайти в аккаунт

Тут не уверен, что это действительно необходимо. Сессия с аккаунтом может протухнуть в двух случаях:

  1. Если пользователь завершил сессию через вкладку "Защита профиля" на Авито.
  2. Если сессия ни разу не использовалась в течении года (!), от чего истекла кука sessid

В первом случае пользователь и так знает, что сессия была отозвана, а во втором случае при запуске парсер выдаст ошибку 429.

Протестировать работу с прокси, к сожалению, нет возможности т.к. у меня нет аккаунта на mobileproxy. Очень помог бы лог работы данного патча через прокси.

Недосягаемый код и некоторые другие ошибки Pylint исправил. Также playwright_state_file = "" теперь воспринимается парсером как отключённый и больше не выдаёт ошибку.

@Duff89
Copy link
Owner

Duff89 commented Jan 20, 2026

что в теории позволит работать даже без аккаунта

Не будет так работать. Точнее будет, но не долго.

Причины остаться на запросах, а не переходить на playwright

  1. Они уже есть и работают. Обращаю внимание, что используется не обычный requets, а curl_cff - по сути stealth вариант
  2. Меньше ресурсов требует
  3. В дальнейшем в парсер будут внесены изменения (они еще в разработке), которые потребуют запросов и поэтому получится, что нужно опять возвращаться на запросы или делать уже 2 реализации, что явно лишнее.

PS: Если нужен мобильный прокси для тестов - оставь здесь почту, дам на пару дней

@InvisibleRain
Copy link
Contributor Author

InvisibleRain commented Jan 20, 2026

Ок, тогда как время будет - напишу логику для использования playwright state file в requests и откачу на него логику запросов. В целом даже если смотреть в будущем в сторону решателей капчи вроде https://github.com/xKiian/GeekedTest - playwright всё равно не понадобится.

Гугломыло - manzhos.va

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants