Skip to content
This repository was archived by the owner on May 25, 2022. It is now read-only.

Commit 04225fe

Browse files
committed
Add cli_proxy_tester project
1 parent e445aed commit 04225fe

File tree

6 files changed

+184
-2
lines changed

6 files changed

+184
-2
lines changed

README.md

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
11
# mini-projects-python
2-
A collection of simple python mini projects to enhance your python skills
32

3+
A collection of simple python mini projects to enhance your python skills
44

55
If you want to learn about python visit [Here](https://github.com/chavarera/PythonScript)
6+
67
## Steps To Follow
8+
79
- Select an issue
810
- Open [project here](https://github.com/chavarera/python-mini-projects)
911
- Create a fork of the project
@@ -31,7 +33,7 @@ Sr no | Project Name | Author
3133
9 | [WishList App Using Django](https://github.com/chavarera/python-mini-projects/tree/master/projects/WishList) | [Ravi Chavare](https://github.com/chavarera)
3234
10 | [Split Folders into Subfolders](https://github.com/chavarera/python-mini-projects/tree/master/projects/split%20folder%20into%20subfolders) | [Ravi Chavare](https://github.com/chavarera)
3335
11 | [Download bulk images](https://github.com/chavarera/python-mini-projects/tree/master/projects/download%20images%20from%20website) | [Mitesh](https://github.com/Mitesh2499)
34-
12 | [Ranom word from file](https://github.com/chavarera/python-mini-projects/tree/master/projects/Random_word_from_list) |
36+
12 | [Random word from file](https://github.com/chavarera/python-mini-projects/tree/master/projects/Random_word_from_list) |
3537
13 | [Battery notification](https://github.com/chavarera/python-mini-projects/tree/master/projects/battery%20notification) | [Mitesh](https://github.com/Mitesh2499)
3638
14 | [Calculate age](https://github.com/chavarera/python-mini-projects/tree/master/projects/Calculate%20age) | [Gaodong](https://github.com/xlgd)
3739
15 | [Text file analysis](https://github.com/chavarera/python-mini-projects/tree/master/projects/Textfile%20analysis) | [m044de](https://github.com/m044de/)
@@ -53,3 +55,4 @@ Sr no | Project Name | Author
5355
31 | [Cli Based Todo Application](https://github.com/chavarera/python-mini-projects/tree/master/projects/CLI%20Todo) | [Audrey Yang](https://github.com/audrey-yang)
5456
32 | [Currency Convertor cli app](https://github.com/chavarera/python-mini-projects/tree/master/projects/Currency%20Converter) | [github-of-wone](https://github.com/github-of-wone/)
5557
33 | [Stopwatch Application](https://github.com/chavarera/python-mini-projects/tree/master/projects/create%20a%20simple%20stopwatch) | [Gaodong](https://github.com/xlgd)
58+
34 | [CLI Proxy Tester](https://github.com/chavarera/python-mini-projects/tree/master/projects/cli_proxy_tester) | [Ingo Kleiber](https://github.com/IngoKl)
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
# mini-projects-python - cli based proxy tester (#77)
2+
3+
*Author:* Ingo Kleiber (ingo@kleiber.me)
4+
5+
This mini project is a proxy tester based on `requests`. It utilized `pandas` for handling csv files and
6+
`click` for the CLI.
7+
8+
## Usage
9+
10+
This script tests proxies by querying (GET request) a testing website that returns the IP of the client. If the returned IP matches the IP of the proxy, we consider the proxy to be good.
11+
12+
### Testing Single Proxies
13+
14+
`python cli.py single http://1.1.1.1`
15+
16+
This will test the HTTP proxy 1.1.1.1 against the default testing website [iptest.ingokleiber.de](http://iptest.ingokleiber.de). You can run your own testing service using the PHP script in `/ipinfo`.
17+
18+
`python cli.py single http://1.1.1.1 --iptest iptest.yourdomain.com`
19+
20+
### (Re)Testing a CSV File
21+
22+
`python cli.py csv-file proxies.csv`
23+
24+
This will (re)test all proxies in the given file.
25+
26+
### Adding and Testing Proxies From a Text File
27+
28+
`python cli.py add-from-txt-file proxy_candidates.txt`
29+
30+
This will add and test each proxy (one per line) in `proxy_candidates.txt`.

projects/cli_proxy_tester/cli.py

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
import logging
2+
import click
3+
4+
from proxytest import test_single_proxy, test_file, add_from_text_file
5+
6+
@click.group()
7+
def cli():
8+
pass
9+
10+
@cli.command()
11+
@click.argument('proxy')
12+
@click.option('--iptest', default='http://iptest.ingokleiber.de', help='iptest address')
13+
@click.option('--csv', default='proxies.csv', help='CSV path')
14+
def single(proxy, iptest, csv):
15+
test_single_proxy(proxy, iptest, csv)
16+
17+
@cli.command()
18+
@click.argument('csv')
19+
@click.option('--iptest', default='http://iptest.ingokleiber.de', help='iptest address')
20+
def csv_file(iptest, csv):
21+
test_csv_file(iptest, csv)
22+
23+
@cli.command()
24+
@click.argument('txt')
25+
@click.option('--iptest', default='http://iptest.ingokleiber.de', help='iptest address')
26+
@click.option('--csv', default='proxies.csv', help='CSV path')
27+
def add_from_txt_file(iptest, txt, csv):
28+
add_from_text_file(iptest, txt, csv)
29+
30+
31+
if __name__ == '__main__':
32+
cli()
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
<?php
2+
header('Content-type: application/json');
3+
4+
$client_information = array(
5+
"ip" => $_SERVER['REMOTE_ADDR'],
6+
"xff" => $_SERVER['HTTP_X_FORWARDED_FOR'],
7+
"useragent" => $_SERVER['HTTP_USER_AGENT']
8+
);
9+
10+
echo json_encode($client_information);
11+
?>
Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
from pathlib import Path
2+
import logging
3+
import requests
4+
from requests.exceptions import ProxyError
5+
import pandas as pd
6+
from json.decoder import JSONDecodeError
7+
8+
logging.basicConfig(level=logging.INFO)
9+
10+
11+
def add_proxies_to_file(csv_path: str, proxies: list):
12+
'''This function will add one or multiple proxies to the CSV file.'''
13+
14+
if not csv_path.exists():
15+
proxies_file: pd.DataFrame = pd.DataFrame(columns=['proxy_type', 'proxy_address', 'proxy_status'])
16+
logging.info('New CSV file will be created')
17+
else:
18+
proxies_file: pd.DataFrame = pd.read_csv(csv_path)
19+
logging.info('Existing CSV file has been loaded')
20+
21+
for proxy in proxies:
22+
if len(proxies_file) == 0:
23+
# First proxy in the file
24+
proxies_file = proxies_file.append(proxy, ignore_index=True)
25+
else:
26+
if len(proxies_file.loc[ (proxies_file['proxy_type'] == proxy['proxy_type']) & (proxies_file['proxy_address'] == proxy['proxy_address'])]) > 0:
27+
# Proxy is already in the file
28+
proxies_file.loc[ (proxies_file['proxy_type'] == proxy['proxy_type']) & (proxies_file['proxy_address'] == proxy['proxy_address']) , ['proxy_status']] = proxy['proxy_status']
29+
else:
30+
# Proxy is not yet in the file
31+
proxies_file = proxies_file.append(proxy, ignore_index=True)
32+
33+
34+
proxies_file = proxies_file.drop_duplicates()
35+
proxies_file.to_csv(csv_path, index=False)
36+
logging.info('CSV file has been written')
37+
38+
39+
def test_proxy(proxy_type: str, proxy_address: str, iptest: str):
40+
'''This function takes a proxy (type, address) and tests it against a given iptest adress.'''
41+
42+
logging.info(f'Testing proxy: {proxy_address}')
43+
44+
try:
45+
proxies = {proxy_type: proxy_address}
46+
proxy_status: str = ''
47+
r = requests.get('http://iptest.ingokleiber.de', proxies=proxies)
48+
49+
try:
50+
json_response: dict = r.json()
51+
52+
if json_response["ip"] == proxy_address:
53+
proxy_status = 'Proxy functional'
54+
else:
55+
logging.warning(f'Proxy "{proxy_address}" returned {json_response}')
56+
proxy_status = 'Proxy not functional'
57+
except JSONDecodeError:
58+
proxy_status = 'Invalid response'
59+
except ProxyError:
60+
proxy_status = 'Proxy error'
61+
62+
logging.info(f'Proxy {proxy_address}: {proxy_status}')
63+
return {'proxy_type': proxy_type, 'proxy_address': proxy_address, 'proxy_status': proxy_status}
64+
65+
66+
def test_single_proxy(proxy: str, iptest: str, csv_path: str):
67+
'''This function tests an individual proxy and adds it to the CSV file.'''
68+
proxy_type, proxy_address = proxy.split('://')
69+
result: dict = test_proxy(proxy_type, proxy_address, iptest)
70+
71+
add_proxies_to_file(Path(csv_path), [result])
72+
73+
74+
def test_file(iptest: str, csv_path: str):
75+
'''This function (re)tests every proxy in a given CSV file.'''
76+
77+
csv_path: Path = Path(csv_path)
78+
79+
if csv_path.exists():
80+
proxies_file: pd.DataFrame = pd.read_csv(csv_path)
81+
else:
82+
raise FileNotFoundError
83+
84+
proxies: list = []
85+
86+
for index, proxy in proxies_file.iterrows():
87+
proxies.append(test_proxy(proxy['proxy_type'], proxy['proxy_address'], iptest))
88+
89+
add_proxies_to_file(csv_path, proxies)
90+
91+
92+
def add_from_text_file(iptest: str, text_path: str, csv_path: str):
93+
''' This function adds a list of proxies from a text file (line by line).'''
94+
text_path: Path = Path(text_path)
95+
96+
if text_path.exists():
97+
proxies: list = text_path.read_text().splitlines()
98+
99+
for proxy in proxies:
100+
# We will treat each proxy as a single proxy and leverage the existing function
101+
test_single_proxy(proxy, iptest, csv_path)
102+
else:
103+
raise FileNotFoundError
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
click==7.1.2
2+
requests[socks]==2.24.0
3+
pandas==1.0.5

0 commit comments

Comments
 (0)