一、项目简介与工具优势

DrissionPage 是一个集成了 Selenium 的操作便利性Requests 的数据包捕获能力 的 Python 库。

为什么选择 DrissionPage 而不是 Selenium?

  1. 无需下载驱动:自动处理浏览器内核。
  2. 监听网络响应:可以直接拦截 API 接口返回的 JSON 数据,而无需去解析复杂的 HTML 标签,速度和稳定性大幅提升。
  3. 无缝切换模式:既可以控制浏览器点击翻页,又能直接获取数据包。

二、环境准备

  1. Python 版本:建议 3.8+
  2. 安装依赖库
    pip install DrissionPage
    
  3. 浏览器路径:确保电脑上安装有 Chrome 或 Edge 浏览器。本文示例使用的是 Microsoft Edge

三、核心思路分析

  1. 访问页面:打开携程酒店列表页。
  2. 模拟点击:点击“城市”输入框,触发搜索;点击“好评优先”排序。
  3. 开启监听:使用 listen.start('fetchHotelList') 监听携程用于加载酒店列表的 XHR/Fetch 请求。
  4. 循环翻页:每获取一页数据,滚动到底部,等待接口返回,解析 JSON,写入 CSV。

四、代码详解与实现

以下为完整的爬虫代码,我将在关键步骤后添加注释说明。

1. 导入库与初始化文件
from DrissionPage import ChromiumPage, ChromiumOptions
import csv
import time

# 创建 CSV 文件,注意编码使用 utf-8-sig 防止 Excel 打开乱码
f = open('hotelInfo.csv', 'w+', encoding='utf-8-sig', newline='')
fieldnames = ['酒店名', '城市', '地址', '商圈', '原价', '现价', '评价', '评分', '点评数', '完整分级', '标签', '卫生', '设施', '环境', '服务', '酒店星级']
csv_writer = csv.DictWriter(f, fieldnames=fieldnames)
csv_writer.writeheader()
2. 浏览器配置与初始化操作
# 配置 Edge 浏览器路径
options = ChromiumOptions()
options.set_browser_path(r"C:\Program Files (x86)\Microsoft\Edge\Application\msedge.exe")

chrome = ChromiumPage(options)
chrome.get('https://hotels.ctrip.com/hotels/list/')

# 简单的模拟人工操作:点击城市框、点击排序
time.sleep(2)
chrome.ele('css:.style_dropdown-selector-title__ENzTr').click()
chrome.listen.start('fetchHotelList')  # 开启监听,关键词为接口特征
chrome.ele('text=好评优先').click()
3. 循环获取数据(核心逻辑)
page = 1
while True:
    print(f'正在采集第{page}页的数据')
    try:
        # 等待包含数据的响应返回,超时 15 秒
        response = chrome.listen.wait(timeout=15)
        json_data = response.response.body
        hotelList = json_data.get('data', {}).get('hotelList', [])
        
        if not hotelList:
            print('没有更多数据,采集结束')
            break

        for hotel in hotelList:
            # 安全提取数据,防止字段缺失报错
            hotel_info = hotel.get('hotelInfo', {})
            room_info = hotel.get('roomInfo', [{}])[0] if hotel.get('roomInfo') else {}
            price_info = room_info.get('priceInfo', {})
            comment_info = hotel_info.get('commentInfo', {})

            # 处理价格逻辑(原价与现价)
            delete_price = price_info.get('deletePrice', 0)
            current_price = price_info.get('price', 0)

            # 构建数据字典
            dit = {
                '酒店名': hotel_info.get('nameInfo', {}).get('name', ''),
                '城市': hotel_info.get('positionInfo', {}).get('cityName', ''),
                '地址': hotel_info.get('positionInfo', {}).get('address', ''),
                '商圈': hotel_info.get('positionInfo', {}).get('positionDesc', ''),
                '原价': current_price if delete_price == 0 else delete_price,
                '现价': current_price,
                '评价': comment_info.get('commentDescription', ''),
                '评分': comment_info.get('commentScore', 0),
                '点评数': comment_info.get('commenterNumber', 0),
                '完整分级': comment_info.get('fullRating', ''),
                '标签': comment_info.get('oneSentenceComment', [{}])[0].get('tagTitle', ''),
                '卫生': comment_info.get('subScore', [{}])[0].get('number', 0),
                '设施': comment_info.get('subScore', [{}, {}])[1].get('number', 0),
                '环境': comment_info.get('subScore', [{}, {}, {}])[2].get('number', 0),
                '服务': comment_info.get('subScore', [{}, {}, {}, {}])[3].get('number', 0),
                '酒店星级': hotel_info.get('hotelStar', {}).get('star', 0),
            }
            csv_writer.writerow(dit)
            print(dit)

        page += 1
        # 翻页动作:滚动到底部触发加载更多
        chrome.scroll.to_bottom()
        time.sleep(1)

    except Exception as e:
        print(f'采集出错: {e}')
        break

f.close()
print('采集完成!')

五、运行结果展示

运行脚本后,控制台会打印出采集到的字典数据,同时项目根目录下会生成 hotelInfo.csv 文件。
在这里插入图片描述

用 Excel 打开 CSV 文件,效果如下:
在这里插入图片描述

六、注意事项与优化建议

  1. 浏览器路径修改

    • 如果你使用的是 Chrome,需要修改 set_browser_path 为 Chrome 的安装路径。
    • 如果你不想指定路径,也可以留空,让 DrissionPage 自动查找,但有时会失败。
  2. 监听关键词

    • 代码中使用的是 'fetchHotelList'。如果携程接口更新改变了名称,你需要打开浏览器 F12 -> Network -> Fetch/XHR,找到返回酒店列表的那个请求,将 URL 中的部分关键词替换进去。
  3. 反爬策略

    • 代码中加入了 time.sleep(1) 来控制频率。
    • 如需大规模采集,建议配合 IP 代理池 使用,或者适当增加等待时间。
  4. 数据为空的问题

    • 携程有时会根据未登录状态限制数据返回数量。如果发现采集几页后数据为空,可以尝试在代码中手动模拟点击“加载更多”按钮,或者使用 cookies 维持登录态。

七、总结

本文利用 DrissionPage 的监听功能,避开了解析 HTML 的繁琐步骤,直接解析 JSON 数据,高效且稳定地实现了携程酒店数据的爬取。这种方式对于各类现代化、前后端分离的 Web 应用爬虫开发非常有借鉴意义。

完整代码已贴出,如果觉得有用,欢迎点赞、收藏、关注哦!


Logo

DAMO开发者矩阵,由阿里巴巴达摩院和中国互联网协会联合发起,致力于探讨最前沿的技术趋势与应用成果,搭建高质量的交流与分享平台,推动技术创新与产业应用链接,围绕“人工智能与新型计算”构建开放共享的开发者生态。

更多推荐