proxyherd 1.0.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.
- proxyherd-1.0.0/LICENCE +17 -0
- proxyherd-1.0.0/MANIFEST.in +4 -0
- proxyherd-1.0.0/PKG-INFO +40 -0
- proxyherd-1.0.0/README.md +17 -0
- proxyherd-1.0.0/proxyherd/__init__.py +5 -0
- proxyherd-1.0.0/proxyherd/api.py +72 -0
- proxyherd-1.0.0/proxyherd/blacklist.py +76 -0
- proxyherd-1.0.0/proxyherd/proxy.py +40 -0
- proxyherd-1.0.0/proxyherd/scale.py +42 -0
- proxyherd-1.0.0/proxyherd/sticky.py +14 -0
- proxyherd-1.0.0/proxyherd.egg-info/PKG-INFO +40 -0
- proxyherd-1.0.0/proxyherd.egg-info/SOURCES.txt +21 -0
- proxyherd-1.0.0/proxyherd.egg-info/dependency_links.txt +1 -0
- proxyherd-1.0.0/proxyherd.egg-info/top_level.txt +2 -0
- proxyherd-1.0.0/scrapoxy/__init__.py +18 -0
- proxyherd-1.0.0/scrapoxy/api.py +2 -0
- proxyherd-1.0.0/scrapoxy/blacklist.py +1 -0
- proxyherd-1.0.0/scrapoxy/proxy.py +1 -0
- proxyherd-1.0.0/scrapoxy/scale.py +1 -0
- proxyherd-1.0.0/scrapoxy/sticky.py +1 -0
- proxyherd-1.0.0/setup.cfg +7 -0
- proxyherd-1.0.0/setup.py +24 -0
proxyherd-1.0.0/LICENCE
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
# The MIT License (MIT)
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2016-present Fabien Vauchelles
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy of this software
|
|
6
|
+
and associated documentation files (the "Software"), to deal in the Software without restriction,
|
|
7
|
+
including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
|
8
|
+
and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so,
|
|
9
|
+
subject to the following conditions:
|
|
10
|
+
|
|
11
|
+
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
|
12
|
+
|
|
13
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
|
|
14
|
+
INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
|
15
|
+
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
|
16
|
+
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR
|
|
17
|
+
THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
proxyherd-1.0.0/PKG-INFO
ADDED
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: proxyherd
|
|
3
|
+
Version: 1.0.0
|
|
4
|
+
Summary: Python API and Scrapy middlewares for ProxyHerd, the open-source super proxy manager
|
|
5
|
+
Home-page: https://github.com/proxyherd/proxyherd
|
|
6
|
+
Author: ProxyHerd maintainers
|
|
7
|
+
License: MIT
|
|
8
|
+
Keywords: crawler,crawling,proxyherd,scrapoxy,scrapy,scraper,scraping,webscraping,proxy
|
|
9
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
10
|
+
Classifier: Programming Language :: Python :: 3
|
|
11
|
+
Classifier: Framework :: Scrapy
|
|
12
|
+
Description-Content-Type: text/markdown
|
|
13
|
+
License-File: LICENCE
|
|
14
|
+
Dynamic: author
|
|
15
|
+
Dynamic: classifier
|
|
16
|
+
Dynamic: description
|
|
17
|
+
Dynamic: description-content-type
|
|
18
|
+
Dynamic: home-page
|
|
19
|
+
Dynamic: keywords
|
|
20
|
+
Dynamic: license
|
|
21
|
+
Dynamic: license-file
|
|
22
|
+
Dynamic: summary
|
|
23
|
+
|
|
24
|
+
# Python API for ProxyHerd
|
|
25
|
+
|
|
26
|
+
Scrapy middlewares and a small REST client for [ProxyHerd](https://proxyherd.github.io/proxyherd/),
|
|
27
|
+
the open-source super proxy manager.
|
|
28
|
+
|
|
29
|
+
```shell
|
|
30
|
+
pip install proxyherd
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
Documentation: https://proxyherd.github.io/proxyherd/integration/python/scrapy/guide
|
|
34
|
+
|
|
35
|
+
## Migrating from the `scrapoxy` package
|
|
36
|
+
|
|
37
|
+
`proxyherd` is the continuation of the `scrapoxy` Python package (community fork of Scrapoxy 4.17.4).
|
|
38
|
+
The module `proxyherd` exposes the same middlewares; the settings are now prefixed `PROXYHERD_`
|
|
39
|
+
(`PROXYHERD_MASTER`, `PROXYHERD_API`, `PROXYHERD_USERNAME`, `PROXYHERD_PASSWORD`, ...).
|
|
40
|
+
The old `SCRAPOXY_` settings and the `scrapoxy` module keep working as deprecated aliases.
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
# Python API for ProxyHerd
|
|
2
|
+
|
|
3
|
+
Scrapy middlewares and a small REST client for [ProxyHerd](https://proxyherd.github.io/proxyherd/),
|
|
4
|
+
the open-source super proxy manager.
|
|
5
|
+
|
|
6
|
+
```shell
|
|
7
|
+
pip install proxyherd
|
|
8
|
+
```
|
|
9
|
+
|
|
10
|
+
Documentation: https://proxyherd.github.io/proxyherd/integration/python/scrapy/guide
|
|
11
|
+
|
|
12
|
+
## Migrating from the `scrapoxy` package
|
|
13
|
+
|
|
14
|
+
`proxyherd` is the continuation of the `scrapoxy` Python package (community fork of Scrapoxy 4.17.4).
|
|
15
|
+
The module `proxyherd` exposes the same middlewares; the settings are now prefixed `PROXYHERD_`
|
|
16
|
+
(`PROXYHERD_MASTER`, `PROXYHERD_API`, `PROXYHERD_USERNAME`, `PROXYHERD_PASSWORD`, ...).
|
|
17
|
+
The old `SCRAPOXY_` settings and the `scrapoxy` module keep working as deprecated aliases.
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
from base64 import b64encode
|
|
2
|
+
from urllib.request import Request, urlopen
|
|
3
|
+
from typing import TypedDict, List
|
|
4
|
+
|
|
5
|
+
import json
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
def is_proxy_online(proxy):
|
|
9
|
+
return (
|
|
10
|
+
proxy['status'] == 'STARTED' and
|
|
11
|
+
proxy['fingerprint'] and
|
|
12
|
+
not proxy['removing']
|
|
13
|
+
)
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
class IProxyToRemove(TypedDict):
|
|
17
|
+
id: str
|
|
18
|
+
force: bool
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
class ProxyHerdApi:
|
|
22
|
+
def __init__(self, url: str, username: str, password: str):
|
|
23
|
+
self._url = f"{url}/scraper"
|
|
24
|
+
self._token = b64encode(f"{username}:{password}".encode("utf-8")).decode("utf-8")
|
|
25
|
+
|
|
26
|
+
def get_project(self):
|
|
27
|
+
req = Request(
|
|
28
|
+
url=f"{self._url}/project",
|
|
29
|
+
headers={
|
|
30
|
+
"Authorization": f"Basic {self._token}"
|
|
31
|
+
}
|
|
32
|
+
)
|
|
33
|
+
contents = urlopen(req).read()
|
|
34
|
+
return json.loads(contents)
|
|
35
|
+
|
|
36
|
+
def set_project_status(self, status: str):
|
|
37
|
+
payload = {"status": status}
|
|
38
|
+
req = Request(
|
|
39
|
+
url = f"{self._url}/project/status",
|
|
40
|
+
method="POST",
|
|
41
|
+
headers={
|
|
42
|
+
"Authorization": f"Basic {self._token}",
|
|
43
|
+
"Content-Type": "application/json"
|
|
44
|
+
},
|
|
45
|
+
data=json.dumps(payload).encode("utf-8")
|
|
46
|
+
)
|
|
47
|
+
urlopen(req).read()
|
|
48
|
+
|
|
49
|
+
def get_all_project_connectors_and_proxies(self):
|
|
50
|
+
req = Request(
|
|
51
|
+
url=f"{self._url}/project/connectors",
|
|
52
|
+
headers={
|
|
53
|
+
"Authorization": f"Basic {self._token}"
|
|
54
|
+
}
|
|
55
|
+
)
|
|
56
|
+
contents = urlopen(req).read()
|
|
57
|
+
return json.loads(contents)
|
|
58
|
+
|
|
59
|
+
def ask_proxies_to_remove(self, proxies_ids: List[IProxyToRemove]):
|
|
60
|
+
req = Request(
|
|
61
|
+
url=f"{self._url}/project/proxies/remove",
|
|
62
|
+
method="POST",
|
|
63
|
+
headers={
|
|
64
|
+
"Authorization": f"Basic {self._token}",
|
|
65
|
+
"Content-Type": "application/json"
|
|
66
|
+
},
|
|
67
|
+
data=json.dumps(proxies_ids).encode("utf-8")
|
|
68
|
+
)
|
|
69
|
+
urlopen(req).read()
|
|
70
|
+
|
|
71
|
+
# Backward-compatible alias (the package was named scrapoxy before 1.0.0)
|
|
72
|
+
ScrapoxyApi = ProxyHerdApi
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
from random import randrange
|
|
2
|
+
from scrapy.exceptions import IgnoreRequest
|
|
3
|
+
from proxyherd.api import ProxyHerdApi, is_proxy_online
|
|
4
|
+
from time import sleep
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
class BlacklistError(Exception):
|
|
8
|
+
def __init__(self, response, message, *args, **kwargs):
|
|
9
|
+
super(BlacklistError, self).__init__(*args, **kwargs)
|
|
10
|
+
|
|
11
|
+
self.response = response
|
|
12
|
+
self.message = message
|
|
13
|
+
|
|
14
|
+
def __str__(self):
|
|
15
|
+
return self.message
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
class BlacklistDownloaderMiddleware(object):
|
|
19
|
+
|
|
20
|
+
@classmethod
|
|
21
|
+
def from_crawler(cls, crawler):
|
|
22
|
+
return cls(crawler)
|
|
23
|
+
|
|
24
|
+
def __init__(self, crawler):
|
|
25
|
+
"""Access the settings of the crawler to connect to ProxyHerd.
|
|
26
|
+
"""
|
|
27
|
+
api = crawler.settings.get("PROXYHERD_API", crawler.settings.get("SCRAPOXY_API"))
|
|
28
|
+
assert api, "PROXYHERD_API is required"
|
|
29
|
+
|
|
30
|
+
username = crawler.settings.get("PROXYHERD_USERNAME", crawler.settings.get("SCRAPOXY_USERNAME"))
|
|
31
|
+
assert username, "PROXYHERD_USERNAME is required"
|
|
32
|
+
|
|
33
|
+
password = crawler.settings.get("PROXYHERD_PASSWORD", crawler.settings.get("SCRAPOXY_PASSWORD"))
|
|
34
|
+
assert password, "PROXYHERD_PASSWORD is required"
|
|
35
|
+
|
|
36
|
+
self._api = ProxyHerdApi(api, username, password)
|
|
37
|
+
|
|
38
|
+
self._http_status_codes = crawler.settings.get("PROXYHERD_BLACKLIST_HTTP_STATUS_CODES", crawler.settings.get("SCRAPOXY_BLACKLIST_HTTP_STATUS_CODES", [429, 503]))
|
|
39
|
+
self._force = crawler.settings.get("PROXYHERD_BLACKLIST_FORCE", crawler.settings.get("SCRAPOXY_BLACKLIST_FORCE", True))
|
|
40
|
+
self._sleep_min = crawler.settings.get("PROXYHERD_SLEEP_MIN", crawler.settings.get("SCRAPOXY_SLEEP_MIN", 60))
|
|
41
|
+
self._sleep_max = crawler.settings.get("PROXYHERD_SLEEP_MAX", crawler.settings.get("SCRAPOXY_SLEEP_MAX", 180))
|
|
42
|
+
|
|
43
|
+
def process_response(self, request, response, spider):
|
|
44
|
+
if response.status not in self._http_status_codes:
|
|
45
|
+
return response
|
|
46
|
+
|
|
47
|
+
spider.logger.info("Ignoring Blacklisted response %s: HTTP status %d" % (response.url, response.status))
|
|
48
|
+
|
|
49
|
+
id_raw = response.headers.get("x-scrapoxy-proxyname")
|
|
50
|
+
if not id_raw:
|
|
51
|
+
raise BlacklistError(response, "No header 'X-Scrapoxy-Proxyname' name in response headers. MITM must be enabled")
|
|
52
|
+
|
|
53
|
+
id = id_raw.decode("utf-8")
|
|
54
|
+
|
|
55
|
+
alive_count = 0
|
|
56
|
+
views = self._api.get_all_project_connectors_and_proxies()
|
|
57
|
+
for view in views:
|
|
58
|
+
for proxy in view["proxies"]:
|
|
59
|
+
if (proxy["id"] != id and is_proxy_online(proxy)):
|
|
60
|
+
alive_count += 1
|
|
61
|
+
|
|
62
|
+
spider.logger.error("Remove instance %s (remaining %d instances)." % (response.url, response.status))
|
|
63
|
+
|
|
64
|
+
self._api.ask_proxies_to_remove([
|
|
65
|
+
{
|
|
66
|
+
"id": id,
|
|
67
|
+
"force": self._force
|
|
68
|
+
}
|
|
69
|
+
])
|
|
70
|
+
|
|
71
|
+
if alive_count <= 0:
|
|
72
|
+
delay = randrange(self._sleep_min, self._sleep_max)
|
|
73
|
+
spider.logger.warn("No instance remaining. Sleep for %d seconds..." % delay)
|
|
74
|
+
sleep(delay)
|
|
75
|
+
|
|
76
|
+
raise IgnoreRequest()
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
from base64 import b64encode
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
class ProxyDownloaderMiddleware(object):
|
|
5
|
+
|
|
6
|
+
@classmethod
|
|
7
|
+
def from_crawler(cls, crawler):
|
|
8
|
+
return cls(crawler)
|
|
9
|
+
|
|
10
|
+
def __init__(self, crawler):
|
|
11
|
+
master = crawler.settings.get("PROXYHERD_MASTER", crawler.settings.get("SCRAPOXY_MASTER"))
|
|
12
|
+
if master:
|
|
13
|
+
self._proxy = f"{master}/?noconnect"
|
|
14
|
+
|
|
15
|
+
username = crawler.settings.get("PROXYHERD_USERNAME", crawler.settings.get("SCRAPOXY_USERNAME"))
|
|
16
|
+
password = crawler.settings.get("PROXYHERD_PASSWORD", crawler.settings.get("SCRAPOXY_PASSWORD"))
|
|
17
|
+
if username and password:
|
|
18
|
+
auth_b64 = b64encode(f"{username}:{password}".encode("utf-8")).decode("utf-8")
|
|
19
|
+
self._proxy_auth = (username, password)
|
|
20
|
+
self._proxy_auth_b64 = f"Basic {auth_b64}"
|
|
21
|
+
|
|
22
|
+
def process_request(self, request, spider):
|
|
23
|
+
if request.meta.get("no-proxy"):
|
|
24
|
+
return
|
|
25
|
+
|
|
26
|
+
# Don"t overwrite with a random one (server-side state for IP)
|
|
27
|
+
if hasattr(self, "_proxy"):
|
|
28
|
+
request.meta["proxy"] = self._proxy
|
|
29
|
+
|
|
30
|
+
if hasattr(self, "_proxy_auth"):
|
|
31
|
+
request.headers["proxy-authorization"] = self._proxy_auth_b64
|
|
32
|
+
|
|
33
|
+
if request.meta.get("impersonate"):
|
|
34
|
+
impersonate_args = request.meta.get("impersonate_args", {})
|
|
35
|
+
impersonate_args["verify"] = False
|
|
36
|
+
|
|
37
|
+
if hasattr(self, "_proxy_auth"):
|
|
38
|
+
impersonate_args["proxy_auth"] = self._proxy_auth
|
|
39
|
+
|
|
40
|
+
request.meta["impersonate_args"] = impersonate_args
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
from scrapy import signals
|
|
2
|
+
from proxyherd.api import ProxyHerdApi
|
|
3
|
+
from time import sleep
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class ScaleSpiderMiddleware(object):
|
|
7
|
+
|
|
8
|
+
@classmethod
|
|
9
|
+
def from_crawler(cls, crawler):
|
|
10
|
+
return cls(crawler)
|
|
11
|
+
|
|
12
|
+
def __init__(self, crawler):
|
|
13
|
+
api = crawler.settings.get("PROXYHERD_API", crawler.settings.get("SCRAPOXY_API"))
|
|
14
|
+
assert api, "PROXYHERD_API is required"
|
|
15
|
+
|
|
16
|
+
username = crawler.settings.get("PROXYHERD_USERNAME", crawler.settings.get("SCRAPOXY_USERNAME"))
|
|
17
|
+
assert username, "PROXYHERD_USERNAME is required"
|
|
18
|
+
|
|
19
|
+
password = crawler.settings.get("PROXYHERD_PASSWORD", crawler.settings.get("SCRAPOXY_PASSWORD"))
|
|
20
|
+
assert password, "PROXYHERD_PASSWORD is required"
|
|
21
|
+
|
|
22
|
+
self._api = ProxyHerdApi(api, username, password)
|
|
23
|
+
|
|
24
|
+
self._delay = crawler.settings.get("PROXYHERD_WAIT_FOR_SCALE", crawler.settings.get("SCRAPOXY_WAIT_FOR_SCALE", 120))
|
|
25
|
+
|
|
26
|
+
crawler.signals.connect(self.spider_opened, signals.spider_opened)
|
|
27
|
+
crawler.signals.connect(self.spider_closed, signals.spider_closed)
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
def spider_opened(self, spider):
|
|
31
|
+
spider.logger.info("[ScaleSpiderMiddleware] Upscale ProxyHerd")
|
|
32
|
+
|
|
33
|
+
self._api.set_project_status("HOT")
|
|
34
|
+
|
|
35
|
+
spider.logger.info("[ScaleSpiderMiddleware] Sleeping %d seconds to finish upscale" % self._delay)
|
|
36
|
+
sleep(self._delay)
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
def spider_closed(self, spider):
|
|
40
|
+
spider.logger.info("[ScaleSpiderMiddleware] Downscale ProxyHerd")
|
|
41
|
+
|
|
42
|
+
self._api.set_project_status("OFF")
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
from scrapy import Request
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
class StickySpiderMiddleware:
|
|
5
|
+
# Propagate proxyname between responses and requests to have sticky session
|
|
6
|
+
def process_spider_output(self, response, result, spider):
|
|
7
|
+
proxyname = response.headers.get("x-scrapoxy-proxyname")
|
|
8
|
+
if proxyname:
|
|
9
|
+
for r in result:
|
|
10
|
+
if isinstance(r, Request):
|
|
11
|
+
r.headers["x-scrapoxy-proxyname"] = proxyname
|
|
12
|
+
yield r
|
|
13
|
+
else:
|
|
14
|
+
yield from result
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: proxyherd
|
|
3
|
+
Version: 1.0.0
|
|
4
|
+
Summary: Python API and Scrapy middlewares for ProxyHerd, the open-source super proxy manager
|
|
5
|
+
Home-page: https://github.com/proxyherd/proxyherd
|
|
6
|
+
Author: ProxyHerd maintainers
|
|
7
|
+
License: MIT
|
|
8
|
+
Keywords: crawler,crawling,proxyherd,scrapoxy,scrapy,scraper,scraping,webscraping,proxy
|
|
9
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
10
|
+
Classifier: Programming Language :: Python :: 3
|
|
11
|
+
Classifier: Framework :: Scrapy
|
|
12
|
+
Description-Content-Type: text/markdown
|
|
13
|
+
License-File: LICENCE
|
|
14
|
+
Dynamic: author
|
|
15
|
+
Dynamic: classifier
|
|
16
|
+
Dynamic: description
|
|
17
|
+
Dynamic: description-content-type
|
|
18
|
+
Dynamic: home-page
|
|
19
|
+
Dynamic: keywords
|
|
20
|
+
Dynamic: license
|
|
21
|
+
Dynamic: license-file
|
|
22
|
+
Dynamic: summary
|
|
23
|
+
|
|
24
|
+
# Python API for ProxyHerd
|
|
25
|
+
|
|
26
|
+
Scrapy middlewares and a small REST client for [ProxyHerd](https://proxyherd.github.io/proxyherd/),
|
|
27
|
+
the open-source super proxy manager.
|
|
28
|
+
|
|
29
|
+
```shell
|
|
30
|
+
pip install proxyherd
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
Documentation: https://proxyherd.github.io/proxyherd/integration/python/scrapy/guide
|
|
34
|
+
|
|
35
|
+
## Migrating from the `scrapoxy` package
|
|
36
|
+
|
|
37
|
+
`proxyherd` is the continuation of the `scrapoxy` Python package (community fork of Scrapoxy 4.17.4).
|
|
38
|
+
The module `proxyherd` exposes the same middlewares; the settings are now prefixed `PROXYHERD_`
|
|
39
|
+
(`PROXYHERD_MASTER`, `PROXYHERD_API`, `PROXYHERD_USERNAME`, `PROXYHERD_PASSWORD`, ...).
|
|
40
|
+
The old `SCRAPOXY_` settings and the `scrapoxy` module keep working as deprecated aliases.
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
LICENCE
|
|
2
|
+
MANIFEST.in
|
|
3
|
+
README.md
|
|
4
|
+
setup.cfg
|
|
5
|
+
setup.py
|
|
6
|
+
proxyherd/__init__.py
|
|
7
|
+
proxyherd/api.py
|
|
8
|
+
proxyherd/blacklist.py
|
|
9
|
+
proxyherd/proxy.py
|
|
10
|
+
proxyherd/scale.py
|
|
11
|
+
proxyherd/sticky.py
|
|
12
|
+
proxyherd.egg-info/PKG-INFO
|
|
13
|
+
proxyherd.egg-info/SOURCES.txt
|
|
14
|
+
proxyherd.egg-info/dependency_links.txt
|
|
15
|
+
proxyherd.egg-info/top_level.txt
|
|
16
|
+
scrapoxy/__init__.py
|
|
17
|
+
scrapoxy/api.py
|
|
18
|
+
scrapoxy/blacklist.py
|
|
19
|
+
scrapoxy/proxy.py
|
|
20
|
+
scrapoxy/scale.py
|
|
21
|
+
scrapoxy/sticky.py
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
"""Compatibility shim.
|
|
2
|
+
|
|
3
|
+
The ``scrapoxy`` Python package continues as ``proxyherd`` (community fork of Scrapoxy 4.17.4).
|
|
4
|
+
Importing ``scrapoxy`` still works but is deprecated; import ``proxyherd`` instead.
|
|
5
|
+
"""
|
|
6
|
+
import warnings
|
|
7
|
+
|
|
8
|
+
from proxyherd.api import ProxyHerdApi, ProxyHerdApi as ScrapoxyApi, is_proxy_online # noqa: F401
|
|
9
|
+
from proxyherd.blacklist import BlacklistDownloaderMiddleware # noqa: F401
|
|
10
|
+
from proxyherd.proxy import ProxyDownloaderMiddleware # noqa: F401
|
|
11
|
+
from proxyherd.scale import ScaleSpiderMiddleware # noqa: F401
|
|
12
|
+
from proxyherd.sticky import StickySpiderMiddleware # noqa: F401
|
|
13
|
+
|
|
14
|
+
warnings.warn(
|
|
15
|
+
"The 'scrapoxy' module is deprecated; import 'proxyherd' instead.",
|
|
16
|
+
DeprecationWarning,
|
|
17
|
+
stacklevel=2,
|
|
18
|
+
)
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
from proxyherd.blacklist import * # noqa: F401,F403
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
from proxyherd.proxy import * # noqa: F401,F403
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
from proxyherd.scale import * # noqa: F401,F403
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
from proxyherd.sticky import * # noqa: F401,F403
|
proxyherd-1.0.0/setup.py
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
try:
|
|
2
|
+
from setuptools import setup, find_packages
|
|
3
|
+
except ImportError:
|
|
4
|
+
from distutils.core import setup, find_packages
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
setup(
|
|
8
|
+
name='proxyherd',
|
|
9
|
+
packages=find_packages(),
|
|
10
|
+
install_requires=[],
|
|
11
|
+
version='1.0.0',
|
|
12
|
+
description='Python API and Scrapy middlewares for ProxyHerd, the open-source super proxy manager',
|
|
13
|
+
long_description=open('README.md').read(),
|
|
14
|
+
long_description_content_type='text/markdown',
|
|
15
|
+
author='ProxyHerd maintainers',
|
|
16
|
+
url='https://github.com/proxyherd/proxyherd',
|
|
17
|
+
license='MIT',
|
|
18
|
+
keywords=['crawler', 'crawling', 'proxyherd', 'scrapoxy', 'scrapy', 'scraper', 'scraping', 'webscraping', 'proxy'],
|
|
19
|
+
classifiers=[
|
|
20
|
+
'License :: OSI Approved :: MIT License',
|
|
21
|
+
'Programming Language :: Python :: 3',
|
|
22
|
+
'Framework :: Scrapy',
|
|
23
|
+
],
|
|
24
|
+
)
|