Skip to content

Conversation

@InvisibleRain
Copy link

@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

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

@InvisibleRain
Copy link
Author

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

@PhotikLed
Copy link

@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

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

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

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

@PhotikLed
Copy link

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

@InvisibleRain
Copy link
Author

InvisibleRain commented Jan 4, 2026

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

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

module 'os' has no attribute 'uname'

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

@PhotikLed
Copy link

Через 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
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 кода прислать уведомление пользователю в ТГ, что его куки протухли и нужно было бы опять зайти в аккаунт
  • Продолжить работу без реальных авторизационных кук, а с тем что есть (как было раньше)
    В таком варианте пользователь сам решает, что ему лучше: работать с прокси и без авторизации или сэкономить, но авторизоваться.

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

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