甲方爸爸需求-网站外链深度爬取小工具
字数 1145 2025-08-09 18:44:12

网站外链深度爬取工具开发指南

0X00 项目背景

甲方安全需求:需要对集团各类门户网站进行外链查询,检查是否存在违规或恶意链接。

技术挑战:

  • 需要递归查找所有页面下的外链
  • 短时间内完成大量网站的收集工作
  • 需要区分站内链接和站外链接

0X01 技术方案设计

整体思路

  1. 爬取策略:采用广度优先搜索(BFS)方式遍历网站
  2. 链接识别:通过HTML标签属性(href/src/link)提取链接
  3. 链接分类:根据域名标识区分站内链接和站外链接
  4. 结果输出:分类保存URL到不同文件

技术选型

  • GUI框架:PyQt5
  • 爬虫库:requests + lxml
  • 正则处理:re
  • 打包工具:PyInstaller

0X02 核心功能实现

1. 主程序结构

class mwindow(QWidget, Ui_Spider):
    def __init__(self):
        super(mwindow, self).__init__()
        self.setupUi(self)
        self.initUi()
        self.initarg()
    
    def initUi(self):
        # 绑定按钮事件
        self.spider_button.clicked.connect(self.add_list)
        self.url_button.clicked.connect(self.out_url)
        self.wl_button.clicked.connect(self.out_wl_url)
    
    def initarg(self):
        # 全局变量初始化
        global temp_list2, temp_list, quen_list, count
        temp_list2 = []  # 存储所有URL
        temp_list = []   # 存储外链URL
        quen_list = []   # 待爬队列
        count = 0        # 计数器

2. 爬虫核心逻辑

def sprider(self, reg, url, domain_url):
    if url not in temp_list2:
        temp_list2.append(url)  # 记录已访问URL
        self.url_list.addItem(str(url))  # UI显示
        QApplication.processEvents()
        
        x = self.link_url(url)  # 获取页面内容
        if x != None:
            html = etree.HTML(x.content)  # 解析HTML
            tpl_content = self.get_tpt_content(reg, html)  # 提取链接
            filter_list = self.get_filter_list(url, tpl_content)  # 处理链接
            self.cycle(filter_list, domain_url)  # 分类处理

3. 链接提取与处理

def get_tpt_content(self, reg, html):
    all_content = []
    for r in reg:  # 遍历所有标签属性(href/src/link)
        try:
            tpl_content = list(set(html.xpath(r)))  # 去重
        except:
            continue
        # 清理数据
        tpl_content = [tp for tp in tpl_content if tp != '']
        tpl_content = [' '.join([i.strip() for i in tp.strip().split('\t')]) 
                      for tp in tpl_content]
        all_content += tpl_content
    return set(all_content)

4. 链接分类逻辑

def cycle(self, filter_list, domain_url):
    flag = 0
    temp_filter_list = []
    set(filter_list)
    
    for fl in filter_list:
        for d_url in domain_url:
            if d_url in fl:  # 站内链接
                if fl not in temp_list2:
                    temp_filter_list.append(fl)
                    flag = 1
            else:  # 外链
                temp_list.append(fl)
                self.wl_list.addItem(str(fl))
                QApplication.processEvents()
    
    if flag == 1:  # 将站内链接加入队列继续爬取
        for te in set(temp_filter_list):
            quen_list.append(te)
        time.sleep(0.01)  # 礼貌爬取

5. URL规范化处理

def get_filter_list(self, url, tpl_content):
    filter_list1 = []
    # 提取URL前缀(协议+域名)
    paren = r"(?:https|http)?w.]da-zA-Z]))+(?:[com|cn|org|js|css|img|net]+)"
    url_qinzui = re.findall(paren, url)[0]
    
    for tpl_c in tpl_content:
        if tpl_c[0:4] != 'http':
            if tpl_c[0:1] == '/':
                tpl = url_qinzui + tpl_c
            elif tpl_c[0:1] != '/':
                tpl = url_qinzui + '/' + tpl_c
            elif tpl_c[0:3] == 'www':
                tpl = tpl_c
            else:
                tpl = url_qinzui + '/' + tpl_c
            filter_list1.append(tpl)
        else:
            filter_list1.append(tpl_c)
    return filter_list1

0X03 关键技术点

1. 反爬虫处理方案

  • 使用标准浏览器User-Agent头
  • 设置合理的请求间隔(time.sleep)
  • 配合甲方运维设置白名单
  • 请求时设置超时(timeout=2)
def link_url(self, url):
    head = {
        'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:90.0) Gecko/20100101 Firefox/90.0'
    }
    try:
        x = requests.get(url, allow_redirects=False, headers=head, timeout=2)
        if x != None:
            return x
    except:
        print('无法连接' + url)

2. 广度优先搜索实现

使用队列(quen_list)替代递归,避免递归深度问题:

def pool_pc(self, p_list, seedUrl, domain_url):
    # 初始URL处理
    self.sprider(p_list, seedUrl, domain_url)
    
    # 队列处理
    while quen_list:
        url = quen_list.pop(0)  # 从队列头部取出
        self.sprider(p_list, url, domain_url)
    
    QMessageBox.about(self, '', '爬虫完毕')

3. 结果分类输出

将结果按类型分类保存:

def write_text(self):
    url_list = []  # 普通URL
    css_list = []   # CSS文件
    js_list = []    # JS文件
    img_list = []   # 图片文件
    
    all_list = list(set(temp_list2))
    for a in all_list:
        h_3 = (a[-3:]).lower()
        h_4 = (a[-4:]).lower()
        if h_3 == '.js':
            js_list.append(a)
        elif h_4 == '.css':
            css_list.append(a)
        elif h_4 == '.jpg' or h_4 == '.png' or h_4 == '.gif':
            img_list.append(a)
        else:
            url_list.append(a)
    
    return ['URL列表为:'] + url_list + ['\n\nJS列表为:'] + js_list + 
           ['\n\nCSS列表为'] + css_list + ['\n\n图片列表为'] + img_list

0X04 使用说明

1. 软件打包

pyinstaller -F --icon=favicon.icon spider_wl.py --noconsole

2. 运行参数

  • URL输入框:输入要爬取的起始URL(如https://www.example.com)
  • Domain输入框:输入标识本站的字符串,多个用分号分隔(如example;test)

3. 功能按钮

  1. 开始爬取:启动爬虫程序
  2. 导出URL:将所有URL保存到url.txt
  3. 导出外链:将所有外链URL保存到wl_url.txt

0X05 开发经验总结

1. 遇到的问题及解决方案

问题 解决方案
反爬虫机制 使用标准请求头,配合运维设置白名单
连接异常 增加异常处理,跳过无效URL
正则不准确 优化正则表达式,多次测试调整
递归问题 改用队列实现广度优先搜索
变量传递 使用全局变量替代参数传递

2. 最佳实践建议

  1. 爬虫礼仪

    • 设置合理的请求间隔
    • 遵守robots.txt规则
    • 控制并发数量
  2. 代码健壮性

    • 增加完善的异常处理
    • 记录爬取日志
    • 支持断点续爬
  3. 性能优化

    • 使用多线程/多进程
    • 实现去重机制
    • 优化正则表达式
  4. 扩展功能

    • 添加深度控制参数
    • 支持代理设置
    • 增加结果分析功能

0X06 完整代码结构

spider_wl.py
├── mwindow类
│   ├── __init__: 初始化UI和参数
│   ├── initUi: 绑定按钮事件
│   ├── initarg: 初始化全局变量
│   ├── add_list: 开始爬取入口
│   ├── sprider: 爬虫核心方法
│   ├── cycle: 链接分类处理
│   ├── get_filter_list: URL规范化
│   ├── get_tpt_content: 提取页面链接
│   ├── link_url: 请求页面内容
│   ├── write_text: 结果分类
│   ├── out_url: 导出URL
│   ├── out_wl_url: 导出外链
│   └── pool_pc: 队列调度
└── 主程序入口

通过本工具,可以高效完成网站外链的深度爬取和分析工作,满足甲方安全审计的需求。开发者可根据实际需求进一步扩展功能,如增加自动化分析、危险链接识别等高级特性。

网站外链深度爬取工具开发指南 0X00 项目背景 甲方安全需求:需要对集团各类门户网站进行外链查询,检查是否存在违规或恶意链接。 技术挑战: 需要递归查找所有页面下的外链 短时间内完成大量网站的收集工作 需要区分站内链接和站外链接 0X01 技术方案设计 整体思路 爬取策略 :采用广度优先搜索(BFS)方式遍历网站 链接识别 :通过HTML标签属性(href/src/link)提取链接 链接分类 :根据域名标识区分站内链接和站外链接 结果输出 :分类保存URL到不同文件 技术选型 GUI框架 :PyQt5 爬虫库 :requests + lxml 正则处理 :re 打包工具 :PyInstaller 0X02 核心功能实现 1. 主程序结构 2. 爬虫核心逻辑 3. 链接提取与处理 4. 链接分类逻辑 5. URL规范化处理 0X03 关键技术点 1. 反爬虫处理方案 使用标准浏览器User-Agent头 设置合理的请求间隔(time.sleep) 配合甲方运维设置白名单 请求时设置超时(timeout=2) 2. 广度优先搜索实现 使用队列(quen_ list)替代递归,避免递归深度问题: 3. 结果分类输出 将结果按类型分类保存: 0X04 使用说明 1. 软件打包 2. 运行参数 URL输入框 :输入要爬取的起始URL(如https://www.example.com) Domain输入框 :输入标识本站的字符串,多个用分号分隔(如example;test) 3. 功能按钮 开始爬取 :启动爬虫程序 导出URL :将所有URL保存到url.txt 导出外链 :将所有外链URL保存到wl_ url.txt 0X05 开发经验总结 1. 遇到的问题及解决方案 | 问题 | 解决方案 | |------|----------| | 反爬虫机制 | 使用标准请求头,配合运维设置白名单 | | 连接异常 | 增加异常处理,跳过无效URL | | 正则不准确 | 优化正则表达式,多次测试调整 | | 递归问题 | 改用队列实现广度优先搜索 | | 变量传递 | 使用全局变量替代参数传递 | 2. 最佳实践建议 爬虫礼仪 : 设置合理的请求间隔 遵守robots.txt规则 控制并发数量 代码健壮性 : 增加完善的异常处理 记录爬取日志 支持断点续爬 性能优化 : 使用多线程/多进程 实现去重机制 优化正则表达式 扩展功能 : 添加深度控制参数 支持代理设置 增加结果分析功能 0X06 完整代码结构 通过本工具,可以高效完成网站外链的深度爬取和分析工作,满足甲方安全审计的需求。开发者可根据实际需求进一步扩展功能,如增加自动化分析、危险链接识别等高级特性。