Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
44 commits
Select commit Hold shift + click to select a range
c158978
Use Playwright for the very first request
InvisibleRain Dec 31, 2025
3730d4a
Revert "Use Playwright for the very first request"
InvisibleRain Jan 1, 2026
42443f2
Actually use playwright to obtain html_code
InvisibleRain Jan 1, 2026
fa96081
Update .gitignore
InvisibleRain Jan 1, 2026
960f082
Use different default Playwright paths on different platforms
InvisibleRain Jan 1, 2026
1f6b1f2
Fix ensure_playwright_installed reporting everything is ok after `pla…
InvisibleRain Jan 2, 2026
23391d8
Add a function to save authenticated Plawright session to a file
InvisibleRain Jan 2, 2026
b402dd0
Load playwright state filepath from config.toml
InvisibleRain Jan 2, 2026
8269d77
Allow to run `python prompt_user_login.py`
InvisibleRain Jan 2, 2026
b9d68b4
Save playwright state file to the filepath from config.toml
InvisibleRain Jan 2, 2026
caf0c2a
Only allow the current user to access playwright state file to protec…
InvisibleRain Jan 2, 2026
da38d59
Fix a memeory leak and improve exception handling
InvisibleRain Jan 2, 2026
9b4dc4e
typo
InvisibleRain Jan 2, 2026
9a07a7c
Move get_html() to parser_cls to avoid spaghetti code
InvisibleRain Jan 2, 2026
24f56b1
Remove unnecessary config parsing
InvisibleRain Jan 3, 2026
5bde40e
FIXME: add proxy support for get_html
InvisibleRain Jan 3, 2026
7a60145
Remove unused dependencies and comments
InvisibleRain Jan 3, 2026
546b803
Remove the unused stop_event parameter
InvisibleRain Jan 3, 2026
ba2ca50
Use playwright for parsing views
InvisibleRain Jan 3, 2026
286e3f7
FIXME: save playwright context containing browser after each request
InvisibleRain Jan 3, 2026
d58abda
Add instructions on using prompt_user_login.py to readme
InvisibleRain Jan 3, 2026
05fb7fe
Don't try to save playwright state file after a failed request
InvisibleRain Jan 3, 2026
5587235
Add a default state.json
InvisibleRain Jan 3, 2026
1523de5
Make sure playwright_state_file is configured before trying to save it
InvisibleRain Jan 3, 2026
100205a
Use string interpolation instead of string concatenation to avoid typ…
InvisibleRain Jan 3, 2026
142b2ed
Add http status code handling to get_html
InvisibleRain Jan 3, 2026
fa14b1a
Update flet to 0.80.1 so the parser can run on modern Linux
InvisibleRain Jan 3, 2026
74ac468
Unambigiously refer to self.config
InvisibleRain Jan 4, 2026
e2a3e96
Add helper in gui for playwright state_file
InvisibleRain Jan 4, 2026
6026550
Add GUI for configuring Playwright State file
InvisibleRain Jan 3, 2026
8f4a0b1
Add a button to login into an Avito account to the GUI
InvisibleRain Jan 4, 2026
1fc317f
Fix a typo that caused the parsing to fail
InvisibleRain Jan 4, 2026
3724c1c
Reccomend to either log in or enable proxy in error messages
InvisibleRain Jan 4, 2026
8c818b7
Add help message for prompt_user_login in GUI
InvisibleRain Jan 4, 2026
c95304b
Use ft.run instead of ft.app
InvisibleRain Jan 4, 2026
a85abc1
Fix ui visibility not changing after start_btn is clicked
InvisibleRain Jan 4, 2026
520d8ce
Use a platform-independent way to check the user OS
InvisibleRain Jan 5, 2026
0fdf6e7
Use a more ambigous log message when saving playwright state
InvisibleRain Jan 5, 2026
fe1f419
Excplicitly update flet-desktop for users upgrading wheels from older…
InvisibleRain Jan 5, 2026
5a58353
Verify that we are logged in into an Avito account
InvisibleRain Jan 5, 2026
bd9c1b3
Fix unreachable code
InvisibleRain Jan 20, 2026
c0650dc
Fix Pylint error
InvisibleRain Jan 20, 2026
94aef84
Improve comment
InvisibleRain Jan 21, 2026
6cc9964
Treat `playwright_state_file=""` as the state file being disabled
InvisibleRain Jan 21, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 10 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,2 +1,11 @@
# created by virtualenv automatically
.secret.txt
result
logs
config.toml
cookies.json
state.json
venv
__pycache__
*.bak
database.db
december.txt
39 changes: 27 additions & 12 deletions AvitoParser.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import threading
import time
from pathlib import Path
import prompt_user_login

import flet as ft
import tkinter as tk
Expand Down Expand Up @@ -76,6 +77,7 @@ def set_up():
parse_views.value = config.parse_views
save_xlsx.value = config.save_xlsx
use_webdriver.value = config.use_webdriver
playwright_state_file.value = config.playwright_state_file

page.update()

Expand Down Expand Up @@ -111,6 +113,7 @@ def save_config():
"parse_views": parse_views.value,
"save_xlsx": save_xlsx.value,
"use_webdriver": use_webdriver.value,
"playwright_state_file": playwright_state_file.value,
}}

save_avito_config(config)
Expand Down Expand Up @@ -165,6 +168,9 @@ def open_dlg_modal(e):
dlg_modal_proxy.open = True
page.update()

async def btn_prompt_user_login_handler(e):
await prompt_user_login.wrapper()

def start_parser(e):
nonlocal is_run
result = check_string()
Expand All @@ -179,6 +185,10 @@ def start_parser(e):
stop_btn.visible = True
is_run = True
page.update()

threading.Thread(target=run_parser, daemon=True).start()

def run_parser():
while is_run and not stop_event.is_set():
run_process()
if not is_run:
Expand Down Expand Up @@ -290,14 +300,14 @@ def run_process():
tooltip=TG_TOKEN_HELP)
tg_chat_id = ft.TextField(label="Chat id telegram. Можно несколько через Enter", width=400,
multiline=True, expand=True, text_size=12, height=70, tooltip=TG_CHAT_ID_HELP)
btn_test_tg = ft.ElevatedButton(text="Проверить tg", disabled=False, on_click=telegram_log_test, expand=True,
btn_test_tg = ft.Button("Проверить tg", disabled=False, on_click=telegram_log_test, expand=True,
tooltip=BTN_TEST_TG_HELP)
proxy = ft.TextField(label="Прокси в формате username:password@mproxy.site:port", width=400, expand=True,
tooltip=PROXY_HELP)
proxy_change_ip = ft.TextField(
label="Ссылка для изменения IP, в формате https://changeip.mobileproxy.space/?proxy_key=***", width=400,
expand=True, tooltip=PROXY_CHANGE_IP_HELP)
proxy_btn_help = ft.ElevatedButton(text="Подробнее про прокси", on_click=open_dlg_modal, expand=True,
proxy_btn_help = ft.Button("Подробнее про прокси", on_click=open_dlg_modal, expand=True,
tooltip=PROXY_BTN_HELP_HELP)
geo = ft.TextField(label="Ограничение по городу", width=400, expand=True, text_size=12, height=30,
tooltip=GEO_HELP)
Expand All @@ -313,16 +323,16 @@ def run_process():
)
start_btn = ft.FilledButton("Старт", width=800, on_click=start_parser, expand=True)
stop_btn = ft.OutlinedButton("Стоп", width=980, on_click=stop_parser, visible=False,
style=ft.ButtonStyle(bgcolor=ft.colors.RED_400), expand=True)
console_widget = ft.Text(width=800, height=60, color=ft.colors.GREEN, value="", selectable=True,
style=ft.ButtonStyle(bgcolor=ft.Colors.RED_400), expand=True)
console_widget = ft.Text(width=800, height=60, color=ft.Colors.GREEN, value="", selectable=True,
expand=True)

buy_me_coffe_btn = ft.TextButton("Продвинуть разработку",
on_click=lambda e: page.launch_url(DONAT_LINK),
style=ft.ButtonStyle(color=ft.colors.GREEN_300), expand=True,
style=ft.ButtonStyle(color=ft.Colors.GREEN_300), expand=True,
tooltip=BUY_ME_COFFE_BTN_HELP)
report_issue_btn = ft.TextButton("Сообщить о проблеме", on_click=lambda e: page.launch_url(
"https://github.com/Duff89/parser_avito/issues"), style=ft.ButtonStyle(color=ft.colors.GREY), expand=True,
"https://github.com/Duff89/parser_avito/issues"), style=ft.ButtonStyle(color=ft.Colors.GREY), expand=True,
tooltip=REPORT_ISSUE_BTN_HELP)
ignore_ads_in_reserv = ft.Checkbox(label="Игнор-ть резервы", value=True, tooltip=IGNORE_RESERV_HELP)
ignore_promote_ads = ft.Checkbox(label="Игнор-ть продвинутые", value=False)
Expand All @@ -336,7 +346,10 @@ def run_process():

use_webdriver = ft.Checkbox(label="Использовать браузер", value=True,
tooltip=USE_WEBDRIVER_HELP)

playwright_state_file = ft.TextField(label="Файл сессии Авито", width=400, expand=True, text_size=12, height=50,
tooltip=PLAYWRIGHT_STATE_FILE_HELP)
btn_prompt_user_login = ft.Button("Войти в аккаунт Авито", on_click=btn_prompt_user_login_handler, expand=True,
tooltip=PROMPT_USER_LOGIN_HELP)

input_fields = ft.Column(
[
Expand Down Expand Up @@ -370,7 +383,12 @@ def run_process():
alignment=ft.MainAxisAlignment.CENTER,
spacing=0
),
seller_black_list,
ft.Row(
[seller_black_list, playwright_state_file],
alignment=ft.MainAxisAlignment.CENTER,
spacing=0
),
btn_prompt_user_login,
ft.Row(
[tg_token, tg_chat_id],
alignment=ft.MainAxisAlignment.CENTER,
Expand Down Expand Up @@ -431,7 +449,4 @@ def start_page():
logger_console_init()


ft.app(
target=main,
assets_dir="assets",
)
ft.run(main, assets_dir="assets")
3 changes: 3 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,9 @@
python parser_cls.py
```

### Использование аккаунта Авито
Для обхода капчи и ограничений по количеству запросов можно подвязать к парсеру свой аккаунт. Категорически **НЕ** рекомендуется использовать свой основоной аккаунт. Для привязки аккаунта прописываем в конфиге `playwright_state_file = "state.json"`, после чего запускаем на системе с графическим интерфейсом `python prompt_user_login.py` и авторизуемся. Далее запускаем парсер, он автоматически подтянет сессию из `playwright_state_file` и будет обновлять её в файле по мере отправки запросов.

## Работа через Docker

Перед использованием настройте `config.toml`
Expand Down
1 change: 1 addition & 0 deletions config.toml
Original file line number Diff line number Diff line change
Expand Up @@ -27,3 +27,4 @@ one_file_for_link = false
parse_views = false
save_xlsx = true
use_webdriver = true
playwright_state_file = "state.json"
1 change: 1 addition & 0 deletions dto.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,4 +42,5 @@ class AvitoConfig:
parse_views: bool = False
save_xlsx: bool = True
use_webdriver: bool = True
playwright_state_file: str | None = None

14 changes: 14 additions & 0 deletions get_cookies.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,11 @@
from playwright.async_api import async_playwright
from playwright_stealth import Stealth
from typing import Optional, Dict, List
from playwright.async_api import Error, TimeoutError

from dto import Proxy, ProxySplit
from playwright_setup import ensure_playwright_installed
from load_config import load_avito_config

MAX_RETRIES = 3
RETRY_DELAY = 10
Expand Down Expand Up @@ -77,6 +79,12 @@ def parse_cookie_string(cookie_str: str) -> dict:

async def launch_browser(self):
ensure_playwright_installed("chromium")

try:
config = load_avito_config("config.toml")
except Exception as err:
logger.error(f"Ошибка загрузки конфига: {err}")

stealth = Stealth()
self.playwright_context = stealth.use_async(async_playwright())
playwright = await self.playwright_context.__aenter__()
Expand Down Expand Up @@ -105,6 +113,12 @@ async def launch_browser(self):
"has_touch": False,
}

if isinstance(config.playwright_state_file,str):
context_args["storage_state"] = config.playwright_state_file
logger.debug(f"Используем Playwright state file {config.playwright_state_file}")
else:
logger.debug("Playwright state file не задан. Используем пустой контекст Playwright.")

if self.proxy_split_obj:
context_args["proxy"] = {
"server": self.proxy_split_obj.ip_port,
Expand Down
3 changes: 3 additions & 0 deletions lang.py
Original file line number Diff line number Diff line change
Expand Up @@ -55,3 +55,6 @@
SAVE_XLSX_HELP = "Сохранять результат в Excel файл?"
USE_WEBDRIVER_HELP = ("Использовать эмулятор браузера или нет. Если запускаете на сервере, где мало оперативной памяти"
" и работать будет долго - полезнее будет отключить, стабильность повысится")
PLAYWRIGHT_STATE_FILE_HELP = ("Не меняйте это значение если не знаете что делаете. В этот файл будет сохраняться сессия " \
"пользователя Авито после входа в аккаунт")
PROMPT_USER_LOGIN_HELP = ("Войти а аккаунт Авито для обхода ошибки 429. Категорически НЕ рекомендуется использовать свой основной аккаунт")
Loading