Python的反爬技术一直研究不明白

比如 xxfb.mwr.cn/sq_djdh.html 全国水情数据,不知道怎么搞

讨论数量: 14

当然可以,以下是关于 Python 反爬技术的系统性总结,包括基本策略、中高级技术以及应对常见爬虫行为的方法,适用于开发网站、接口服务等需要保护数据不被恶意抓取的场景。


🛡️ Python 反爬虫技术总结

一、基本反爬策略

1. User-Agent 识别

  • 拦截非浏览器 User-Agent(如 Python requests、Scrapy 等默认值)
  • 实现方式:
    ua = request.headers.get("User-Agent")
    if "python" in ua.lower() or "scrapy" in ua.lower():
        return HttpResponseForbidden()

2. IP 限速与封禁

  • 根据单位时间内请求次数限制访问频率(Rate limiting)
  • 加入黑名单:连续触发规则即临时封禁 IP

3. 验证码(CAPTCHA)

  • 针对可疑行为请求验证码,如滑块、人机验证图像

4. Referer 检查

  • 检测请求来源页面,若为空或非本站来源,视为爬虫行为

二、中级反爬策略

1. JavaScript 渲染

  • 将关键数据通过 JS 异步加载
  • 例如使用 Vue、React 前端,后端 API 加密或延迟加载数据

2. 动态 Token / 参数加密

  • 请求时加入动态生成的 token(如 timestamp + 签名)
  • 参数加密防止爬虫直接构造请求

3. 行为识别与分析

  • 分析用户行为轨迹:
    • 鼠标移动轨迹
    • 页面停留时间
    • 滚动频率
  • 可用 JS SDK 实现行为数据上传分析

4. Session / Cookie 校验

  • 要求用户登录并维持 session
  • 检查 Cookie 的一致性与生命周期

三、高级反爬策略

1. 设备指纹识别

  • 收集并绑定访问者的设备指纹(浏览器、系统、插件等信息)
  • 防止更换 IP 或 User-Agent 伪装

2. API 网关 + 动态验证

  • 利用 API Gateway 层进行访问控制与数据加解密
  • 可通过 JWT + RSA 加密访问令牌(access token)

3. 无头浏览器识别

  • 检测 puppeteer / selenium 等特征:
    • navigator.webdriver == True
    • 判断 Chrome 扩展属性是否存在
    • 检查 window.navigator.plugins、语言、字体等信息异常

4. 蜜罐链接(Honeypot Links)

  • 页面中放置隐藏链接,只有爬虫才会点击,触发封禁策略

四、配合工具推荐

工具 用途
Cloudflare Bot Management 云端智能识别并阻断爬虫
AWS WAF / 阿里云 WAF 配置规则限制访问流量和频率
F5 / Nginx 反向代理 加入层级验证机制
Redis / MongoDB 存储 IP 行为、频率数据用于封禁

五、反爬与合法性提醒

虽然反爬技术可以有效保护资源,但也需要遵守隐私保护和合理使用原则:

  • 避免误伤真实用户
  • 合理设置验证码频率
  • 尊重爬虫访问的合法性与 robots.txt 协议
1天前 评论

我第二次遇到这种乱码加密了。我之前的做法是用OCR识别

有没有大佬给个方向,怎么分析这种乱码加密呀

file

{
            "addvnm": "#pc9LegLrrd_1744617145580otltag䔿㾙#FontTag",
            "alertValue": 0.0,
            "bsnm": "#pc9LegLrrd_1744617145580otltag䔿䇥#FontTag",
            "createTime": "2025-04-11 15:40:21",
            "idNo": "#pc9LegLrrd_1744617145580otltag㵛㵟㵧#FontTag",
            "importantSection": "#pc9LegLrrd_1744617145580otltag㻡#FontTag",
            "lgtd": "",
            "lttd": "",
            "rvnm": "#pc9LegLrrd_1744617145580otltag䌋䌅䇥#FontTag",
            "stType": "#pc9LegLrrd_1744617145580otltag㶓㶅㶛㶁㶓#FontTag",
            "stnm": "#pc9LegLrrd_1744617145580otltag㶳䗑#FontTag",
            "tm": "2025-04-11 08:00:00",
            "z": "#pc9LegLrrd_1744617145580otltag㵣㵛.㵫㵣#FontTag"
        }
1天前 评论
勇敢的心 1天前
faxi (楼主) 1天前
sinmu (作者) 1天前

研究了下原理

他这个网站在后端拿到的数据就是乱码

然后通过字体渲染的方式来让肉眼看起来正常。AI告诉我这个叫【自定义的字符实体编码】

解决的方式

搜索网页上CSS文件的字体声明【@font-face】

就可以拿到ttf的字体文件。

拿到之后可以用 FontForge 进行查看映射关系,类似于下图

Python

悲伤的是,没有找到python导出映射关系的方式。也不知道如何导出一个映射文件

另外:页面每次刷新,字体文件都会变

1天前 评论
faxi (楼主) 1天前

关系已经处理好了,一看到那个加密字解决头痛,不知道怎么做映射了

file

file

file

1天前 评论
sinmu 1天前

我昨天提取了一部分这个东西

file

你看看能不能找到中文的映射呢?

file

我昨天提取的代码如下

from fontTools.ttLib import TTFont
import json

font_file_path = 'opvTZwpcKN_1744622522766.ttf'  # 替换为您的字体文件路径
output_json_path = 'font_mapping.json'       # 输出 JSON 文件的路径

try:
    font = TTFont(font_file_path)

    # 获取 cmap 表 (Character to Glyph Mapping Table)
    cmap_table = None
    if 'cmap' in font:
        cmap_table = font['cmap']
    else:
        print("Error: No 'cmap' table found in the font file.")
        exit()

    # 选择 Unicode 平台和编码的 cmap (通常是 platformID=0, platEncID=3 或 platformID=3, platEncID=1)
    unicode_cmap = None
    for table in cmap_table.tables:
        if table.platformID in [0, 3] and table.platEncID in [1, 3, 10]: # 常见的 Unicode cmap 组合
            unicode_cmap = table
            break

    if not unicode_cmap:
        print("Error: No suitable Unicode cmap table found.")
        exit()

    # 获取字符映射关系 (Unicode code point -> glyph name)
    char_map = unicode_cmap.cmap

    # 将 glyph name 替换为实际的字符 (如果可能,但这可能比较复杂,这里先简化为 glyph name)
    # 如果您需要将 glyph name 进一步解析为字符,可能需要更复杂的逻辑,
    # 比如查找 'glyf' 表,但这超出基本映射导出的范围。
    # 这里我们先直接使用 glyph name 作为映射值。
    mapping_data = {}
    for unicode_code_point, glyph_name in char_map.items():
        char = chr(unicode_code_point) # 将 Unicode code point 转换为字符
        mapping_data[char] = glyph_name # 或者如果您只需要 code point,可以 mapping_data[hex(unicode_code_point)] = glyph_name


    # 导出为 JSON 文件
    with open(output_json_path, 'w', encoding='utf-8') as f:
        json.dump(mapping_data, f, indent=4, ensure_ascii=False) # ensure_ascii=False 防止中文乱码

    print(f"字符映射关系已导出到 {output_json_path}")

except Exception as e:
    print(f"发生错误: {e}")
1天前 评论
faxi (楼主) 1天前
sinmu (作者) 1天前
sinmu (作者) 1天前
sinmu (作者) 1天前

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!