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

122 lines
3.6 KiB
Python
Raw Normal View History

2024-01-21 17:45:01 +00:00
from __future__ import annotations
import asyncio
import itertools
import logging
2024-06-03 14:08:42 +05:00
from typing import TYPE_CHECKING
2024-01-21 17:45:01 +00:00
import aiofiles
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
2024-11-22 14:32:29 +03:00
from proxy_scraper_checker.counter import IncrInt
from proxy_scraper_checker.http import get_response_text
from proxy_scraper_checker.parsers import PROXY_REGEX
from proxy_scraper_checker.proxy import Proxy
from proxy_scraper_checker.utils import bytes_decode, 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(
*,
counter: IncrInt,
2024-01-21 17:45:01 +00:00
progress: Progress,
proto: ProxyType,
session: ClientSession,
source: str,
storage: ProxyStorage,
task: TaskID,
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()
2024-01-23 09:37:29 +03:00
text = get_response_text(response=response, content=content)
2024-01-21 17:45:01 +00:00
else:
async with aiofiles.open(source, "rb") as f:
content = await f.read()
2024-01-23 09:37:29 +03:00
text = bytes_decode(content)
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:
counter.incr()
2024-01-21 17:45:01 +00:00
proxies = PROXY_REGEX.finditer(text)
try:
proxy = next(proxies)
except StopIteration:
2024-11-06 15:05:34 +03:00
_logger.warning("%s | No proxies found", source)
2024-01-21 17:45:01 +00:00
else:
for proxy in itertools.chain((proxy,), proxies): # noqa: B020
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"),
)
)
progress.update(task_id=task, advance=1, successful_count=counter.value)
2024-01-21 17:45:01 +00:00
async def scrape_all(
*,
progress: Progress,
session: ClientSession,
settings: Settings,
storage: ProxyStorage,
) -> None:
counters = {proto: IncrInt() 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)
2024-01-25 10:30:40 +03:00
await asyncio.gather(
*(
scrape_one(
counter=counters[proto],
2024-01-25 10:30:40 +03:00
progress=progress,
proto=proto,
session=session,
source=source,
storage=storage,
2024-01-25 11:49:22 +03:00
task=progress_tasks[proto],
2024-01-25 10:30:40 +03:00
timeout=timeout,
)
for proto, sources in settings.sources.items()
for source in sources
2024-01-21 17:45:01 +00:00
)
)