proxy-scraper-cli 1.13.0__tar.gz → 1.14.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {proxy_scraper_cli-1.13.0 → proxy_scraper_cli-1.14.0}/PKG-INFO +9 -1
- {proxy_scraper_cli-1.13.0 → proxy_scraper_cli-1.14.0}/README.md +8 -0
- {proxy_scraper_cli-1.13.0 → proxy_scraper_cli-1.14.0}/proxy_scraper_cli.egg-info/PKG-INFO +9 -1
- {proxy_scraper_cli-1.13.0 → proxy_scraper_cli-1.14.0}/proxy_scraper_cli.egg-info/SOURCES.txt +1 -0
- {proxy_scraper_cli-1.13.0 → proxy_scraper_cli-1.14.0}/proxyscraper/__init__.py +1 -1
- {proxy_scraper_cli-1.13.0 → proxy_scraper_cli-1.14.0}/proxyscraper/cli.py +52 -0
- proxy_scraper_cli-1.14.0/tests/test_pick.py +44 -0
- {proxy_scraper_cli-1.13.0 → proxy_scraper_cli-1.14.0}/LICENSE +0 -0
- {proxy_scraper_cli-1.13.0 → proxy_scraper_cli-1.14.0}/proxy_scraper_cli.egg-info/dependency_links.txt +0 -0
- {proxy_scraper_cli-1.13.0 → proxy_scraper_cli-1.14.0}/proxy_scraper_cli.egg-info/entry_points.txt +0 -0
- {proxy_scraper_cli-1.13.0 → proxy_scraper_cli-1.14.0}/proxy_scraper_cli.egg-info/requires.txt +0 -0
- {proxy_scraper_cli-1.13.0 → proxy_scraper_cli-1.14.0}/proxy_scraper_cli.egg-info/top_level.txt +0 -0
- {proxy_scraper_cli-1.13.0 → proxy_scraper_cli-1.14.0}/proxyscraper/__main__.py +0 -0
- {proxy_scraper_cli-1.13.0 → proxy_scraper_cli-1.14.0}/proxyscraper/action.py +0 -0
- {proxy_scraper_cli-1.13.0 → proxy_scraper_cli-1.14.0}/proxyscraper/agent.py +0 -0
- {proxy_scraper_cli-1.13.0 → proxy_scraper_cli-1.14.0}/proxyscraper/api.py +0 -0
- {proxy_scraper_cli-1.13.0 → proxy_scraper_cli-1.14.0}/proxyscraper/app.py +0 -0
- {proxy_scraper_cli-1.13.0 → proxy_scraper_cli-1.14.0}/proxyscraper/asndb.py +0 -0
- {proxy_scraper_cli-1.13.0 → proxy_scraper_cli-1.14.0}/proxyscraper/blocklist.py +0 -0
- {proxy_scraper_cli-1.13.0 → proxy_scraper_cli-1.14.0}/proxyscraper/charts.py +0 -0
- {proxy_scraper_cli-1.13.0 → proxy_scraper_cli-1.14.0}/proxyscraper/checker.py +0 -0
- {proxy_scraper_cli-1.13.0 → proxy_scraper_cli-1.14.0}/proxyscraper/compat.py +0 -0
- {proxy_scraper_cli-1.13.0 → proxy_scraper_cli-1.14.0}/proxyscraper/completion.py +0 -0
- {proxy_scraper_cli-1.13.0 → proxy_scraper_cli-1.14.0}/proxyscraper/exporters.py +0 -0
- {proxy_scraper_cli-1.13.0 → proxy_scraper_cli-1.14.0}/proxyscraper/fetchcache.py +0 -0
- {proxy_scraper_cli-1.13.0 → proxy_scraper_cli-1.14.0}/proxyscraper/geo.py +0 -0
- {proxy_scraper_cli-1.13.0 → proxy_scraper_cli-1.14.0}/proxyscraper/geodb.py +0 -0
- {proxy_scraper_cli-1.13.0 → proxy_scraper_cli-1.14.0}/proxyscraper/handshake.py +0 -0
- {proxy_scraper_cli-1.13.0 → proxy_scraper_cli-1.14.0}/proxyscraper/history.py +0 -0
- {proxy_scraper_cli-1.13.0 → proxy_scraper_cli-1.14.0}/proxyscraper/judges.py +0 -0
- {proxy_scraper_cli-1.13.0 → proxy_scraper_cli-1.14.0}/proxyscraper/mcp_entry.py +0 -0
- {proxy_scraper_cli-1.13.0 → proxy_scraper_cli-1.14.0}/proxyscraper/mcp_server.py +0 -0
- {proxy_scraper_cli-1.13.0 → proxy_scraper_cli-1.14.0}/proxyscraper/netio.py +0 -0
- {proxy_scraper_cli-1.13.0 → proxy_scraper_cli-1.14.0}/proxyscraper/options.py +0 -0
- {proxy_scraper_cli-1.13.0 → proxy_scraper_cli-1.14.0}/proxyscraper/output.py +0 -0
- {proxy_scraper_cli-1.13.0 → proxy_scraper_cli-1.14.0}/proxyscraper/pages.py +0 -0
- {proxy_scraper_cli-1.13.0 → proxy_scraper_cli-1.14.0}/proxyscraper/parsing.py +0 -0
- {proxy_scraper_cli-1.13.0 → proxy_scraper_cli-1.14.0}/proxyscraper/paths.py +0 -0
- {proxy_scraper_cli-1.13.0 → proxy_scraper_cli-1.14.0}/proxyscraper/pipeline.py +0 -0
- {proxy_scraper_cli-1.13.0 → proxy_scraper_cli-1.14.0}/proxyscraper/preferences.py +0 -0
- {proxy_scraper_cli-1.13.0 → proxy_scraper_cli-1.14.0}/proxyscraper/proxypages.py +0 -0
- {proxy_scraper_cli-1.13.0 → proxy_scraper_cli-1.14.0}/proxyscraper/publish.py +0 -0
- {proxy_scraper_cli-1.13.0 → proxy_scraper_cli-1.14.0}/proxyscraper/report.py +0 -0
- {proxy_scraper_cli-1.13.0 → proxy_scraper_cli-1.14.0}/proxyscraper/runsteps.py +0 -0
- {proxy_scraper_cli-1.13.0 → proxy_scraper_cli-1.14.0}/proxyscraper/server/__init__.py +0 -0
- {proxy_scraper_cli-1.13.0 → proxy_scraper_cli-1.14.0}/proxyscraper/server/core.py +0 -0
- {proxy_scraper_cli-1.13.0 → proxy_scraper_cli-1.14.0}/proxyscraper/server/http.py +0 -0
- {proxy_scraper_cli-1.13.0 → proxy_scraper_cli-1.14.0}/proxyscraper/server/pool.py +0 -0
- {proxy_scraper_cli-1.13.0 → proxy_scraper_cli-1.14.0}/proxyscraper/server/socks.py +0 -0
- {proxy_scraper_cli-1.13.0 → proxy_scraper_cli-1.14.0}/proxyscraper/server/status.py +0 -0
- {proxy_scraper_cli-1.13.0 → proxy_scraper_cli-1.14.0}/proxyscraper/server/upstream.py +0 -0
- {proxy_scraper_cli-1.13.0 → proxy_scraper_cli-1.14.0}/proxyscraper/site/apple-touch-icon.png +0 -0
- {proxy_scraper_cli-1.13.0 → proxy_scraper_cli-1.14.0}/proxyscraper/site/googleaac1161b7853c5b5.html +0 -0
- {proxy_scraper_cli-1.13.0 → proxy_scraper_cli-1.14.0}/proxyscraper/site/index.html +0 -0
- {proxy_scraper_cli-1.13.0 → proxy_scraper_cli-1.14.0}/proxyscraper/site/logo.png +0 -0
- {proxy_scraper_cli-1.13.0 → proxy_scraper_cli-1.14.0}/proxyscraper/site/og.png +0 -0
- {proxy_scraper_cli-1.13.0 → proxy_scraper_cli-1.14.0}/proxyscraper/sites.py +0 -0
- {proxy_scraper_cli-1.13.0 → proxy_scraper_cli-1.14.0}/proxyscraper/sources.json +0 -0
- {proxy_scraper_cli-1.13.0 → proxy_scraper_cli-1.14.0}/proxyscraper/sources.py +0 -0
- {proxy_scraper_cli-1.13.0 → proxy_scraper_cli-1.14.0}/proxyscraper/speed.py +0 -0
- {proxy_scraper_cli-1.13.0 → proxy_scraper_cli-1.14.0}/proxyscraper/targets.py +0 -0
- {proxy_scraper_cli-1.13.0 → proxy_scraper_cli-1.14.0}/proxyscraper/ui/__init__.py +0 -0
- {proxy_scraper_cli-1.13.0 → proxy_scraper_cli-1.14.0}/proxyscraper/ui/dashboard.py +0 -0
- {proxy_scraper_cli-1.13.0 → proxy_scraper_cli-1.14.0}/proxyscraper/ui/keys.py +0 -0
- {proxy_scraper_cli-1.13.0 → proxy_scraper_cli-1.14.0}/proxyscraper/ui/report.py +0 -0
- {proxy_scraper_cli-1.13.0 → proxy_scraper_cli-1.14.0}/proxyscraper/ui/serve.py +0 -0
- {proxy_scraper_cli-1.13.0 → proxy_scraper_cli-1.14.0}/proxyscraper/ui/widgets.py +0 -0
- {proxy_scraper_cli-1.13.0 → proxy_scraper_cli-1.14.0}/proxyscraper/ui/wizard.py +0 -0
- {proxy_scraper_cli-1.13.0 → proxy_scraper_cli-1.14.0}/pyproject.toml +0 -0
- {proxy_scraper_cli-1.13.0 → proxy_scraper_cli-1.14.0}/setup.cfg +0 -0
- {proxy_scraper_cli-1.13.0 → proxy_scraper_cli-1.14.0}/tests/test_action.py +0 -0
- {proxy_scraper_cli-1.13.0 → proxy_scraper_cli-1.14.0}/tests/test_agent.py +0 -0
- {proxy_scraper_cli-1.13.0 → proxy_scraper_cli-1.14.0}/tests/test_api.py +0 -0
- {proxy_scraper_cli-1.13.0 → proxy_scraper_cli-1.14.0}/tests/test_app.py +0 -0
- {proxy_scraper_cli-1.13.0 → proxy_scraper_cli-1.14.0}/tests/test_asndb.py +0 -0
- {proxy_scraper_cli-1.13.0 → proxy_scraper_cli-1.14.0}/tests/test_auth.py +0 -0
- {proxy_scraper_cli-1.13.0 → proxy_scraper_cli-1.14.0}/tests/test_blocklist.py +0 -0
- {proxy_scraper_cli-1.13.0 → proxy_scraper_cli-1.14.0}/tests/test_charts.py +0 -0
- {proxy_scraper_cli-1.13.0 → proxy_scraper_cli-1.14.0}/tests/test_checker.py +0 -0
- {proxy_scraper_cli-1.13.0 → proxy_scraper_cli-1.14.0}/tests/test_compat.py +0 -0
- {proxy_scraper_cli-1.13.0 → proxy_scraper_cli-1.14.0}/tests/test_completion.py +0 -0
- {proxy_scraper_cli-1.13.0 → proxy_scraper_cli-1.14.0}/tests/test_discovery_growth.py +0 -0
- {proxy_scraper_cli-1.13.0 → proxy_scraper_cli-1.14.0}/tests/test_exporters.py +0 -0
- {proxy_scraper_cli-1.13.0 → proxy_scraper_cli-1.14.0}/tests/test_fetchcache.py +0 -0
- {proxy_scraper_cli-1.13.0 → proxy_scraper_cli-1.14.0}/tests/test_geodb.py +0 -0
- {proxy_scraper_cli-1.13.0 → proxy_scraper_cli-1.14.0}/tests/test_judges.py +0 -0
- {proxy_scraper_cli-1.13.0 → proxy_scraper_cli-1.14.0}/tests/test_learning.py +0 -0
- {proxy_scraper_cli-1.13.0 → proxy_scraper_cli-1.14.0}/tests/test_live_api.py +0 -0
- {proxy_scraper_cli-1.13.0 → proxy_scraper_cli-1.14.0}/tests/test_mcp_server.py +0 -0
- {proxy_scraper_cli-1.13.0 → proxy_scraper_cli-1.14.0}/tests/test_mine_sources.py +0 -0
- {proxy_scraper_cli-1.13.0 → proxy_scraper_cli-1.14.0}/tests/test_options.py +0 -0
- {proxy_scraper_cli-1.13.0 → proxy_scraper_cli-1.14.0}/tests/test_output_stdout.py +0 -0
- {proxy_scraper_cli-1.13.0 → proxy_scraper_cli-1.14.0}/tests/test_packaging.py +0 -0
- {proxy_scraper_cli-1.13.0 → proxy_scraper_cli-1.14.0}/tests/test_pages.py +0 -0
- {proxy_scraper_cli-1.13.0 → proxy_scraper_cli-1.14.0}/tests/test_parsing.py +0 -0
- {proxy_scraper_cli-1.13.0 → proxy_scraper_cli-1.14.0}/tests/test_parsing_fuzz.py +0 -0
- {proxy_scraper_cli-1.13.0 → proxy_scraper_cli-1.14.0}/tests/test_paths.py +0 -0
- {proxy_scraper_cli-1.13.0 → proxy_scraper_cli-1.14.0}/tests/test_pipeline.py +0 -0
- {proxy_scraper_cli-1.13.0 → proxy_scraper_cli-1.14.0}/tests/test_proxy_pages.py +0 -0
- {proxy_scraper_cli-1.13.0 → proxy_scraper_cli-1.14.0}/tests/test_proxy_sources.py +0 -0
- {proxy_scraper_cli-1.13.0 → proxy_scraper_cli-1.14.0}/tests/test_publish.py +0 -0
- {proxy_scraper_cli-1.13.0 → proxy_scraper_cli-1.14.0}/tests/test_report.py +0 -0
- {proxy_scraper_cli-1.13.0 → proxy_scraper_cli-1.14.0}/tests/test_robustness.py +0 -0
- {proxy_scraper_cli-1.13.0 → proxy_scraper_cli-1.14.0}/tests/test_serve_password.py +0 -0
- {proxy_scraper_cli-1.13.0 → proxy_scraper_cli-1.14.0}/tests/test_serve_refill.py +0 -0
- {proxy_scraper_cli-1.13.0 → proxy_scraper_cli-1.14.0}/tests/test_serve_v2.py +0 -0
- {proxy_scraper_cli-1.13.0 → proxy_scraper_cli-1.14.0}/tests/test_server.py +0 -0
- {proxy_scraper_cli-1.13.0 → proxy_scraper_cli-1.14.0}/tests/test_server_closed_writer.py +0 -0
- {proxy_scraper_cli-1.13.0 → proxy_scraper_cli-1.14.0}/tests/test_server_fixes.py +0 -0
- {proxy_scraper_cli-1.13.0 → proxy_scraper_cli-1.14.0}/tests/test_sites.py +0 -0
- {proxy_scraper_cli-1.13.0 → proxy_scraper_cli-1.14.0}/tests/test_sources_json.py +0 -0
- {proxy_scraper_cli-1.13.0 → proxy_scraper_cli-1.14.0}/tests/test_speed.py +0 -0
- {proxy_scraper_cli-1.13.0 → proxy_scraper_cli-1.14.0}/tests/test_tamper.py +0 -0
- {proxy_scraper_cli-1.13.0 → proxy_scraper_cli-1.14.0}/tests/test_targets.py +0 -0
- {proxy_scraper_cli-1.13.0 → proxy_scraper_cli-1.14.0}/tests/test_ui.py +0 -0
- {proxy_scraper_cli-1.13.0 → proxy_scraper_cli-1.14.0}/tests/test_uptime.py +0 -0
- {proxy_scraper_cli-1.13.0 → proxy_scraper_cli-1.14.0}/tests/test_wizard.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: proxy-scraper-cli
|
|
3
|
-
Version: 1.
|
|
3
|
+
Version: 1.14.0
|
|
4
4
|
Summary: Finds free HTTP, SOCKS4 and SOCKS5 proxies that actually work: 700+ sources, real checks, honeypot filtering and a rotating local proxy server.
|
|
5
5
|
Author: Maximilian Feix
|
|
6
6
|
License-Expression: MIT
|
|
@@ -699,6 +699,13 @@ pip download requests # git, pip, npm & co. now go through the pool
|
|
|
699
699
|
|
|
700
700
|
`proxy` is the fastest one, `file` a text file with all of them (up to `limit`, default 20), `count` how many. Without a match the step fails, unless `fail-if-empty: false`.
|
|
701
701
|
|
|
702
|
+
**In the shell, without a scan** – `--pick` takes proxies from the hourly list in about half a second
|
|
703
|
+
|
|
704
|
+
```bash
|
|
705
|
+
curl -x "$(proxy-scraper --pick --https-only --min-uptime 90)" https://api.ipify.org
|
|
706
|
+
proxy-scraper --pick 10 --country DE --works-on google > de.txt
|
|
707
|
+
```
|
|
708
|
+
|
|
702
709
|
**Without installing anything** – straight from the live list
|
|
703
710
|
|
|
704
711
|
```bash
|
|
@@ -743,6 +750,7 @@ curl.exe -x (Get-Content "$run\all.txt" -TotalCount 1) http://api.ipify.org
|
|
|
743
750
|
| `--discover` | search GitHub for new sources right now |
|
|
744
751
|
| `--no-cache` | download every list again (unchanged ones are normally skipped via ETag) |
|
|
745
752
|
| `--list-sources [N]` | show the source ranking (add `--json` for scripts: url, status, hit rate, checks, last change) |
|
|
753
|
+
| `--pick [N]` | print N proxies (default 1) from the hourly checked list and exit – no scan, same filters, plus `--min-uptime PERCENT` and `--works-on google,reddit,…` |
|
|
746
754
|
| `--serve-host ADDR` | where the proxy server listens (default `127.0.0.1`; `0.0.0.0` for Docker, with a warning) |
|
|
747
755
|
| `--serve-password SECRET` | clients must send this password in the proxy login; better set `PROXY_SCRAPER_SERVE_PASSWORD` |
|
|
748
756
|
| `--rotate STRATEGY` · `--sticky SEC` | how the proxy server picks proxies, see [above](#proxy-server) |
|
|
@@ -658,6 +658,13 @@ pip download requests # git, pip, npm & co. now go through the pool
|
|
|
658
658
|
|
|
659
659
|
`proxy` is the fastest one, `file` a text file with all of them (up to `limit`, default 20), `count` how many. Without a match the step fails, unless `fail-if-empty: false`.
|
|
660
660
|
|
|
661
|
+
**In the shell, without a scan** – `--pick` takes proxies from the hourly list in about half a second
|
|
662
|
+
|
|
663
|
+
```bash
|
|
664
|
+
curl -x "$(proxy-scraper --pick --https-only --min-uptime 90)" https://api.ipify.org
|
|
665
|
+
proxy-scraper --pick 10 --country DE --works-on google > de.txt
|
|
666
|
+
```
|
|
667
|
+
|
|
661
668
|
**Without installing anything** – straight from the live list
|
|
662
669
|
|
|
663
670
|
```bash
|
|
@@ -702,6 +709,7 @@ curl.exe -x (Get-Content "$run\all.txt" -TotalCount 1) http://api.ipify.org
|
|
|
702
709
|
| `--discover` | search GitHub for new sources right now |
|
|
703
710
|
| `--no-cache` | download every list again (unchanged ones are normally skipped via ETag) |
|
|
704
711
|
| `--list-sources [N]` | show the source ranking (add `--json` for scripts: url, status, hit rate, checks, last change) |
|
|
712
|
+
| `--pick [N]` | print N proxies (default 1) from the hourly checked list and exit – no scan, same filters, plus `--min-uptime PERCENT` and `--works-on google,reddit,…` |
|
|
705
713
|
| `--serve-host ADDR` | where the proxy server listens (default `127.0.0.1`; `0.0.0.0` for Docker, with a warning) |
|
|
706
714
|
| `--serve-password SECRET` | clients must send this password in the proxy login; better set `PROXY_SCRAPER_SERVE_PASSWORD` |
|
|
707
715
|
| `--rotate STRATEGY` · `--sticky SEC` | how the proxy server picks proxies, see [above](#proxy-server) |
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: proxy-scraper-cli
|
|
3
|
-
Version: 1.
|
|
3
|
+
Version: 1.14.0
|
|
4
4
|
Summary: Finds free HTTP, SOCKS4 and SOCKS5 proxies that actually work: 700+ sources, real checks, honeypot filtering and a rotating local proxy server.
|
|
5
5
|
Author: Maximilian Feix
|
|
6
6
|
License-Expression: MIT
|
|
@@ -699,6 +699,13 @@ pip download requests # git, pip, npm & co. now go through the pool
|
|
|
699
699
|
|
|
700
700
|
`proxy` is the fastest one, `file` a text file with all of them (up to `limit`, default 20), `count` how many. Without a match the step fails, unless `fail-if-empty: false`.
|
|
701
701
|
|
|
702
|
+
**In the shell, without a scan** – `--pick` takes proxies from the hourly list in about half a second
|
|
703
|
+
|
|
704
|
+
```bash
|
|
705
|
+
curl -x "$(proxy-scraper --pick --https-only --min-uptime 90)" https://api.ipify.org
|
|
706
|
+
proxy-scraper --pick 10 --country DE --works-on google > de.txt
|
|
707
|
+
```
|
|
708
|
+
|
|
702
709
|
**Without installing anything** – straight from the live list
|
|
703
710
|
|
|
704
711
|
```bash
|
|
@@ -743,6 +750,7 @@ curl.exe -x (Get-Content "$run\all.txt" -TotalCount 1) http://api.ipify.org
|
|
|
743
750
|
| `--discover` | search GitHub for new sources right now |
|
|
744
751
|
| `--no-cache` | download every list again (unchanged ones are normally skipped via ETag) |
|
|
745
752
|
| `--list-sources [N]` | show the source ranking (add `--json` for scripts: url, status, hit rate, checks, last change) |
|
|
753
|
+
| `--pick [N]` | print N proxies (default 1) from the hourly checked list and exit – no scan, same filters, plus `--min-uptime PERCENT` and `--works-on google,reddit,…` |
|
|
746
754
|
| `--serve-host ADDR` | where the proxy server listens (default `127.0.0.1`; `0.0.0.0` for Docker, with a warning) |
|
|
747
755
|
| `--serve-password SECRET` | clients must send this password in the proxy login; better set `PROXY_SCRAPER_SERVE_PASSWORD` |
|
|
748
756
|
| `--rotate STRATEGY` · `--sticky SEC` | how the proxy server picks proxies, see [above](#proxy-server) |
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
"""proxy-scraper: collects public HTTP/SOCKS4/SOCKS5 proxies from hundreds of sources, checks them
|
|
2
2
|
in parallel with its own protocol handshakes and learns which sources deliver good proxies."""
|
|
3
3
|
|
|
4
|
-
__version__ = "1.
|
|
4
|
+
__version__ = "1.14.0"
|
|
5
5
|
|
|
6
6
|
|
|
7
7
|
def __getattr__(name):
|
|
@@ -34,6 +34,7 @@ from .output import has_latest_results
|
|
|
34
34
|
from .parsing import PROXY_TYPES
|
|
35
35
|
from .preferences import load_last_argv, save_last_argv
|
|
36
36
|
from .server.pool import STRATEGIES
|
|
37
|
+
from .sites import SITES
|
|
37
38
|
from .targets import parse_target
|
|
38
39
|
from .ui import ACCENT, BAD, MUTED, banner, note, render_source_ranking, widgets
|
|
39
40
|
from .ui.keys import is_interactive
|
|
@@ -62,6 +63,36 @@ def list_sources(limit: int, as_json: bool = False) -> int:
|
|
|
62
63
|
return 0
|
|
63
64
|
|
|
64
65
|
|
|
66
|
+
def pick(args) -> int:
|
|
67
|
+
"""--pick: proxies from the hourly list, nothing but their URLs on stdout (for $(…) in a shell)."""
|
|
68
|
+
from .api import live_proxies
|
|
69
|
+
|
|
70
|
+
try:
|
|
71
|
+
found = live_proxies(types=args.types, countries=args.country or "", https=args.https_only,
|
|
72
|
+
anonymity=args.anonymity or "", max_latency=args.max_latency,
|
|
73
|
+
no_datacenter=args.no_datacenter, no_blocklisted=args.no_blocklisted,
|
|
74
|
+
min_uptime=args.min_uptime, works_on=args.works_on, limit=args.pick)
|
|
75
|
+
except (ConnectionError, ValueError) as e:
|
|
76
|
+
print(f"proxy-scraper: {e}", file=sys.stderr)
|
|
77
|
+
return 1
|
|
78
|
+
if not found:
|
|
79
|
+
print("proxy-scraper: no proxy in the live list matches these filters right now – loosen them, "
|
|
80
|
+
"or run a scan of your own", file=sys.stderr)
|
|
81
|
+
return 1
|
|
82
|
+
sys.stdout.write("".join(f"{p.url}\n" for p in found))
|
|
83
|
+
return 0
|
|
84
|
+
|
|
85
|
+
|
|
86
|
+
def site_list(text: str) -> List[str]:
|
|
87
|
+
"""argparse type for --works-on: google,reddit -> ["google", "reddit"]"""
|
|
88
|
+
names = [n.strip().lower() for n in text.split(",") if n.strip()]
|
|
89
|
+
known = [s.name for s in SITES]
|
|
90
|
+
for n in names:
|
|
91
|
+
if n not in known:
|
|
92
|
+
raise argparse.ArgumentTypeError(f"unknown site {n!r}, use {', '.join(known)}")
|
|
93
|
+
return names
|
|
94
|
+
|
|
95
|
+
|
|
65
96
|
def _number(kind, minimum, strict=False, maximum=None):
|
|
66
97
|
"""argparse type for numbers with limits – with an understandable error message."""
|
|
67
98
|
def parse(text: str):
|
|
@@ -96,6 +127,7 @@ def export_list(text: str) -> List[str]:
|
|
|
96
127
|
positive_int = _number(int, 1)
|
|
97
128
|
port_number = _number(int, 1, maximum=65535)
|
|
98
129
|
non_negative_int = _number(int, 0)
|
|
130
|
+
percent = _number(int, 0, maximum=100)
|
|
99
131
|
positive_float = _number(float, 0, strict=True)
|
|
100
132
|
non_negative_float = _number(float, 0)
|
|
101
133
|
|
|
@@ -166,6 +198,16 @@ def parse_args(argv: Optional[List[str]] = None) -> argparse.Namespace:
|
|
|
166
198
|
f.add_argument("--target", action="append", type=target_url, metavar="URL",
|
|
167
199
|
help="only proxies that reach this site (repeatable), e.g. --target google.com")
|
|
168
200
|
|
|
201
|
+
live = p.add_argument_group("Live list (no scan)")
|
|
202
|
+
live.add_argument("--pick", nargs="?", const=1, type=positive_int, metavar="N",
|
|
203
|
+
help="print N proxies (default 1) from the hourly checked list that match the filters above, "
|
|
204
|
+
"one URL per line, and exit – e.g. curl -x \"$(proxy-scraper --pick --https-only)\" …")
|
|
205
|
+
live.add_argument("--min-uptime", type=percent, default=0, metavar="PERCENT",
|
|
206
|
+
help="with --pick: only proxies on the list in at least this share of the week's checks")
|
|
207
|
+
live.add_argument("--works-on", type=site_list, default=[], metavar="SITES",
|
|
208
|
+
help=f"with --pick: only proxies that got through to these sites in the last check "
|
|
209
|
+
f"({', '.join(s.name for s in SITES)})")
|
|
210
|
+
|
|
169
211
|
v = p.add_argument_group("Proxy server")
|
|
170
212
|
v.add_argument("--serve", nargs="?", const=DEFAULT_SERVE_PORT, default=0, type=port_number, metavar="PORT",
|
|
171
213
|
help=f"serve the hits as a rotating proxy on 127.0.0.1:PORT after the run "
|
|
@@ -209,6 +251,14 @@ def parse_args(argv: Optional[List[str]] = None) -> argparse.Namespace:
|
|
|
209
251
|
args = p.parse_args(argv)
|
|
210
252
|
if args.json and args.list_sources is None:
|
|
211
253
|
p.error("--json only works together with --list-sources")
|
|
254
|
+
if (args.min_uptime or args.works_on) and args.pick is None:
|
|
255
|
+
p.error("--min-uptime and --works-on only work together with --pick")
|
|
256
|
+
if args.pick is not None: # --pick exits right away: options for a scan or the server would be silently ignored
|
|
257
|
+
scan_only = [flag for dest, flag in (("target", "--target"), ("serve", "--serve"), ("recheck", "--recheck"),
|
|
258
|
+
("want", "--want"), ("output", "-o/--output"), ("export", "--export"))
|
|
259
|
+
if getattr(args, dest) != p.get_default(dest)]
|
|
260
|
+
if scan_only:
|
|
261
|
+
p.error(f"--pick takes proxies from the live list and exits – {', '.join(scan_only)} belong to a scan")
|
|
212
262
|
return args
|
|
213
263
|
|
|
214
264
|
|
|
@@ -260,6 +310,8 @@ def run(argv: Optional[List[str]] = None) -> int:
|
|
|
260
310
|
return mcp_main()
|
|
261
311
|
if args.list_sources is not None:
|
|
262
312
|
return list_sources(args.list_sources, args.json)
|
|
313
|
+
if args.pick is not None:
|
|
314
|
+
return pick(args)
|
|
263
315
|
opts = RunOptions.from_args(args)
|
|
264
316
|
if opts.output == STDOUT:
|
|
265
317
|
widgets.console = Console(highlight=False, stderr=True) # stdout only carries the hits
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
"""proxy-scraper --pick: proxies from the hourly list on stdout, with the usual filters, no scan."""
|
|
2
|
+
|
|
3
|
+
import pytest
|
|
4
|
+
|
|
5
|
+
from proxyscraper import api, cli
|
|
6
|
+
from tests.test_live_api import ROWS, STATS, fetch_from
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
@pytest.fixture(autouse=True)
|
|
10
|
+
def offline(monkeypatch):
|
|
11
|
+
rows = [dict(ROWS[0], sites={"google": True}), ROWS[1], ROWS[2]]
|
|
12
|
+
monkeypatch.setattr(api, "_live_fetch", fetch_from({"proxies.json": rows, "stats.json": STATS}))
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
def test_one_proxy_by_default_and_nothing_else_on_stdout(capsys):
|
|
16
|
+
assert cli.run(["--pick"]) == 0
|
|
17
|
+
assert capsys.readouterr().out == "http://2.2.2.2:80\n" # the fastest
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
def test_the_usual_filters_apply(capsys):
|
|
21
|
+
assert cli.run(["--pick", "5", "--types", "socks4", "socks5", "--country", "DE", "--https-only"]) == 0
|
|
22
|
+
assert capsys.readouterr().out.splitlines() == ["socks4://3.3.3.3:4145", "socks5://1.1.1.1:1080"]
|
|
23
|
+
assert cli.run(["--pick", "--min-uptime", "90", "--works-on", "google"]) == 0
|
|
24
|
+
assert capsys.readouterr().out == "socks5://1.1.1.1:1080\n"
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
def test_nothing_matching_is_exit_1_with_a_hint_on_stderr(capsys):
|
|
28
|
+
assert cli.run(["--pick", "--country", "JP"]) == 1
|
|
29
|
+
out = capsys.readouterr()
|
|
30
|
+
assert out.out == "" and "no proxy" in out.err.lower()
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
def test_pick_only_filters_need_pick(capsys):
|
|
34
|
+
with pytest.raises(SystemExit):
|
|
35
|
+
cli.run(["--min-uptime", "90"])
|
|
36
|
+
assert "--pick" in capsys.readouterr().err
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
@pytest.mark.parametrize("extra", [["--target", "discord.com"], ["--serve"], ["--recheck"], ["--want", "5"],
|
|
40
|
+
["-o", "x.txt"], ["--export", "clash"]])
|
|
41
|
+
def test_options_for_a_scan_are_an_error_not_ignored(extra, capsys):
|
|
42
|
+
with pytest.raises(SystemExit):
|
|
43
|
+
cli.run(["--pick", *extra])
|
|
44
|
+
assert "--pick" in capsys.readouterr().err
|
|
File without changes
|
|
File without changes
|
{proxy_scraper_cli-1.13.0 → proxy_scraper_cli-1.14.0}/proxy_scraper_cli.egg-info/entry_points.txt
RENAMED
|
File without changes
|
{proxy_scraper_cli-1.13.0 → proxy_scraper_cli-1.14.0}/proxy_scraper_cli.egg-info/requires.txt
RENAMED
|
File without changes
|
{proxy_scraper_cli-1.13.0 → proxy_scraper_cli-1.14.0}/proxy_scraper_cli.egg-info/top_level.txt
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{proxy_scraper_cli-1.13.0 → proxy_scraper_cli-1.14.0}/proxyscraper/site/apple-touch-icon.png
RENAMED
|
File without changes
|
{proxy_scraper_cli-1.13.0 → proxy_scraper_cli-1.14.0}/proxyscraper/site/googleaac1161b7853c5b5.html
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|