Files
proxy-scraper-checker/proxy_scraper_checker/__main__.py
T

182 lines
5.5 KiB
Python
Raw Normal View History

2024-11-06 15:05:34 +03:00
# ruff: noqa: E402
2023-01-02 00:09:55 +03:00
from __future__ import annotations
2024-11-22 14:32:29 +03:00
from proxy_scraper_checker import logs
2024-11-06 15:05:34 +03:00
2024-11-06 15:09:38 +03:00
_logs_listener = logs.configure()
2024-11-06 15:05:34 +03:00
2023-01-02 00:09:55 +03:00
import asyncio
import logging
import sys
2024-07-09 03:08:30 +03:00
from typing import TYPE_CHECKING
2023-01-02 00:09:55 +03:00
2024-01-21 17:45:01 +00:00
import aiofiles
2024-11-06 15:09:38 +03:00
import rich
2024-01-21 17:45:01 +00:00
from aiohttp import ClientSession, TCPConnector
from rich.progress import BarColumn, MofNCompleteColumn, Progress, TextColumn
from rich.table import Table
2023-01-02 00:09:55 +03:00
2024-11-22 14:32:29 +03:00
from proxy_scraper_checker import (
checker,
geodb,
http,
output,
scraper,
sort,
utils,
)
from proxy_scraper_checker.settings import Settings
from proxy_scraper_checker.storage import ProxyStorage
2024-01-21 17:45:01 +00:00
if sys.version_info >= (3, 11):
try:
import tomllib
except ImportError:
# Help users on older alphas
if not TYPE_CHECKING:
import tomli as tomllib
else:
import tomli as tomllib
2024-06-03 14:08:42 +05:00
if TYPE_CHECKING:
2024-10-17 14:18:27 +03:00
from collections.abc import Coroutine, Mapping
from typing import Callable
2024-07-09 03:08:30 +03:00
2024-06-03 14:08:42 +05:00
from aiohttp_socks import ProxyType
2024-07-09 03:35:36 +03:00
from typing_extensions import Any, TypeVar
2024-06-03 14:08:42 +05:00
2024-07-09 03:35:36 +03:00
T = TypeVar("T")
2023-01-02 09:44:39 +03:00
2024-11-06 15:05:34 +03:00
_logger = logging.getLogger(__name__)
2023-01-02 00:09:55 +03:00
2024-05-31 21:12:18 +05:00
def get_async_run() -> Callable[[Coroutine[Any, Any, T]], T]:
if sys.implementation.name == "cpython":
try:
import uvloop # type: ignore[import-not-found, unused-ignore] # noqa: PLC0415
except ImportError:
pass
else:
2024-05-31 21:12:18 +05:00
try:
return uvloop.run # type: ignore[no-any-return, unused-ignore]
except AttributeError:
uvloop.install()
return asyncio.run
try:
2024-05-31 13:48:09 +05:00
import winloop # type: ignore[import-not-found, unused-ignore] # noqa: PLC0415
except ImportError:
pass
else:
2024-05-31 21:12:18 +05:00
try:
return winloop.run # type: ignore[no-any-return, unused-ignore]
except AttributeError:
winloop.install()
return asyncio.run
if sys.platform == "win32":
asyncio.set_event_loop_policy(asyncio.WindowsSelectorEventLoopPolicy())
2024-05-31 21:12:18 +05:00
return asyncio.run
2023-01-02 00:09:55 +03:00
2024-06-03 14:08:42 +05:00
async def read_config(file: str, /) -> dict[str, Any]:
2024-01-21 17:45:01 +00:00
async with aiofiles.open(file, "rb") as f:
content = await f.read()
return tomllib.loads(utils.bytes_decode(content))
def get_summary_table(
*, before: Mapping[ProxyType, int], after: Mapping[ProxyType, int]
) -> Table:
table = Table()
table.add_column("Protocol", style="cyan")
table.add_column("Working", style="magenta")
table.add_column("Total", style="green")
for proto in sort.PROTOCOL_ORDER:
2024-02-04 16:58:45 +03:00
if (total := before.get(proto)) is not None:
2024-01-21 17:45:01 +00:00
working = after.get(proto, 0)
2024-02-04 16:58:45 +03:00
percentage = (working / total) if total else 0
2024-01-21 17:45:01 +00:00
table.add_row(
proto.name, f"{working} ({percentage:.1%})", str(total)
)
return table
2023-02-06 20:59:03 +03:00
2023-02-21 21:22:47 +03:00
async def main() -> None:
2024-01-21 17:45:01 +00:00
cfg = await read_config("config.toml")
2024-11-06 15:05:34 +03:00
if cfg["debug"]:
logging.root.setLevel(logging.DEBUG)
2024-09-18 18:23:01 +03:00
should_save = False
try:
async with ClientSession(
connector=TCPConnector(ssl=http.SSL_CONTEXT),
headers=http.HEADERS,
cookie_jar=http.get_cookie_jar(),
raise_for_status=True,
fallback_charset_resolver=http.fallback_charset_resolver,
) as session:
settings = await Settings.from_mapping(cfg, session=session)
storage = ProxyStorage(protocols=settings.sources)
with Progress(
TextColumn("[yellow]{task.fields[module]}"),
2024-09-18 18:23:01 +03:00
TextColumn("[red]::"),
TextColumn("[green]{task.fields[protocol]}"),
2024-09-18 18:23:01 +03:00
BarColumn(),
TextColumn("[cyan]{task.fields[successful_count]}"),
2024-09-18 18:23:01 +03:00
MofNCompleteColumn(),
transient=True,
) as progress:
scrape = scraper.scrape_all(
progress=progress,
session=session,
settings=settings,
storage=storage,
)
await (
asyncio.gather(
geodb.download_geodb(
progress=progress, session=session
),
scrape,
)
if settings.enable_geolocation
else scrape
)
await session.close()
count_before_checking = storage.get_count()
should_save = True
2024-09-18 18:30:59 +03:00
if settings.check_website:
await checker.check_all(
settings=settings,
storage=storage,
progress=progress,
proxies_count=count_before_checking,
)
2024-09-18 18:23:01 +03:00
finally:
if should_save:
2024-09-18 18:30:59 +03:00
if settings.check_website:
storage.remove_unchecked()
2024-09-18 18:23:01 +03:00
count_after_checking = storage.get_count()
2024-11-06 15:09:38 +03:00
rich.print(
2024-09-18 18:23:01 +03:00
get_summary_table(
before=count_before_checking, after=count_after_checking
2024-01-21 17:45:01 +00:00
)
)
2024-11-04 11:00:52 +03:00
await asyncio.to_thread(
output.save_proxies, storage=storage, settings=settings
)
2024-01-21 17:45:01 +00:00
2024-11-06 15:05:34 +03:00
_logger.info(
2024-09-18 18:23:01 +03:00
"Thank you for using https://github.com/monosans/proxy-scraper-checker"
)
2023-01-02 09:44:39 +03:00
if __name__ == "__main__":
2024-11-06 15:05:34 +03:00
_logs_listener.start()
try:
get_async_run()(main())
2024-11-22 13:50:58 +03:00
except KeyboardInterrupt:
sys.exit(130)
2024-11-06 15:05:34 +03:00
finally:
_logs_listener.stop()