Skip to content

Commit 0fb7b9a

Browse files
committed
bump docs
1 parent 8831f70 commit 0fb7b9a

File tree

5 files changed

+116
-17
lines changed

5 files changed

+116
-17
lines changed

README.md

Lines changed: 107 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@ Unified python interface for proxy provider APIs, supports BrightData, WebShare,
99
- [Getting Started](#getting-started)
1010
- [How to Support The Project](#how-to-support-the-project)
1111
- [Installing](#installing)
12-
- [Common Issues](#common-issues)
1312
- [Quick Start Guide](#quick-start-guide)
1413
- [Examples](https://github.com/davidteather/proxyproviders/tree/main/examples)
1514

@@ -39,5 +38,112 @@ python -m pip install proxyproviders
3938

4039
## Quick Start Guide
4140

41+
Here's a quick bit of code to get you started! There's also a few [examples in the folder](https://github.com/davidteather/proxyproviders/tree/main/examples).
4242

43+
**Note:** If you want to learn how to web scrape websites check my [free and open-source course for learning everything web scraping](https://github.com/davidteather/everything-web-scraping)
44+
45+
### Choose a Proxy Provider
46+
47+
If you already haven't, choose which proxy provider to use. You can find a [list in the documentation](https://davidteather.github.io/proxyproviders/#proxyproviders-supported-providers). After choosing, look at the documentation around the specific provider you've choosen. Where needed, we've laid out steps to get api keys in the documentation. These steps will vary slightly by provider. For this example I'll be using the [Webshare Provider](https://davidteather.github.io/proxyproviders/#proxyproviders.providers.webshare.Webshare) because it's both easy to setup and they give you 10 free data center proxies to test out.
48+
49+
You can create an account on webshare [here](https://www.webshare.io/?referral_code=3x5812idzzzp) (affiliate link), then head into the [API tab](https://dashboard.webshare.io/userapi/keys) on the side and generate a new token. Keep this API token safe and don't post it publically.
50+
51+
### Basic Example
52+
53+
After you can list out your proxies with
54+
```py
55+
from proxyproviders import Webshare
56+
57+
proxy_provider = Webshare(api_key="your-api-key")
58+
59+
proxies = proxy_provider.list_proxies()
60+
61+
print(proxies)
62+
```
63+
64+
Each provider has their own custom options, the `Webshare` class lets you specify url params according to their [api spec](https://apidocs.webshare.io/proxy-list/list#parameters), here's an example which will only return proxies that are based in the US.
65+
66+
```py
67+
proxy_provider = Webshare(api_key="your-api-key", params={"country_code_in": "US"})
68+
```
69+
70+
### Using ProxyConfig
71+
72+
For any shared logic across all types of proxy providers, we use the `ProxyConfig` data class to configure them. The full docs for [ProxyConfig are here](https://davidteather.github.io/proxyproviders/#proxyproviders.proxy_provider.ProxyConfig). In this example we will configure it to use a shorter `refresh_interval` than default.
73+
74+
```py
75+
from proxyproviders import Webshare, ProxyConfig
76+
import time
77+
78+
config = ProxyConfig(refresh_interval=3)
79+
ws = Webshare(api_key="your-api-token", config=config)
80+
81+
proxies = ws.list_proxies() # calls API
82+
83+
ws.list_proxies() # cached
84+
85+
time.sleep(5)
86+
ws.list_proxies() # calls API since it's more than 3s later
87+
```
88+
89+
### Function Using Generic ProxyProvider
90+
91+
Since all proxy providers implement the same interface, we can make a function that allows us to easily swap out and utilize different providers. This is the main appeal of having a unified interface. It allows other modules to be provider agnostic, like my [TikTokAPI](https://github.com/davidteather/TikTok-Api) package.
92+
93+
```py
94+
from proxyproviders import Webshare, ProxyProvider, ProxyConfig
95+
96+
def some_function(provider: ProxyProvider):
97+
proxies = provider.list_proxies()
98+
print(proxies)
99+
100+
webshare = Webshare(api_key="your_api_key")
101+
brightdata = BrightData(api_key="your_api_key")
102+
103+
some_function(webshare)
104+
some_function(brightdata)
105+
```
106+
107+
### Making Your Own Proxy Provider
108+
109+
Here's a skeleton of how you can make your very own `ProxyProvider` class. You'll need to implemenet all the required functions of the `ProxyProvider` which may be more than what's here at the time of writing.
110+
111+
If you do find yourself making one of these, consider contributing it back to the repository so everyone can use them :D
112+
113+
```py
114+
from proxyproviders import ProxyProvider, ProxyConfig, Proxy
115+
from typing import List, Optional
116+
117+
class MyProxyProvider(ProxyProvider):
118+
def __init__(self, config: Optional[ProxyConfig] = None):
119+
super().__init__(config=config)
120+
121+
def _fetch_proxies(self):
122+
proxies: List[Proxy] = []
123+
124+
for i in range(10):
125+
# TODO: your real proxy fetching logic
126+
127+
# There are required fields on the Proxy class, be sure that these are filled out properly
128+
# especially if you're using it with another library.
129+
proxy = Proxy(
130+
id=str(i),
131+
username="username",
132+
password="password",
133+
proxy_address="192.168.1.1",
134+
port=80,
135+
)
136+
137+
proxies.append(proxy)
138+
139+
return proxies
140+
141+
def some_function(provider: ProxyProvider):
142+
proxies = provider.list_proxies()
143+
for proxy in proxies:
144+
print(proxy)
145+
146+
provider = MyProxyProvider()
147+
some_function(provider) # calls the function with the provider
148+
```
43149

proxyproviders/models/proxy.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -21,14 +21,14 @@ class Proxy:
2121
port: int
2222
"""The port number through which the proxy connection is established"""
2323

24-
country_code: Optional[str]
24+
country_code: Optional[str] = None
2525
"""The country code where the proxy is located, e.g., 'US', 'FR'. Optional"""
2626

27-
city_name: Optional[str]
27+
city_name: Optional[str] = None
2828
"""The city name where the proxy is located, e.g., 'New York', 'Paris'. Optional"""
2929

30-
created_at: Optional[datetime]
30+
created_at: Optional[datetime] = None
3131
"""The timestamp when the proxy was created. Optional"""
3232

33-
protocols: List[str]
33+
protocols: List[str] = None
3434
"""A list of connection protocols supported by the proxy, e.g., ['http', 'https']"""

proxyproviders/providers/webshare.py

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ class Webshare(ProxyProvider):
2828
proxy_provider = Webshare(api_key="your-api-key", params={"country_code_in": "US"})
2929
3030
# Fetch proxies
31-
proxies = proxy_provider.fetch_proxies()
31+
proxies = proxy_provider.list_proxies()
3232
3333
# With config
3434
from proxyproviders import ProxyConfig
@@ -37,7 +37,7 @@ class Webshare(ProxyProvider):
3737
proxy_provider = Webshare(api_key="your-api-key", params={"country_code_in": "US"}, config=config)
3838
3939
# Fetch proxies
40-
proxies = proxy_provider.fetch_proxies()
40+
proxies = proxy_provider.list_proxies()
4141
"""
4242
_BASE_URL = "https://proxy.webshare.io/api/v2"
4343
_PROTOCOLS = ["http", "https"]
@@ -80,7 +80,6 @@ def _fetch_proxies(self) -> List[Proxy]:
8080
if data.get("next") is None: # no more pages
8181
break
8282

83-
self._set_proxies(all_proxies)
8483
return all_proxies
8584

8685
def _convert_to_proxy(self, data: Dict) -> Proxy:

proxyproviders/proxy_provider.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,8 @@ def list_proxies(self, force_refresh: bool = False) -> List[Proxy]:
4949
:param force_refresh: If True, fetches new proxies even if the list is not considered stale.
5050
"""
5151
if force_refresh or self.should_refresh() or not self._proxies:
52-
self._fetch_proxies()
52+
proxies = self._fetch_proxies()
53+
self._set_proxies(proxies)
5354

5455
with self._lock:
5556
return list(self._proxies) if self._proxies else []
@@ -59,7 +60,7 @@ def list_proxies(self, force_refresh: bool = False) -> List[Proxy]:
5960
#
6061
@abstractmethod
6162
def _fetch_proxies(self) -> List[Proxy]:
62-
"""Fetch proxies from the provider and calls super()._set_proxies().
63+
"""Fetch proxies from the provider implementation.
6364
This is not meant to be called directly, as it will always pull from the API even if not stale.
6465
"""
6566
pass

tests/test_proxy_provider.py

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,6 @@ def test_force_refresh():
3838
class TestProxyProvider(MockProxyProvider):
3939
def _fetch_proxies(self) -> List[Proxy]:
4040
proxies = [1, 2, 3]
41-
self._set_proxies(proxies)
4241
return proxies
4342

4443
provider = TestProxyProvider()
@@ -62,12 +61,6 @@ def test_refresh_interval():
6261
# When refresh_interval is 0, it should never refresh automatically
6362
provider = MockProxyProvider(config=ProxyConfig(refresh_interval=0))
6463
provider._fetch_proxies = lambda: [1, 2, 3]
65-
66-
# No proxies initially, so should be an empty list
67-
assert provider.list_proxies() == []
68-
69-
# Proxies should not refresh even after calling list_proxies
70-
assert provider.list_proxies() == []
7164

7265
# Simulate a fetch and set proxies to check refresh
7366
provider._set_proxies([1, 2, 3])

0 commit comments

Comments
 (0)