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

133 lines
3.9 KiB
Python
Raw Normal View History

2024-01-21 17:45:01 +00:00
from __future__ import annotations
import asyncio
import logging
from pathlib import Path
2024-06-03 14:08:42 +05:00
from typing import TYPE_CHECKING
2024-01-21 17:45:01 +00:00
2024-07-09 03:08:30 +03:00
from aiohttp import ClientResponseError, ClientTimeout
2024-01-21 17:45:01 +00:00
from aiohttp_socks import ProxyType
2025-02-27 11:12:52 +03:00
from proxy_scraper_checker.incrementor import Incrementor
2024-11-22 14:32:29 +03:00
from proxy_scraper_checker.parsers import PROXY_REGEX
from proxy_scraper_checker.proxy import Proxy
from proxy_scraper_checker.utils import is_http_url
2024-01-21 17:45:01 +00:00
2024-06-03 14:08:42 +05:00
if TYPE_CHECKING:
2024-07-09 03:08:30 +03:00
from aiohttp import ClientSession
2024-06-03 14:08:42 +05:00
from rich.progress import Progress, TaskID
2024-11-22 14:32:29 +03:00
from proxy_scraper_checker.settings import Settings
from proxy_scraper_checker.storage import ProxyStorage
2024-06-03 14:08:42 +05:00
2024-11-06 15:05:34 +03:00
_logger = logging.getLogger(__name__)
2024-01-21 17:45:01 +00:00
async def scrape_one(
*,
2025-02-27 11:12:52 +03:00
incrementor: Incrementor,
2024-01-21 17:45:01 +00:00
progress: Progress,
2025-02-27 11:12:52 +03:00
progress_task: TaskID,
2024-01-21 17:45:01 +00:00
proto: ProxyType,
session: ClientSession,
2025-01-10 12:49:36 +03:00
settings: Settings,
2024-01-21 17:45:01 +00:00
source: str,
storage: ProxyStorage,
timeout: ClientTimeout,
) -> None:
try:
if is_http_url(source):
2024-01-21 17:45:01 +00:00
async with session.get(source, timeout=timeout) as response:
2024-01-21 21:46:01 +03:00
content = await response.read()
text = content.decode(response.get_encoding(), errors="replace")
2024-01-21 17:45:01 +00:00
else:
text = await asyncio.to_thread(
Path(source.removeprefix("file://")).read_text,
encoding="utf-8",
errors="replace",
2025-01-07 21:09:43 +03:00
)
except ClientResponseError as e:
2024-11-06 15:05:34 +03:00
_logger.warning(
"%s | HTTP status code %d: %s", source, e.status, e.message
)
2024-01-21 17:45:01 +00:00
except Exception as e:
2024-11-06 15:05:34 +03:00
_logger.warning(
2024-01-21 17:45:01 +00:00
"%s | %s.%s: %s",
source,
e.__class__.__module__,
e.__class__.__qualname__,
e,
)
else:
2025-02-27 11:12:52 +03:00
incrementor.increment()
2025-01-10 12:49:36 +03:00
proxies = tuple(PROXY_REGEX.finditer(text))
2025-01-10 12:33:56 +03:00
if not proxies:
2024-11-06 15:05:34 +03:00
_logger.warning("%s | No proxies found", source)
2025-01-10 12:49:36 +03:00
elif (
settings.proxies_per_source_limit
and len(proxies) > settings.proxies_per_source_limit
):
2025-01-10 12:33:56 +03:00
_logger.warning(
"%s has too many proxies (%d), skipping", source, len(proxies)
)
2024-01-21 17:45:01 +00:00
else:
2025-01-10 12:33:56 +03:00
for proxy in proxies:
2024-01-21 17:45:01 +00:00
try:
protocol = ProxyType[
2024-03-23 09:47:55 +03:00
proxy.group("protocol").upper().rstrip("S")
2024-01-21 17:45:01 +00:00
]
except AttributeError:
protocol = proto
storage.add(
Proxy(
protocol=protocol,
host=proxy.group("host"),
port=int(proxy.group("port")),
username=proxy.group("username"),
password=proxy.group("password"),
)
)
2025-02-27 11:12:52 +03:00
progress.update(
task_id=progress_task,
advance=1,
successful_count=incrementor.get_value(),
)
2024-01-21 17:45:01 +00:00
async def scrape_all(
*,
progress: Progress,
session: ClientSession,
settings: Settings,
storage: ProxyStorage,
) -> None:
2025-02-27 11:12:52 +03:00
incrementors = {proto: Incrementor() for proto in settings.sources}
2024-01-25 11:49:22 +03:00
progress_tasks = {
2024-01-21 17:45:01 +00:00
proto: progress.add_task(
description="",
total=len(sources),
module="Scraper",
protocol=proto.name,
successful_count=0,
2024-01-21 17:45:01 +00:00
)
for proto, sources in settings.sources.items()
}
timeout = ClientTimeout(total=settings.source_timeout, connect=5)
2024-01-25 10:30:40 +03:00
await asyncio.gather(
*(
scrape_one(
2025-02-27 11:12:52 +03:00
incrementor=incrementors[proto],
2024-01-25 10:30:40 +03:00
progress=progress,
2025-02-27 11:12:52 +03:00
progress_task=progress_tasks[proto],
2024-01-25 10:30:40 +03:00
proto=proto,
session=session,
2025-01-10 12:49:36 +03:00
settings=settings,
2024-01-25 10:30:40 +03:00
source=source,
storage=storage,
timeout=timeout,
)
for proto, sources in settings.sources.items()
for source in sources
2024-01-21 17:45:01 +00:00
)
)