Files
proxy-scraper-checker/proxy_scraper_checker/output.py
T
monosansandGitHub e4047e16ae Huge update
- Drop support for Python 3.7.
- Use offline geolocation database instead of ip-api.com.
- Add support for proxy authentication.
- Add pre-compiled binaries.
- Refactor the code by a lot.
- Simplify config.
- Add automatic text encoding detection.
- Use TOML instead of INI for configuration.
- Add support for using httpbin-compatible services and services which return plain IP address for getting proxy's exit node.
- Add support for reading proxy lists from local files.
- Add support for saving to json.
- Remove support for saving geolocation to txt, use json instead.
- Improve parser.
- Improve config validation.
- Use poetry instead of requirements.txt.
- Use venv in start scripts.
2024-01-21 17:45:01 +00:00

101 lines
3.4 KiB
Python

from __future__ import annotations
import json
import logging
from shutil import rmtree
from typing import Sequence, Union
import aiofiles
import aiofiles.os
import aiofiles.ospath
import maxminddb
from . import sort
from .geodb import GEODB_PATH
from .null_context import NullContext
from .proxy import Proxy
from .settings import Settings
from .storage import ProxyStorage
logger = logging.getLogger(__name__)
def _create_proxy_list_str(
*, anonymous_only: bool, include_protocol: bool, proxies: Sequence[Proxy]
) -> str:
return "\n".join(
proxy.as_str(include_protocol=include_protocol)
for proxy in proxies
if not anonymous_only or proxy.host != proxy.exit_ip
)
@aiofiles.ospath.wrap
def save_proxies(*, settings: Settings, storage: ProxyStorage) -> None:
if settings.output_json:
mmdb: Union[maxminddb.Reader, NullContext] = (
maxminddb.open_database(GEODB_PATH)
if settings.enable_geolocation
else NullContext()
)
settings.output_path.mkdir(parents=True, exist_ok=True)
with mmdb as mmdb_reader:
proxy_dicts = [
{
"protocol": proxy.protocol.name.lower(),
"username": proxy.username,
"password": proxy.password,
"host": proxy.host,
"port": proxy.port,
"exit_ip": proxy.exit_ip,
"timeout": round(proxy.timeout, 2),
"geolocation": mmdb_reader.get(proxy.exit_ip)
if mmdb_reader is not None
else None,
}
for proxy in sorted(storage, key=sort.timeout_sort_key)
]
with (settings.output_path / "proxies.json").open(
"w", encoding="utf-8"
) as f:
json.dump(
proxy_dicts, f, ensure_ascii=False, separators=(",", ":")
)
with (settings.output_path / "proxies_pretty.json").open(
"w", encoding="utf-8"
) as f:
json.dump(proxy_dicts, f, ensure_ascii=False, indent="\t")
if settings.output_txt:
sorted_proxies = storage.get_sorted(key=settings.sorting_key)
grouped_proxies = tuple(
(k, sorted(v, key=settings.sorting_key))
for k, v in storage.get_grouped().items()
)
for folder, anonymous_only in (
(settings.output_path / "proxies", False),
(settings.output_path / "proxies_anonymous", True),
):
try:
rmtree(folder)
except FileNotFoundError:
pass
folder.mkdir(parents=True, exist_ok=True)
text = _create_proxy_list_str(
proxies=sorted_proxies,
anonymous_only=anonymous_only,
include_protocol=True,
)
(folder / "all.txt").write_text(text, encoding="utf-8")
for proto, proxies in grouped_proxies:
text = _create_proxy_list_str(
proxies=proxies,
anonymous_only=anonymous_only,
include_protocol=False,
)
(folder / f"{proto.name.lower()}.txt").write_text(
text, encoding="utf-8"
)
logger.info(
"Proxies have been saved to %s", settings.output_path.absolute()
)