关于URL采集的构想与实现
字数 1275 2025-08-19 12:41:34
URL采集器设计与实现教学文档
1. 项目背景与需求分析
1.1 项目起源
- 初始需求:检查公司网站首页是否被挂了暗链
- 现有工具不足:网上可用脚本较少且功能有限
- 需求扩展:随着要求不断增加,最终发展为一款功能完善的URL采集器
1.2 传统URL采集工具的局限性
- 采集范围有限:仅能获取被搜索引擎收录的URL
- 过滤机制粗糙:仅依靠去重+黑名单过滤
- 结果同质化:使用相同关键词采集的结果相似,对安全人员不友好
2. 系统设计与功能规划
2.1 核心功能
-
双入口设计:
- 搜索引擎接口采集
- 导入已采集网址进行二次处理
-
深度采集机制:
- 基于初始URL进行友链爬行
- 可自定义是否进行友链爬取
-
多维度过滤:
- URL黑白名单
- 网站标题黑白名单
- 网页内容黑白名单
2.2 系统流程图
[启动] → [选择采集方式] → [关键字采集/文本导入] → [初步过滤] → [友链爬取(可选)] → [多级过滤] → [结果保存]
3. 关键技术实现
3.1 URL采集方式
3.1.1 正则表达式过滤方式
def GetLink(url):
UA = random.choice(headerss)
headers = {'User-Agent': UA, 'Connection': 'close'}
link_urls = []
try:
r = requests.get(url, headers=headers, verify=False, timeout=timeout)
encoing = requests.utils.get_encodings_from_content(r.text)[0]
content = r.content.decode(encoing)
urls = [f"{urlparse(url).scheme}://{urlparse(url).netloc}"
for url in re.findall(r'http[s]?://(?:[a-zA-Z]|[0-9]|[$-_@.&+]|[!*
$$
,]|(?:%[0-9a-fA-F][0-9a-fA-F]))+', content, re.I)]
for url in list(set(urls)):
url = url.replace("'", "")
link_urls.append(url)
except:
pass
return list(set(link_urls))
3.1.2 BeautifulSoup过滤方式
def GetLink(url):
UA = random.choice(headerss)
headers = {'User-Agent': UA, 'Connection': 'close'}
try:
r = requests.get(url, headers=headers, verify=False)
encoding = requests.utils.get_encodings_from_content(r.text)[0]
content = r.content.decode(encoding)
soup = BeautifulSoup(content, 'html.parser')
bs4_urls = set()
for tag in ['a', 'img', 'script', 'link']:
for attr in ['href', 'src']:
for element in soup.find_all(tag):
if attr in element.attrs:
href = element.get(attr)
if href and (href.startswith('http://') or href.startswith('https://')):
parsed = urlparse(href)
url = f"{parsed.scheme}://{parsed.netloc}"
bs4_urls.add(url)
except Exception as e:
pass
link_urls = []
for bs4_url in bs4_urls:
try:
r = requests.head(bs4_url, timeout=5, headers=headers, verify=False)
if r.status_code in [200, 301, 302]:
link_urls.append(bs4_url)
except:
pass
return link_urls
3.2 搜索引擎接口采集
百度搜索接口实现
def BDUrl(key):
cookie = input('请输入cookie:')
bd_headers = {
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64)...",
"Cookie": cookie,
"Connection": "Keep-Alive",
}
bd_url = []
for page in range(0, 8):
url = 'http://www.baidu.com/s?wd={}&pn={}0'
try:
r = requests.get(url.format(key, page), headers=bd_headers, verify=False)
encoing = requests.utils.get_encodings_from_content(r.text)[0]
content = r.content.decode(encoing)
result = [f"{urlparse(url).scheme}://{urlparse(url).netloc}"
for url in re.findall('mu="http[s]?://(?:[a-zA-Z]|[0-9]|[$-_@.&+]|[!*
$$
,]|(?:%[0-9a-fA-F][0-9a-fA-F]))+"', content)[1:]]
for res_url in list(set(result)):
bd_url.append(res_url)
except:
pass
return list(set(bd_url))
3.3 配置文件设计
config.ini 结构
[User]
whoami = JF
[Config]
# 友链爬行,0关闭,1开启
state = 0
# 网址黑名单
black_url = None
# 网址白名单
white_url = None
# 标题黑名单
black_title = None
# 标题白名单
white_title = 安全狗
# 网页内容黑名单
black_content = None
# 网页内容白名单
white_content = None
# 连接超时5秒
timeout = 5
3.4 过滤规则实现
3.4.1 多级过滤规则(单URL版)
def rule_url(url):
# URL黑名单过滤
if black_url != 'None' and (any(key in url for key in black_url.split('|'))):
return False
# URL白名单过滤
if white_url != 'None' and (all(key not in url for key in white_url.split('|'))):
return False
try:
UA = random.choice(headerss)
header = {'User-Agent': UA, 'Connection': 'close'}
r = requests.get(url=url, headers=header, verify=False, timeout=timeout)
if r.status_code in [200, 301, 302]:
encoing = requests.utils.get_encodings_from_content(r.text)[0]
content = r.content.decode(encoing)
title = re.findall('<title>(.*?)</title>', content, re.S)[0]
# 标题黑名单过滤
if black_title != 'None' and (any(key in title for key in black_title.split('|'))):
return False
# 标题白名单过滤
if white_title != 'None' and (all(key not in title for key in white_title.split('|'))):
return False
# 内容黑名单过滤
if black_content != 'None' and (any(key in content for key in black_content.split('|'))):
return False
# 内容白名单过滤
if white_content != 'None' and (all(key not in content for key in white_content.split('|'))):
return False
return url
else:
return False
except:
return False
return False
3.4.2 多线程处理
with ThreadPoolExecutor(max_workers=10) as executor:
results_bd = executor.map(rule_url, bd)
with lock:
for url in results_bd:
if url:
rule_bd_urls.add(url)
4. 系统使用指南
4.1 启动与配置
-
修改
config.ini文件:state: 友链爬行开关(0/1)- 黑白名单设置:使用
|分隔多个关键词 None表示不启用该过滤条件
-
优先级规则:
网址黑名单 > 网址白名单 > 标题黑名单 > 标题白名单 > 网页内容黑名单 > 网页内容白名单
4.2 运行方式
方式一:关键字采集
0:关键字扫描
请输入关键字:教育
流程:
- 通过百度搜索接口获取前7页结果
- 对每个URL应用过滤规则
- 可选进行友链爬取
- 结果保存为
{关键字}_url.txt
方式二:文本导入采集
1:导入文本扫描
将需要扫描的url拖到此窗口:urls.txt
选项:
- 不进行友链爬取(state=0)
- 进行友链爬取(state=1)
4.3 使用示例
示例1:搜索引擎采集教育类站点
- 选择方式0
- 输入关键字"教育"
- 系统自动采集并过滤
- 结果保存为"教育_url.txt"
示例2:文本导入+友链爬取
- 准备包含URL的文本文件
- 选择方式1并拖入文件
- 设置state=1启用友链爬取
- 系统进行多级过滤和友链采集
- 结果保存到指定文件
5. 性能优化与注意事项
5.1 性能优化点
- 从批量处理改为单URL处理,便于并发
- 使用线程池(ThreadPoolExecutor)提高效率
- 减少不必要的网络请求
- 使用HEAD方法检查URL存活状态
5.2 注意事项
- 百度搜索需要提供有效的Cookie
- 确保配置文件字段不为空
- 文本中的URL需包含协议头(http/https)
- 合理设置超时时间(timeout)
- 注意网络请求频率,避免被封禁
6. 项目资源
GitHub仓库: https://github.com/JiangFengSec/JF_URL
7. 总结与扩展
本URL采集器通过多入口采集、深度爬取和多级过滤机制,解决了传统URL采集工具的局限性。系统设计考虑了安全人员的特殊需求,提供了高度可定制的过滤规则。开发者可以根据实际需求进一步扩展:
- 增加更多搜索引擎接口
- 实现分布式爬取
- 添加代理支持
- 完善异常处理和日志记录
- 增加可视化界面