某程旅行小程序爬虫技术解析与实战案例

简介: 某程旅行小程序爬虫技术解析与实战案例

一、小程序爬虫核心技术认知

  1. 小程序与传统 Web 爬虫的核心差异
    传统 Web 爬虫主要针对 PC 端或移动端网页,基于 HTML 解析、Cookie 维持、HTTP/HTTPS 请求模拟即可完成大部分数据抓取工作。而小程序爬虫的核心差异体现在三个方面:
    传输协议与数据格式:小程序后端接口多采用 JSON 格式传输数据,极少返回完整 HTML 页面,无需进行 DOM 解析,重点在于接口参数解密与响应数据提取;
    身份验证机制:小程序普遍采用 wx.login 生成的 code、session_key、openid 等进行用户身份验证,部分接口还会携带自定义签名(如 sign 参数),防止非法请求;
    抓包与调试限制:小程序运行在微信的沙箱环境中,默认禁止外部工具直接抓包,且存在反爬机制(如接口频率限制、设备指纹验证、参数时效性校验)。
  2. 小程序爬虫必备核心技术栈
    完成某程旅行小程序爬虫开发,需要掌握以下核心技术:
    抓包技术:使用 Fiddler、Charles 等工具配置代理,突破微信沙箱环境限制,捕获小程序的网络请求;
    接口分析技术:解析请求头、请求参数、响应数据的结构,识别加密参数(如 sign、timestamp、nonce)的生成逻辑;
    请求模拟技术:基于 Python 的 requests、aiohttp 库模拟小程序的 HTTP/HTTPS 请求,维持会话状态;
    数据处理技术:使用 json、pandas 库解析、清洗、存储抓取到的 JSON 数据;
    反反爬应对技术:实现请求频率控制、UA 伪装、签名参数模拟等,规避小程序的反爬策略。
    二、前期准备工作
  3. 环境与工具搭建
    开发环境:Python 3.8+(兼容性好,第三方库生态完善),推荐使用 Anaconda 管理环境;
    抓包工具:Charles(跨平台,操作友好,适合小程序抓包);
    Python 第三方库:安装必备依赖
    requests:模拟 HTTP/HTTPS 请求;
    pandas:数据清洗与存储;
    pycryptodome:应对可能的接口数据加密(如 AES、DES);
    fake-useragent:生成随机 User-Agent,伪装请求来源。
  4. Charles 抓包配置(关键步骤)
    小程序运行在微信环境中,需配置代理才能捕获其网络请求,步骤如下:
    打开 Charles,进入「Proxy」→「Proxy Settings」,设置端口(如 8888),勾选「Enable transparent HTTP proxying」;
    配置电脑本机代理,将 HTTP/HTTPS 代理指向 Charles 的 IP 与端口(本地 IP+8888);
    安装 Charles 证书:进入「Help」→「SSL Proxying」→「Install Charles Root Certificate」,完成证书信任配置(重点:移动端 / 微信需安装对应证书);
    微信小程序抓包配置:打开手机微信(或电脑微信模拟器),连接与电脑同一局域网,配置手机代理为电脑 IP+8888,安装 Charles 手机证书;
    开启 SSL 代理:在 Charles 中右键点击目标请求(某程旅行小程序相关),选择「Enable SSL Proxying」,即可捕获 HTTPS 加密请求。
  5. 合规性声明
    重要提醒:本文所有技术内容仅用于技术研究与学习,不得用于商业用途或非法数据抓取。
    某程旅行小程序的所有数据均受《中华人民共和国著作权法》《网络安全法》保护,抓取前需确认是否获得平台授权;
    不得突破平台的反爬机制,不得进行高频次请求影响平台服务器正常运行;
    抓取的数据不得用于传播、售卖、竞品分析等违规场景,仅可用于个人技术研究。
    三、某程旅行小程序接口分析
  6. 目标接口定位
    打开某程旅行小程序,进入「酒店」板块,选择某一城市(如北京),筛选入住 / 离店日期,触发数据加载。此时在 Charles 中可捕获到对应的酒店列表接口,特征如下:
    请求方式:POST(部分接口为 GET);
    请求域名:多为某程官方域名(如api.ctrip.com,实际需以抓包结果为准);
    请求头:包含User-Agent(小程序专属 UA,格式如Mozilla/5.0 (iPhone; CPU iPhone OS 16_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148 MicroMessenger/8.0.30(0x18001e31) NetType/WIFI MiniProgramEnv/Windows WindowsWechat/3.9.5.81)、Referer、Content-Type(application/json)等;
    请求参数:包含cityId(城市 ID)、checkInDate(入住日期)、checkOutDate(离店日期)、pageNum(页码)、pageSize(每页条数)、sign(签名参数)、timestamp(时间戳)等;
    响应数据:JSON 格式,包含酒店 ID、酒店名称、价格、评分、地址等核心字段,无复杂加密(部分接口可能对响应数据进行 AES 加密,需进一步解析)。
  7. 关键参数解析
    本次实战以未加密的公开接口(模拟场景,贴合技术学习需求)为例,核心参数说明:
    参数名
    含义
    取值示例
    cityId
    城市 ID
    1(北京)
    checkInDate
    入住日期
    2026-01-15
    checkOutDate
    离店日期
    2026-01-18
    pageNum
    页码
    1
    pageSize
    每页条数
    20
    timestamp
    时间戳(毫秒级)
    1736985600000
    sign
    签名(简化版,实际为参数拼接加密)
    md5(cityId+checkInDate+timestamp+secret)
    其中,sign参数是小程序接口的核心反爬手段之一,通常由平台后端约定的 secret 密钥 + 请求参数拼接后进行 MD5/SHA256 加密生成。本次实战中,我们模拟简化版签名生成逻辑(实际场景需通过逆向工程解析小程序源码获取完整签名逻辑)。
    四、实战:某程旅行小程序酒店数据爬虫开发
  8. 爬虫核心流程设计
    定义配置参数(城市 ID、日期、页码、请求域名等);
    实现签名参数生成逻辑(模拟 MD5 加密);
    伪装请求头,构造完整请求参数;
    发送 HTTP 请求,获取响应数据;
    解析 JSON 响应,提取核心酒店数据;
    数据清洗与存储(保存为 CSV 文件);
    实现多页数据抓取,添加请求延迟,规避反爬。
  9. 完整实现代码
    python
    运行
    ```
    import requests
    import pandas as pd
    import time
    import hashlib
    from fake_useragent import UserAgent
    from typing import List, Dict

class CtripMiniProgramSpider:
"""
某程旅行小程序酒店数据爬虫(仅用于技术学习)
"""
def init(self):

    # 基础配置
    self.base_url = "https://api.ctrip.com/hotel/list"  # 模拟接口,实际以抓包为准
    self.city_id = "1"  # 北京城市ID
    self.check_in_date = "2026-01-15"  # 入住日期
    self.check_out_date = "2026-01-18"  # 离店日期
    self.page_size = 20  # 每页条数
    self.max_page = 5  # 最大抓取页码
    self.secret = "ctrip_mini_program_secret_123"  # 模拟secret密钥,实际需逆向获取
    self.session = requests.Session()  # 维持会话状态
    self.ua = UserAgent()  # 随机生成UA
    self.all_hotel_data: List[Dict] = []  # 存储所有酒店数据

def generate_sign(self, params: Dict) -> str:
    """
    生成签名参数(模拟MD5加密逻辑,实际需贴合平台真实算法)
    :param params: 核心请求参数
    :return: 加密后的签名字符串
    """
    # 1. 按平台约定的顺序拼接参数(关键:参数顺序必须与小程序一致)
    sign_str = f"{params['cityId']}{params['checkInDate']}{params['checkOutDate']}{params['timestamp']}{self.secret}"
    # 2. MD5加密
    md5_obj = hashlib.md5()
    md5_obj.update(sign_str.encode("utf-8"))
    return md5_obj.hexdigest().upper()  # 转为大写,贴合多数平台签名格式

def get_request_params(self, page_num: int) -> Dict:
    """
    构造完整的请求参数
    :param page_num: 页码
    :return: 完整请求参数
    """
    # 1. 生成毫秒级时间戳
    timestamp = int(time.time() * 1000)
    # 2. 核心参数(无签名)
    core_params = {
        "cityId": self.city_id,
        "checkInDate": self.check_in_date,
        "checkOutDate": self.check_out_date,
        "pageNum": page_num,
        "pageSize": self.page_size,
        "timestamp": timestamp
    }
    # 3. 生成签名并添加到参数中
    core_params["sign"] = self.generate_sign(core_params)
    return core_params

def get_request_headers(self) -> Dict:
    """
    构造请求头,伪装小程序请求
    :return: 请求头字典
    """
    return {
        "User-Agent": self.ua.random,  # 随机UA
        "Content-Type": "application/json; charset=utf-8",
        "Referer": "https://servicewechat.com/wx1234567890abcdef/0/page-frame.html",  # 模拟小程序Referer
        "Accept": "application/json, text/plain, */*",
        "X-Requested-With": "XMLHttpRequest"
    }

def parse_hotel_data(self, response_json: Dict) -> None:
    """
    解析响应数据,提取核心酒店信息
    :param response_json: 接口返回的JSON数据
    """
    try:
        # 模拟响应数据结构,实际以抓包的接口响应为准
        hotel_list = response_json.get("data", {}).get("hotelList", [])
        if not hotel_list:
            print("当前页码无酒店数据")
            return
        # 提取核心字段
        for hotel in hotel_list:
            hotel_info = {
                "hotel_id": hotel.get("hotelId", ""),
                "hotel_name": hotel.get("hotelName", ""),
                "price": hotel.get("lowestPrice", 0),
                "score": hotel.get("hotelScore", 0.0),
                "address": hotel.get("address", ""),
                "star_rating": hotel.get("starRating", ""),
                "check_in_date": self.check_in_date,
                "check_out_date": self.check_out_date

```

  1. 代码关键说明
    会话维持:使用requests.Session()维持会话状态,避免每次请求重新建立连接,同时可自动保存 Cookie,适配需要登录验证的接口;
    签名生成:模拟 MD5 加密逻辑,实际场景中需通过反编译小程序(如使用 Jadx、Frida 工具)获取真实的签名参数拼接顺序和加密算法;
    反反爬策略:使用fake-useragent生成随机 UA,添加time.sleep(2)控制请求频率,避免高频请求触发平台风控,使用高匿代理IP避免引起反爬,例如亿牛云隧道代理
    数据存储:使用pandas将数据保存为 CSV 文件,指定encoding="utf-8-sig"防止中文乱码,方便后续数据分析;
    异常处理:添加try-except捕获请求异常和数据解析异常,提高爬虫的稳定性。
  2. 运行结果与后续优化
    运行结果:执行代码后,控制台会输出各页码的抓取状态,最终在当前目录生成ctrip_hotel_data.csv文件,包含酒店 ID、名称、价格等核心字段,可直接用 Excel 打开查看;
    后续优化方向:
    逆向解析真实签名逻辑:使用 FridaHook 小程序的加密函数,获取完整的sign生成算法;
    处理加密响应数据:若接口响应为 AES 加密,添加pycryptodome的解密逻辑,解析真实数据;
    实现异步抓取:使用aiohttp替代requests,提高多页数据的抓取效率;
    增加数据去重:针对hotel_id进行去重,避免重复抓取相同酒店数据;
    完善日志记录:使用logging模块替代print,方便排查抓取过程中的问题。
    五、总结与风险提示
  3. 核心总结
    本文围绕某程旅行小程序爬虫展开,从技术差异、前期准备、接口分析到实战开发,完整呈现了小程序爬虫的落地流程。核心要点如下:
    小程序爬虫的核心在于抓包配置与接口参数解析,尤其是签名等加密参数的模拟;
    合规性是爬虫开发的前提,不得触碰平台数据安全与服务器稳定的红线;
    反反爬策略的核心是 “伪装” 与 “节制”,模拟正常用户请求,控制请求频率;
    实战代码仅为技术演示,实际落地需根据平台接口的真实情况进行调整与优化。
相关文章
|
3月前
|
数据采集 自然语言处理 数据可视化
时序数据分析:Python爬取新浪财经频道新闻并绘制趋势图
时序数据分析:Python爬取新浪财经频道新闻并绘制趋势图
|
3月前
|
Web App开发 数据采集 前端开发
集成Scrapy与异步库:Scrapy+Playwright自动化爬取动态内容
集成Scrapy与异步库:Scrapy+Playwright自动化爬取动态内容
|
4月前
|
JSON 前端开发 JavaScript
从携程爬取的杭州酒店数据中提取价格、评分与评论的关键信息
从携程爬取的杭州酒店数据中提取价格、评分与评论的关键信息
|
1月前
|
数据采集 机器学习/深度学习 人工智能
未来趋势:AI 时代下 python 爬虫技术的发展方向
未来趋势:AI 时代下 python 爬虫技术的发展方向
|
2月前
|
数据采集 存储 分布式计算
海量小说数据采集:Spark 爬虫系统设计
海量小说数据采集:Spark 爬虫系统设计
|
2月前
|
数据采集 JavaScript 前端开发
拼多多数据抓取:Python 爬虫中的 JS 逆向基础案例分析
拼多多数据抓取:Python 爬虫中的 JS 逆向基础案例分析
|
3月前
|
数据采集 存储 JSON
构建1688店铺商品数据集:Python爬虫数据采集与格式化实践
构建1688店铺商品数据集:Python爬虫数据采集与格式化实践
|
4月前
|
Web App开发 数据采集 JavaScript
利用Selenium和PhantomJS提升网页内容抓取与分析的效率
利用Selenium和PhantomJS提升网页内容抓取与分析的效率
|
4月前
|
数据采集 Web App开发 JSON
从快手评论数据中挖掘舆情:Python爬虫与文本分析实战
从快手评论数据中挖掘舆情:Python爬虫与文本分析实战
|
4月前
|
数据采集 人工智能 JSON
Prompt 工程实战:如何让 AI 生成高质量的 aiohttp 异步爬虫代码
Prompt 工程实战:如何让 AI 生成高质量的 aiohttp 异步爬虫代码