12306反反爬虫策略:Python网络请求优化实战

一、引言:12306反爬虫的严峻挑战

12306作为中国铁路售票系统,每天面临着海量的抢票请求,其反爬虫机制异常严格:IP封锁、验证码、请求频率限制、会话追踪等。要在这样的环境下实现稳定抢票,必须设计一套完善的反反爬虫策略。12306抢票项目通过CDN加速、代理IP、请求频率控制和"小黑屋"机制等技术,成功突破了12306的反爬虫防线。

二、CDN加速:突破网络瓶颈

1. 实现原理

CDN(内容分发网络)通过将资源分发到全球各地的节点,使用户可以就近获取所需内容,提高访问速度。12306项目通过筛选和使用高速CDN节点,加速与12306服务器的通信。

2. 代码实现

核心文件d:\python-code\12306-master\init\select_ticket_info.py

python 复制代码
def cdn_certification(self):
    """CDN认证与筛选"""
    if self.is_cdn == 1:
        CDN = CDNProxy()
        all_cdn = CDN.open_cdn_file()
        if all_cdn:
            print("开启cdn查询")
            print("本次待筛选cdn总数为{}, 筛选时间大约为5-10min".format(len(all_cdn)))
            t = threading.Thread(target=self.cdn_req, args=(all_cdn,))
            t.setDaemon(True)
            t.start()
        else:
            raise ticketConfigException("cdn列表为空,请先加载cdn")

def cdn_req(self, cdn):
    """测试并筛选可用CDN节点"""
    for i in range(len(cdn) - 1):
        http = HTTPClient(0)
        urls = self.urls["loginInitCdn"]
        http._cdn = cdn[i].replace("\n", "")
        start_time = datetime.datetime.now()
        rep = http.send(urls)
        # 筛选响应时间<500ms的可用CDN
        if rep and "message" not in rep and (datetime.datetime.now() - start_time).microseconds / 1000 < 500:
            if cdn[i].replace("\n", "") not in self.cdn_list:
                self.cdn_list.append(cdn[i].replace("\n", ""))

3. 实现细节

  • cdn_list文件读取CDN节点列表
  • 多线程测试CDN响应速度
  • 筛选响应时间<500ms的可用节点
  • 动态更新可用CDN列表

三、代理IP:隐藏真实身份

1. 实现原理

使用代理IP可以隐藏真实IP地址,避免因频繁请求导致的IP封锁。12306项目支持自动爬取和筛选代理IP。

2. 代码实现

核心文件d:\python-code\12306-master\agency\agency_tools.py

python 复制代码
def filter_proxy(self):
    """筛选可用代理IP"""
    socket.setdefaulttimeout(1)
    path = os.path.join(os.path.dirname(__file__), './proxy_list')
    f = open(path, "w")
    url = "http://icanhazip.com"  # 用于验证代理IP
    for proxy in self.proxy_list:
        proxy_temp = {"https": "https://{}".format(proxy)}
        try:
            req = requests.get(url, proxies=proxy_temp, timeout=2, headers=head).content
            write_proxy = proxy + "\n"
            f.write(write_proxy)
        except Exception:
            print("代理链接超时,去除此IP:{0}".format(proxy))
            continue

3. 实现细节

  • 从西刺代理网站爬取免费代理IP
  • 使用icanhazip.com验证代理可用性
  • 将可用代理保存到proxy_list文件
  • 随机选择代理IP进行请求

四、请求频率控制:模拟正常用户行为

1. 实现原理

通过随机调整请求间隔,模拟真实用户的操作行为,避免触发12306的请求频率限制。

2. 代码实现

核心文件d:\python-code\12306-master\init\select_ticket_info.py

python 复制代码
def main(self):
    # ... 初始化代码 ...
    while 1:
        try:
            num += 1
            now = datetime.datetime.now()
            configCommon.checkSleepTime(self)  # 夜间休眠控制
            
            # 预售模式vs捡漏模式,不同请求频率
            if self.order_model == 1:  # 预售模式
                sleep_time_s = 0.5
                sleep_time_t = 0.6
                # 精准时间控制,到点立即刷新
                while not now.strftime("%H:%M:%S") == self.open_time:
                    now = datetime.datetime.now()
                    if now.strftime("%H:%M:%S") > self.open_time:
                        break
                    time.sleep(0.0001)
            else:  # 捡漏模式
                sleep_time_s = 0.5
                sleep_time_t = 3
            
            # 执行余票查询
            q = query(session=self, from_station=from_station, to_station=to_station, ...)
            queryResult = q.sendQuery()
            
            # 有余票则提交订单,否则随机休眠
            if not queryResult.get("status", False):
                # 随机休眠,避免固定频率
                random_time = round(random.uniform(sleep_time_s, sleep_time_t), 2)
                print(u"正在第{0}次查询 随机停留时长:{1}...".format(num, random_time))
                time.sleep(random_time)

3. 实现细节

  • 动态睡眠机制:根据模式调整休眠时间
  • 夜间休眠:避免非高峰期无效请求
  • 精准时间控制:预售模式下到点立即刷新
  • 随机休眠时长:0.5-3秒随机波动,模拟真实用户

五、小黑屋机制:智能规避无效请求

1. 实现原理

"小黑屋"机制用于临时屏蔽异常车次,避免无效请求浪费资源,提高抢票效率。

2. 代码实现

核心文件d:\python-code\12306-master\config\TicketEnmu.pyd:\python-code\12306-master\init\select_ticket_info.py

python 复制代码
# 小黑屋配置(TicketEnmu.py)
QUERY_IN_BLACK_LIST = u"该车次{} 正在被关小黑屋,跳过此车次"
TICKET_BLACK_LIST_TIME = 5  # 小黑屋时长,默认5分钟

# 小黑屋使用(select_ticket_info.py)
if wrapcache.get(train_no):
    print(ticket.QUEUE_WARNING_MSG.format(train_no))
else:
    # 正常处理车次
    # 有余票时提交订单
    if queryResult.get("status", False):
        # ... 订单提交逻辑 ...
        # 处理排队异常,加入小黑屋
        if "status" in queue_count and queue_count["status"]:
            if queue_count["data"]["ticket"] == "false":
                wrapcache.set(train_no, train_no, ticket.TICKET_BLACK_LIST_TIME * 60)
                print(ticket.QUEUE_JOIN_BLACK.format(queue_count["data"]["msg"], stationTrainCode))

3. 实现细节

  • 触发条件:排队异常、僵尸票、未知错误
  • 时长配置:默认5分钟,可通过配置文件修改
  • 缓存实现 :使用wrapcache库标记小黑屋车次
  • 自动释放:到期后自动从小黑屋释放

六、反反爬虫策略总结

12306项目的反反爬虫策略通过多层防护,有效规避了12306的反爬虫机制:

策略 实现方式 核心优势
CDN加速 筛选高速CDN节点 提高请求速度,分散请求压力
代理IP 自动爬取和筛选 隐藏真实IP,避免被封
请求频率控制 随机休眠、夜间休眠 模拟正常用户行为
小黑屋机制 临时屏蔽异常车次 提高资源利用率,避免无效请求

七、代码优化建议

  1. CDN自动更新:定期自动更新CDN列表,确保节点可用性
  2. 代理IP池优化:增加付费代理IP支持,提高稳定性
  3. 智能请求频率:根据12306响应调整请求频率,实现动态优化
  4. 分布式部署:支持多机分布式抢票,进一步分散请求压力
  5. 验证码AI识别:集成AI模型,提高自动验证码识别率

八、结语:反反爬虫的未来

随着12306反爬虫机制的不断升级,反反爬虫策略也需要持续演进。未来的反反爬虫技术将更加智能化,结合机器学习、分布式架构和更精细的请求模拟,实现更高效、更稳定的抢票服务。

通过学习12306项目的反反爬虫策略,我们可以更好地理解网络请求优化的核心原理,掌握各种反反爬虫技术的实现方法,为构建更强大的网络应用打下基础。


参考资料

  • 12306抢票项目源码
  • Python标准库文档
  • 网络爬虫与反爬虫技术白皮书
相关推荐
deephub6 小时前
DeepSeek-R1 与 OpenAI o3 的启示:Test-Time Compute 技术不再迷信参数堆叠
人工智能·python·深度学习·大语言模型
力江7 小时前
FastAPI 最佳架构实践,从混乱到优雅的进化之路
python·缓存·架构·单元测试·fastapi·分页·企业
Raink老师7 小时前
第 11 章 错误处理与异常
python
Lululaurel7 小时前
AI编程文本挖掘提示词实战
人工智能·python·机器学习·ai·ai编程·提示词
znhy60587 小时前
分布计算系统
网络·分布式
HappRobot7 小时前
Python 面向对象
开发语言·python
liebe1*17 小时前
第七章 防火墙地址转换
运维·服务器·网络
BoBoZz198 小时前
AlignTwoPolyDatas 基于ICP算法的配准和相机视角切换
python·vtk·图形渲染·图形处理
KingRumn8 小时前
Linux同步机制之信号量
linux·服务器·网络