Skip to content

Commit a4d79ea

Browse files
authored
v0.1 commit
First early version v0.1 of ProxyGrablin. Fully working.
1 parent 209a888 commit a4d79ea

11 files changed

Lines changed: 483 additions & 2 deletions

‎ProxyGrablin.py‎

Lines changed: 296 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,296 @@
1+
# -*- coding: utf-8 -*-
2+
3+
__title__ = "ProxyGrablin"
4+
__description__ = "A simple proxy scraper and proxy checker with GUI."
5+
__author__ = "DrPython3"
6+
__contact__ = "https://github.com/DrPython3"
7+
__date__ = "2024-10-03"
8+
__version__ = "0.1"
9+
10+
"""
11+
ProxyGrablin by DrPython3 (C) 2024
12+
13+
A simple and easy to use proxy scraper and checker with a GUI.
14+
15+
If you want to support this project, please consider a donation or tip me a coffee:
16+
17+
(BTC): 16KLyV8C1S9NGkPeaPTGZxahvh1uw9aQCv
18+
(LTC): LboqWKdYjmVGu44kWkSSFTadVmzSu4B3sE
19+
20+
Every support is appreciated!
21+
22+
And do not forget to check the repository for Updates.
23+
"""
24+
25+
# TODO: Add threading-support.
26+
# TODO: Check logs and reduce to minimum.
27+
# TODO: Integrate live output in GUI.
28+
29+
# Needed modules:
30+
import sys
31+
try:
32+
from PyQt5.QtWidgets import QApplication
33+
from PyQt5.QtWidgets import QWidget
34+
from PyQt5.QtWidgets import QPushButton
35+
from PyQt5.QtWidgets import QVBoxLayout
36+
from PyQt5.QtWidgets import QHBoxLayout
37+
from PyQt5.QtWidgets import QLabel
38+
from PyQt5.QtWidgets import QFileDialog
39+
from PyQt5.QtWidgets import QInputDialog
40+
from PyQt5.QtWidgets import QMessageBox
41+
from PyQt5.QtWidgets import QTextEdit
42+
from PyQt5.QtWidgets import QComboBox
43+
from PyQt5.QtWidgets import QSpinBox
44+
from PyQt5.QtGui import QPixmap
45+
from inc_scraper import scraper
46+
from inc_checker import checker
47+
from inc_etc import writer
48+
from inc_etc import logging
49+
except:
50+
sys.exit("[ERROR] Cannot import needed modules.\n\n")
51+
52+
# ProxyGrablin:
53+
class ProxyGrablin(QWidget):
54+
def __init__(self):
55+
super().__init__()
56+
# Needed variables:
57+
self.test_url = "http://www.google.com" # Standard URL for proxy checker
58+
self.selected_proxy_type = "http" # Standard proxy type for proxy checker
59+
self.timeout_value = 3 # Standard timeout for proxy checker
60+
self.initUI()
61+
62+
def initUI(self):
63+
# GUI setup:
64+
main_layout = QHBoxLayout()
65+
control_layout = QVBoxLayout()
66+
67+
# Logo:
68+
self.label = QLabel(self)
69+
pixmap = QPixmap("logo.png")
70+
self.label.setPixmap(pixmap)
71+
self.label.setScaledContents(True)
72+
self.label.resize(pixmap.width(), pixmap.height())
73+
control_layout.addWidget(self.label)
74+
75+
self.label = QLabel("Simple Proxy Scraper & Checker v0.1", self)
76+
control_layout.addWidget(self.label)
77+
78+
# Scraper button:
79+
self.scraper_button = QPushButton("Scrape Proxies", self)
80+
self.scraper_button.clicked.connect(self.proxy_scraper)
81+
control_layout.addWidget(self.scraper_button)
82+
83+
# Test URL:
84+
self.label_url = QLabel(f"Test URL: {self.test_url}", self)
85+
control_layout.addWidget(self.label_url)
86+
87+
# Test URL setting:
88+
self.set_url_button = QPushButton("Change test URL", self)
89+
self.set_url_button.clicked.connect(self.set_test_url)
90+
control_layout.addWidget(self.set_url_button)
91+
92+
# Set proxy type for checker:
93+
self.proxy_type_label = QLabel("Set proxy type:", self)
94+
control_layout.addWidget(self.proxy_type_label)
95+
96+
self.proxy_type_setting = QComboBox(self)
97+
self.proxy_type_setting.addItems(["http", "https", "socks4", "socks5"])
98+
self.proxy_type_setting.currentTextChanged.connect(self.set_proxy_type)
99+
control_layout.addWidget(self.proxy_type_setting)
100+
101+
# Set timeout for checker:
102+
self.timeout_label = QLabel("Set default timeout (sec):", self)
103+
control_layout.addWidget(self.timeout_label)
104+
105+
self.timeout_setting = QSpinBox(self)
106+
self.timeout_setting.setMinimum(1)
107+
self.timeout_setting.setMaximum(60)
108+
self.timeout_setting.setValue(self.timeout_value)
109+
self.timeout_setting.valueChanged.connect(self.set_timeout)
110+
control_layout.addWidget(self.timeout_setting)
111+
112+
# Checker button:
113+
self.checker_button = QPushButton("Check Proxies", self)
114+
self.checker_button.clicked.connect(self.proxy_checker)
115+
control_layout.addWidget(self.checker_button)
116+
117+
# Add Control_Layout to Main_Layout:
118+
main_layout.addLayout(control_layout)
119+
120+
# Area for text output:
121+
self.result_display = QTextEdit(self)
122+
self.result_display.setReadOnly(True)
123+
main_layout.addWidget(self.result_display)
124+
125+
# Build GUI:
126+
self.setLayout(main_layout)
127+
self.setWindowTitle("ProxyGrablin v0.1")
128+
self.show()
129+
130+
def proxy_scraper(self):
131+
"""
132+
Scrapes potential proxy IPs from given URLs and saves all found unique
133+
IP addresses to a text file. URLs are read from a text file, too.
134+
URL file must provide one URL per line.
135+
:return: None
136+
"""
137+
scraped_ips = []
138+
unique_ips = []
139+
sources_to_scrape = 0
140+
sources_scraped = 0
141+
logging("Scraper started.")
142+
self.result_display.clear()
143+
self.result_display.append("Scraper started.")
144+
# Get file with URL list:
145+
urls, _ = QFileDialog.getOpenFileName(self, "Choose URL list for scraper", "", "Text Files (*.txt)")
146+
if urls:
147+
logging("Importing URL list.")
148+
# Import URL list from file:
149+
with open(urls, "r") as input_file:
150+
sources = [line.strip() for line in input_file.readlines()]
151+
# Scrape proxies from URLs:
152+
if sources:
153+
sources_to_scrape = len(sources)
154+
logging(f"Found {str(sources_to_scrape)} URLs to scrape.")
155+
for source in sources:
156+
sources_scraped += 1
157+
print(f"Scraping {str(sources_scraped)} of {str(sources_to_scrape)}: {source}")
158+
result = scraper(source)
159+
scraped_ips.extend(result)
160+
else:
161+
logging("No URLs to scrape.")
162+
self.result_display.append("No URLs to scrape.")
163+
# Remove duplicates from scraped data and fill unique_ips list:
164+
if len(scraped_ips) > 0:
165+
logging("Removing duplicate proxies.")
166+
print("Removing duplicate proxies.")
167+
ip_pool = set()
168+
for ip in scraped_ips:
169+
if ip not in ip_pool:
170+
unique_ips.append(ip)
171+
ip_pool.add(ip)
172+
else:
173+
continue
174+
try:
175+
del ip_pool
176+
except:
177+
pass
178+
# Save unique_ips list to file:
179+
if len(unique_ips) > 0:
180+
logging("Saving proxies to file.")
181+
output_file, _ = QFileDialog.getSaveFileName(self, "Save scraped IPs", "", "Text files (*.txt)")
182+
if output_file:
183+
writer(unique_ips, output_file)
184+
logging("Scraped proxies saved to file.")
185+
self.result_display.append("Scraped IPs saved to file.")
186+
print("Scraped proxies saved to file.")
187+
else:
188+
logging("Output file not specified.")
189+
self.result_display.append("Output file not specified.")
190+
else:
191+
logging("No proxies found.")
192+
self.result_display.append("No proxies found.")
193+
else:
194+
logging("No URLs to scrape.")
195+
self.result_display.append("No URLs to scrape.")
196+
197+
def set_test_url(self):
198+
"""
199+
Used to set the URL which the proxy checker uses to test given proxies.
200+
:return: None
201+
"""
202+
logging("Setting new test URL.")
203+
new_url, ok = QInputDialog.getText(self, "Enter URL for checker", "Enter the URL for the checker:")
204+
if ok and new_url:
205+
self.test_url = new_url
206+
QMessageBox.information(self, "Test URL", f"New test URL set: {self.test_url}")
207+
logging("New test URL set.")
208+
self.result_display.append(f"New test URL set: {self.test_url}")
209+
else:
210+
QMessageBox.warning(self, "Invalid URL", "Entered URL is invalid, test URL not changed.")
211+
logging("Entered URL is invalid, test URL not changed.")
212+
self.result_display.append("Entered URL is invalid, test URL not changed.")
213+
self.label_url.setText(f"Test URL: {self.test_url}")
214+
215+
def set_proxy_type(self, proxy_type):
216+
"""
217+
Used to set the proxy type the checker will test for.
218+
:param proxy_type: Proxy type used for the checker.
219+
:return: None
220+
"""
221+
self.selected_proxy_type = proxy_type
222+
logging(f"Proxy type to use set to {proxy_type}")
223+
self.result_display.append(f"Proxy type set to {proxy_type}")
224+
225+
def set_timeout(self, value):
226+
"""
227+
Used to set the default timeout for the proxy checker.
228+
:param value: timeout in secounds
229+
:return: None
230+
"""
231+
self.timeout_value = value
232+
logging(f"Timeout value changed to {str(value)}")
233+
self.result_display.append(f"Timeout value changed to {str(value)}")
234+
self.timeout_label.setText(f"Timeout value changed to {str(value)}")
235+
236+
def proxy_checker(self):
237+
"""
238+
Starts the proxy checker. IPs will be checked one by one. Working proxies
239+
are saved to a text file. The IPs to check have to be provided in a text file
240+
with one IP per line.
241+
:return: None
242+
"""
243+
working_proxies = []
244+
amount_ips = 0
245+
amount_proxies = 0
246+
self.result_display.clear()
247+
logging("Proxy Checker started.")
248+
self.result_display.append("Proxy Checker started - this will take some time. Please, be patient!")
249+
ips, _ = QFileDialog.getOpenFileName(self, "Choose file with proxy IPs", "", "Text files (*.txt)")
250+
# Get IPs from file:
251+
if ips:
252+
with open(ips, "r") as input_file:
253+
ips_to_check = [line.strip() for line in input_file.readlines()]
254+
amount_ips = len(ips_to_check)
255+
print(f"{str(amount_ips)} loaded for checking.")
256+
logging(f"{amount_ips} loaded for checking.")
257+
logging("Checking IPs ...")
258+
# Check every IP for working proxy:
259+
if ips_to_check:
260+
for ip in ips_to_check:
261+
result = checker(ip, self.selected_proxy_type, self.test_url, self.timeout_value)
262+
if "alive" in result:
263+
working_proxies.append(ip)
264+
print(result)
265+
else:
266+
self.result_display.append("No IPs to check.")
267+
logging("No IPs to check.")
268+
# Save working proxies to file:
269+
if working_proxies:
270+
amount_proxies = len(working_proxies)
271+
logging(f"Saving {str(amount_proxies)} {self.selected_proxy_type.upper()} proxies to file.")
272+
output_file, _ = QFileDialog.getSaveFileName(self, f"Save working {self.selected_proxy_type.upper()} proxies", "", "Text files (*.txt)")
273+
if output_file:
274+
writer(working_proxies, output_file)
275+
logging("Proxies saved to file.")
276+
else:
277+
logging("No output file specified.")
278+
# Show working proxies in GUI:
279+
self.result_display.clear()
280+
self.result_display.append("WORKING PROXIES:\n" + "-" * 25)
281+
for proxy in working_proxies:
282+
self.result_display.append(proxy)
283+
else:
284+
self.result_display.append("No working proxies found.")
285+
logging("No working proxies found.")
286+
else:
287+
logging("No file to load IPs from.")
288+
self.result_display.append("No file to load IPs from.")
289+
290+
# Main:
291+
if __name__ == "__main__":
292+
app = QApplication(sys.argv)
293+
ex = ProxyGrablin()
294+
sys.exit(app.exec_())
295+
296+
# DrPython3 (C) 2024

‎README.md‎

Lines changed: 46 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,46 @@
1-
# ProxyGrablin
2-
Simple proxy scraper and proxy checker with a easy to use GUI.
1+
# ProxyGrablin
2+
*A simple proxy scraper and proxy checker with a GUI written in Python.*
3+
4+
![Demo](demo.gif)
5+
6+
## Overview
7+
Scrape potential proxy IPs from websites and check the results for working proxies.
8+
ProxyGrablin is a simple proxy checker and scraper for Python 3.12+.
9+
The GUI provides the basic settings and is used to show the results of every task.
10+
11+
Please note, that ProxyGrablin is in a early state of development.
12+
You can support this project for faster development.
13+
14+
## Support
15+
Support this project with a little donation or tip a coffee:
16+
- BTC: 16KLyV8C1S9NGkPeaPTGZxahvh1uw9aQCv
17+
- LTC: LboqWKdYjmVGu44kWkSSFTadVmzSu4B3sE
18+
19+
Every donation and tip helps!
20+
21+
## Requirements
22+
- Python 3.12+
23+
- requests and PyQt5 modules installed.
24+
25+
If Python is already installed, you can use this command in console for installing the requirements:
26+
27+
pip install -r requirements.txt
28+
29+
## Step by Step Guide
30+
First create a text file and paste any URLs of websites which contain proxy IPs to it. Then start ProxyGrablin with:
31+
32+
python ProxyGrablin.py
33+
34+
Click on "Scrape Proxies" and you will be asked to choose a text file. Choose the text file with the URLs here. Now the scraper will start to check the websites for any proxy IPS. Once finished you are asked to save the results. Just enter any filename, e.g. "scraped".
35+
36+
The proxy checker will use Google to check the proxies. If you want to change the website used by the checker, just click on "Change test URL" and enter another one. Select the proxy type to check for and change the timeout value if you want.
37+
38+
Now you can click on "Check Proxies". Then choose the text file you saved the proxy IPs to and wait. You can follow the checker process in the console. Once the checker has finished and in case it found any working proxy, you will be asked for the file into which the working proxies shall be saved. The working proxies will also be displayed in the output area of the GUI.
39+
40+
## Upcoming improvements
41+
42+
- Threads for the proxy checker
43+
- GUI rework
44+
- Logs rework
45+
- other minor improvements
46+

‎demo.gif‎

673 KB
Loading

‎inc_checker.py‎

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
# -*- coding: utf-8 -*-
2+
3+
__title__ = "Proxy Checker for ProxyGrablin"
4+
__description__ = "Checks given IPs for working proxies of a pre-defined type."
5+
__author__ = "DrPython3"
6+
__date__ = "2024-10-03"
7+
__version__ = "0.1"
8+
__contact__ = "https://github.com/DrPython3"
9+
10+
# TODO: Improve checker (geo info, anon level etc.).
11+
# TODO: Prepare for threading.
12+
13+
# Needed modules:
14+
import sys
15+
import requests
16+
from inc_etc import logging
17+
18+
# Functions:
19+
def checker(ip_address, proxy_type, test_url, timeout_value):
20+
"""
21+
Checks a given proxy trying to open the given URL.
22+
:param ip_address: IP of the proxy
23+
:param proxy_type: HTTP, HTTPS, SOCKS4 or SOCKS5
24+
:param test_url: URL for connection test
25+
:param timeout_value: timeout for connection test
26+
:return: proxy information (text)
27+
"""
28+
if "socks" in proxy_type:
29+
proxy_url = f"{proxy_type}h://{ip_address}"
30+
else:
31+
proxy_url = f"{proxy_type}://{ip_address}"
32+
proxy = {proxy_type: proxy_url}
33+
try:
34+
logging(f"Checking {proxy_type.upper()} proxy {ip_address}.")
35+
response = requests.get(test_url, proxies=proxy, timeout=timeout_value)
36+
if response.status_code == 200:
37+
logging(f"{proxy_type.upper()} proxy {ip_address} is alive.")
38+
return f"{proxy_type.upper()} proxy {ip_address} is alive."
39+
else:
40+
logging(f"{proxy_type.upper()} proxy {ip_address} returns errors.")
41+
return f"{proxy_type.upper()} proxy {ip_address} returns errors."
42+
except:
43+
logging(f"{proxy_type.upper()} proxy {ip_address} is dead.")
44+
return f"{proxy_type.upper()} proxy {ip_address} is dead."
45+
46+
# DrPython3 (C) 2024

0 commit comments

Comments
 (0)