first commit

This commit is contained in:
祀梦
2026-01-27 21:17:36 +08:00
commit b06044c91c
57 changed files with 6714 additions and 0 deletions

61
plugins/fate0.py Normal file
View File

@@ -0,0 +1,61 @@
import sys
import os
sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
from core.crawler import BasePlugin
from core.log import logger
import json
import asyncio
class Fate0Plugin(BasePlugin):
def __init__(self):
super().__init__()
self.name = "Fate0聚合源"
# 这是一个持续更新的高质量代理聚合列表
self.urls = ["https://raw.githubusercontent.com/fate0/proxylist/master/proxy.list"]
async def parse(self, html):
if not html:
return
count = 0
# fate0 的数据格式是每行一个 JSON 对象
for line in html.split('\n'):
if not line.strip():
continue
try:
data = json.loads(line)
ip = data.get('host')
port = data.get('port')
protocol = data.get('type', 'http')
if ip and port:
yield ip, int(port), protocol
count += 1
except Exception:
continue
if count > 0:
logger.info(f"{self.name} 解析完成,获得 {count} 个潜在代理")
if __name__ == "__main__":
async def test_plugin():
plugin = Fate0Plugin()
print(f"========== 测试 {plugin.name} ==========")
print(f"目标URL数量: {len(plugin.urls)}")
print(f"开始抓取...\n")
proxies = await plugin.run()
print(f"\n========== 抓取结果 ==========")
print(f"总计获取 {len(proxies)} 个代理:")
print("-" * 60)
for idx, (ip, port, protocol) in enumerate(proxies, 1):
print(f"{idx:3d}. {ip:15s} : {str(port):5s} | {protocol}")
print("-" * 60)
print(f"完成!共 {len(proxies)} 个代理~")
asyncio.run(test_plugin())

74
plugins/ip3366.py Normal file
View File

@@ -0,0 +1,74 @@
import sys
import os
sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
from core.crawler import BasePlugin
from core.log import logger
from bs4 import BeautifulSoup
import re
import asyncio
VALID_PROTOCOLS = ['http', 'https', 'socks4', 'socks5']
class Ip3366Plugin(BasePlugin):
def __init__(self):
super().__init__()
self.name = "IP3366"
# 抓取高匿和普通代理的前 5 页
self.urls = [
f"http://www.ip3366.net/free/?stype=1&page={i}" for i in range(1, 6)
] + [
f"http://www.ip3366.net/free/?stype=2&page={i}" for i in range(1, 6)
]
async def parse(self, html):
if not html:
return
soup = BeautifulSoup(html, 'lxml')
list_div = soup.find('div', id='list')
if not list_div: return
table = list_div.find('table')
if not table: return
rows = table.find_all('tr')
count = 0
for row in rows:
tds = row.find_all('td')
if len(tds) >= 5:
ip = tds[0].get_text(strip=True)
port = tds[1].get_text(strip=True)
protocol = tds[4].get_text(strip=True).lower() if len(tds) > 4 else 'http'
if protocol not in VALID_PROTOCOLS:
protocol = 'http'
if re.match(r'^\d+\.\d+\.\d+\.\d+$', ip) and port.isdigit():
yield ip, int(port), protocol
count += 1
if count > 0:
logger.info(f"{self.name} 解析完成,获得 {count} 个潜在代理")
if __name__ == "__main__":
async def test_plugin():
plugin = Ip3366Plugin()
print(f"========== 测试 {plugin.name} ==========")
print(f"目标URL数量: {len(plugin.urls)}")
print(f"开始抓取...\n")
proxies = await plugin.run()
print(f"\n========== 抓取结果 ==========")
print(f"总计获取 {len(proxies)} 个代理:")
print("-" * 60)
for idx, (ip, port, protocol) in enumerate(proxies, 1):
print(f"{idx:3d}. {ip:15s} : {str(port):5s} | {protocol}")
print("-" * 60)
print(f"完成!共 {len(proxies)} 个代理~")
asyncio.run(test_plugin())

69
plugins/ip89.py Normal file
View File

@@ -0,0 +1,69 @@
import sys
import os
sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
from core.crawler import BasePlugin
from core.log import logger
from bs4 import BeautifulSoup
import re
import asyncio
class Ip89Plugin(BasePlugin):
def __init__(self):
super().__init__()
self.name = "89免费代理"
# 抓取前 5 页
self.urls = [
f"https://www.89ip.cn/index_{i}.html" for i in range(1, 6)
]
async def parse(self, html):
"""
解析 89ip 页面
"""
if not html:
return
soup = BeautifulSoup(html, 'lxml')
table = soup.find('table', class_='layui-table')
if not table:
return
rows = table.find_all('tr')
count = 0
for row in rows:
tds = row.find_all('td')
if len(tds) >= 2:
ip = tds[0].get_text(strip=True)
port = tds[1].get_text(strip=True)
# 89ip 通常不直接写协议,默认尝试 http
protocol = 'http'
if re.match(r'^\d+\.\d+\.\d+\.\d+$', ip) and port.isdigit():
yield ip, int(port), protocol
count += 1
if count > 0:
logger.info(f"{self.name} 解析完成,获得 {count} 个潜在代理")
if __name__ == "__main__":
async def test_plugin():
plugin = Ip89Plugin()
print(f"========== 测试 {plugin.name} ==========")
print(f"目标URL数量: {len(plugin.urls)}")
print(f"开始抓取...\n")
proxies = await plugin.run()
print(f"\n========== 抓取结果 ==========")
print(f"总计获取 {len(proxies)} 个代理:")
print("-" * 60)
for idx, (ip, port, protocol) in enumerate(proxies, 1):
print(f"{idx:3d}. {ip:15s} : {str(port):5s} | {protocol}")
print("-" * 60)
print(f"完成!共 {len(proxies)} 个代理~")
asyncio.run(test_plugin())

79
plugins/kuaidaili.py Normal file
View File

@@ -0,0 +1,79 @@
import sys
import os
sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
from core.crawler import BasePlugin
from core.log import logger
from bs4 import BeautifulSoup
import re
import asyncio
VALID_PROTOCOLS = ['http', 'https', 'socks4', 'socks5']
class KuaiDaiLiPlugin(BasePlugin):
def __init__(self):
super().__init__()
self.name = "快代理"
# 抓取国内高匿和国内普通代理的前 10 页
self.urls = [
f"https://www.kuaidaili.com/free/inha/{i}/" for i in range(1, 11)
] + [
f"https://www.kuaidaili.com/free/intr/{i}/" for i in range(1, 11)
]
async def parse(self, html):
"""
解析快代理页面
"""
if not html:
return
soup = BeautifulSoup(html, 'lxml')
# 快代理的表格在 tbody 中
table = soup.find('table')
if not table:
# 尝试通过正则表达式匹配可能被加密或特殊处理的数据
logger.warning(f"{self.name} 未能找到表格,可能是触发了反爬或结构变化")
return
rows = table.find_all('tr')
count = 0
for row in rows:
tds = row.find_all('td')
if len(tds) >= 5:
ip = tds[0].get_text(strip=True)
port = tds[1].get_text(strip=True)
protocol = tds[4].get_text(strip=True).lower() if len(tds) > 4 else 'http'
if protocol not in VALID_PROTOCOLS:
protocol = 'http'
# 简单校验格式
if re.match(r'^\d+\.\d+\.\d+\.\d+$', ip) and port.isdigit():
yield ip, int(port), protocol
count += 1
if count > 0:
logger.info(f"{self.name} 解析完成,获得 {count} 个潜在代理")
if __name__ == "__main__":
async def test_plugin():
plugin = KuaiDaiLiPlugin()
print(f"========== 测试 {plugin.name} ==========")
print(f"目标URL数量: {len(plugin.urls)}")
print(f"开始抓取...\n")
proxies = await plugin.run()
print(f"\n========== 抓取结果 ==========")
print(f"总计获取 {len(proxies)} 个代理:")
print("-" * 60)
for idx, (ip, port, protocol) in enumerate(proxies, 1):
print(f"{idx:3d}. {ip:15s} : {str(port):5s} | {protocol}")
print("-" * 60)
print(f"完成!共 {len(proxies)} 个代理~")
asyncio.run(test_plugin())

View File

@@ -0,0 +1,64 @@
import sys
import os
sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
from core.crawler import BasePlugin
from core.log import logger
import asyncio
class ProxyListDownloadPlugin(BasePlugin):
def __init__(self):
super().__init__()
self.name = "ProxyListDownload"
self.urls = [
"https://www.proxy-list.download/api/v1/get?type=http",
"https://www.proxy-list.download/api/v1/get?type=https"
]
async def parse(self, html):
if not html:
return
lines = html.split('\r\n')
if len(lines) <= 1:
lines = html.split('\n')
count = 0
for line in lines:
line = line.strip()
if not line:
continue
if ':' in line:
parts = line.split(':')
if len(parts) >= 2:
ip = parts[0]
port = parts[1]
protocol = 'http' if 'type=http' in self.current_url else 'https'
yield ip, int(port), protocol
count += 1
if count > 0:
logger.info(f"{self.name} 解析完成,从 {self.current_url} 获得 {count} 个潜在代理")
if __name__ == "__main__":
async def test_plugin():
plugin = ProxyListDownloadPlugin()
print(f"========== 测试 {plugin.name} ==========")
print(f"目标URL数量: {len(plugin.urls)}")
print(f"开始抓取...\n")
proxies = await plugin.run()
print(f"\n========== 抓取结果 ==========")
print(f"总计获取 {len(proxies)} 个代理:")
print("-" * 60)
for idx, (ip, port, protocol) in enumerate(proxies, 1):
print(f"{idx:3d}. {ip:15s} : {str(port):5s} | {protocol}")
print("-" * 60)
print(f"完成!共 {len(proxies)} 个代理~")
asyncio.run(test_plugin())

78
plugins/speedx.py Normal file
View File

@@ -0,0 +1,78 @@
import sys
import os
sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
from core.crawler import BasePlugin
from core.log import logger
import re
import asyncio
class SpeedXPlugin(BasePlugin):
def __init__(self):
super().__init__()
self.name = "SpeedX代理源"
self.urls = [
"https://raw.githubusercontent.com/TheSpeedX/SOCKS-List/master/http.txt",
"https://raw.githubusercontent.com/TheSpeedX/SOCKS-List/master/socks4.txt",
"https://raw.githubusercontent.com/TheSpeedX/SOCKS-List/master/socks5.txt"
]
async def parse(self, html):
if not html:
return
lines = html.split('\n')
count = 0
for line in lines:
line = line.strip()
if not line:
continue
if ':' in line:
parts = line.split(':')
if len(parts) >= 2:
ip = parts[0].strip()
port = parts[1].strip()
# 验证IP地址格式
if not re.match(r'^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$', ip):
continue
# 验证端口是数字
if not port.isdigit() or not (1 <= int(port) <= 65535):
continue
# 根据 URL 判断协议
protocol = 'http'
if 'socks5' in self.current_url:
protocol = 'socks5'
elif 'socks4' in self.current_url:
protocol = 'socks4'
yield ip, int(port), protocol
count += 1
if count > 0:
logger.info(f"{self.name} 解析完成,从 {self.current_url} 获得 {count} 个潜在代理")
if __name__ == "__main__":
async def test_plugin():
plugin = SpeedXPlugin()
print(f"========== 测试 {plugin.name} ==========")
print(f"目标URL数量: {len(plugin.urls)}")
print(f"开始抓取...\n")
proxies = await plugin.run()
print(f"\n========== 抓取结果 ==========")
print(f"总计获取 {len(proxies)} 个代理:")
print("-" * 60)
for idx, (ip, port, protocol) in enumerate(proxies, 1):
print(f"{idx:3d}. {ip:15s} : {str(port):5s} | {protocol}")
print("-" * 60)
print(f"完成!共 {len(proxies)} 个代理~")
asyncio.run(test_plugin())

79
plugins/yundaili.py Normal file
View File

@@ -0,0 +1,79 @@
import sys
import os
sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
from core.crawler import BasePlugin
from core.log import logger
from bs4 import BeautifulSoup
import re
import asyncio
VALID_PROTOCOLS = ['http', 'https', 'socks4', 'socks5']
class YunDaiLiPlugin(BasePlugin):
def __init__(self):
super().__init__()
self.name = "云代理"
# 抓取高匿和普通代理的前 5 页
self.urls = [
f"http://www.ip3366.net/free/?stype=1&page={i}" for i in range(1, 6)
] + [
f"http://www.ip3366.net/free/?stype=2&page={i}" for i in range(1, 6)
]
async def parse(self, html):
"""
解析云代理/IP3366 页面 (两者结构相似)
"""
if not html:
return
soup = BeautifulSoup(html, 'lxml')
list_table = soup.find('div', id='list')
if not list_table:
return
table = list_table.find('table')
if not table:
return
rows = table.find_all('tr')
count = 0
for row in rows:
tds = row.find_all('td')
if len(tds) >= 5:
ip = tds[0].get_text(strip=True)
port = tds[1].get_text(strip=True)
protocol = tds[4].get_text(strip=True).lower() if len(tds) > 4 else 'http'
if protocol not in VALID_PROTOCOLS:
protocol = 'http'
if re.match(r'^\d+\.\d+\.\d+\.\d+$', ip) and port.isdigit():
yield ip, int(port), protocol
count += 1
if count > 0:
logger.info(f"{self.name} 解析完成,获得 {count} 个潜在代理")
if __name__ == "__main__":
async def test_plugin():
plugin = YunDaiLiPlugin()
print(f"========== 测试 {plugin.name} ==========")
print(f"目标URL数量: {len(plugin.urls)}")
print(f"开始抓取...\n")
proxies = await plugin.run()
print(f"\n========== 抓取结果 ==========")
print(f"总计获取 {len(proxies)} 个代理:")
print("-" * 60)
for idx, (ip, port, protocol) in enumerate(proxies, 1):
print(f"{idx:3d}. {ip:15s} : {str(port):5s} | {protocol}")
print("-" * 60)
print(f"完成!共 {len(proxies)} 个代理~")
asyncio.run(test_plugin())