Python-绕过携程反爬:Selenium实战景点信息采集
2026/7/31 16:38:24 网站建设 项目流程

1. 为什么选择Selenium来爬取携程景点数据

第一次尝试用Python爬取携程景点信息时,我像大多数人一样首先想到用requests库。但很快发现携程的页面数据是通过JavaScript动态加载的,直接发送HTTP请求只能拿到空壳HTML。更麻烦的是,页面请求中有一个叫traceid的加密参数,每次都会变化,这意味着传统的抓包+参数复用的方法完全失效。

这时候你有两个选择:要么硬着头皮去逆向分析JavaScript加密逻辑,要么换个思路用浏览器自动化工具。作为一个主要用爬虫辅助数据分析的开发者,我果断选择了后者。Selenium最大的优势就是能模拟真实用户操作浏览器,完全绕过各种前端加密和动态加载的问题。实测下来,用Selenium采集携程景点信息的成功率接近100%,而代码复杂度比逆向JS低至少三个量级。

不过Selenium也不是完美方案,它的缺点很明显——速度慢、资源占用高。我的经验是:对于中小规模的数据采集(比如某个城市几百个景点),Selenium完全够用;但如果要爬全国所有景点,可能需要考虑结合requests和Selenium的混合方案。

2. 环境搭建与基础配置

2.1 安装必要的工具链

首先确保你的Python环境是3.6以上版本。然后通过pip安装以下核心依赖:

pip install selenium pandas lxml

浏览器驱动是Selenium的关键组件。以Chrome为例,需要下载与本地Chrome版本匹配的chromedriver。将下载的驱动文件放在项目目录下,或者添加到系统PATH中。这里有个小技巧:使用headless模式(无界面模式)可以大幅降低资源消耗:

from selenium.webdriver import Chrome from selenium.webdriver.chrome.options import Options options = Options() options.add_argument('--headless') # 无头模式 options.add_argument('--disable-gpu') # 避免一些兼容性问题 driver = Chrome(options=options)

2.2 处理携程的页面加载特点

携程的景点列表页有个特点:翻页时URL不会变化,传统的通过URL参数控制翻页的方法行不通。这就需要我们模拟点击"下一页"按钮的操作。另外,页面加载需要一定时间,必须合理设置等待策略:

from selenium.webdriver.common.by import By from selenium.webdriver.support.ui import WebDriverWait from selenium.webdriver.support import expected_conditions as EC # 显式等待元素加载 wait = WebDriverWait(driver, 10) next_btn = wait.until(EC.element_to_be_clickable( (By.CLASS_NAME, 'u_icon_enArrowforward'))) next_btn.click()

3. 核心爬取逻辑实现

3.1 定位并提取列表页数据

携程景点列表页的核心数据都包裹在class为"right-content-list"的div中。我们可以先获取这个容器的HTML源码,然后用正则表达式提取景点URL和名称:

content = driver.find_element_by_class_name('right-content-list').get_attribute('innerHTML') url_title_pairs = re.findall(r'href="(.*?)" title="(.*?)"', content) for url, title in url_title_pairs: full_url = 'https:' + url # 补全URL print(f'景点名称:{title}, 详情页URL:{full_url}')

3.2 自动翻页机制

由于携程采用动态加载,我们需要用while循环配合页面元素检测来实现自动翻页。这里有个关键点:必须设置合理的终止条件,否则可能陷入无限循环。我的做法是预设最大爬取页数:

max_page = 5 # 最多爬取5页 current_page = 1 while current_page <= max_page: # 提取当前页数据... try: next_btn = driver.find_element_by_class_name('u_icon_enArrowforward') next_btn.click() time.sleep(2) # 等待新页面加载 current_page += 1 except: print('已到达最后一页') break

4. 详情页数据提取技巧

4.1 处理动态变化的详情模块

景点详情页最棘手的部分是"景点介绍"、"开放时间"这些模块——它们数量不固定,但HTML结构相似。我的解决方案是用XPath提取所有标题和内容,然后通过Python的zip函数建立映射:

from lxml import etree html = driver.page_source tree = etree.HTML(html) titles = tree.xpath('//div[@class="detailModule normalModule"]//div[@class="moduleTitle"]/text()') contents = tree.xpath('//div[@class="detailModule normalModule"]//div[@class="moduleContent"]//text()') # 清理空白字符 titles = [t.strip() for t in titles if t.strip()] contents = [c.strip() for c in contents if c.strip()] # 转为字典 info_dict = dict(zip(titles, contents))

4.2 门票价格的特殊处理

门票数据往往存在三种特殊情况:价格为空、多价格并存、价格元素位置变化。这里需要多层异常处理:

prices = [] for price_element in driver.find_elements_by_xpath('//*[contains(@class, "price")]'): try: price = price_element.text.replace('¥', '').strip() if price and price.isdigit(): prices.append(int(price)) except: continue if not prices: print('未找到价格信息') else: print(f'参考价格区间:{min(prices)}-{max(prices)}元')

5. 反反爬策略实战

5.1 模拟人类操作模式

携程的反爬系统会检测异常操作。我们可以通过随机延迟和动作链来模拟人类行为:

from selenium.webdriver.common.action_chains import ActionChains import random element = driver.find_element_by_class_name('some-class') ActionChains(driver).move_to_element(element).pause( random.uniform(0.5, 2)).click().perform()

5.2 Cookie管理技巧

登录状态可以大幅降低被反爬的概率。建议先手动登录,然后导出cookie供爬虫使用:

# 获取当前所有cookie cookies = driver.get_cookies() # 将cookie转换为requests可用的格式 session = requests.Session() for cookie in cookies: session.cookies.set(cookie['name'], cookie['value'])

6. 数据存储与后续处理

6.1 结构化存储方案

建议使用Pandas将数据转为DataFrame后再存储,方便后续分析:

import pandas as pd data = { 'name': ['景点A', '景点B'], 'price': [100, 150], 'rating': [4.5, 4.2] } df = pd.DataFrame(data) # 保存为CSV df.to_csv('spots.csv', index=False, encoding='utf-8-sig') # 保存为Excel df.to_excel('spots.xlsx', index=False)

6.2 数据清洗的常见问题

实际采集的数据往往需要清洗:

  • 处理缺失值:df.fillna('N/A')
  • 统一价格单位:df['price'] = df['price'].str.replace('¥', '')
  • 去除重复项:df.drop_duplicates(inplace=True)

7. 项目优化与扩展

7.1 性能优化技巧

当需要爬取大量数据时,可以考虑:

  1. 使用Selenium Grid分布式爬取
  2. 将浏览器实例复用,避免频繁启动关闭
  3. 实现断点续爬功能
# 断点续爬示例 try: with open('progress.txt', 'r') as f: last_page = int(f.read()) except: last_page = 1

7.2 扩展其他数据维度

除了基础信息,还可以采集:

  • 用户评论(注意频率控制)
  • 季节性价格波动
  • 周边酒店关联数据

这套方法同样适用于携程的酒店、机票等板块,只需调整XPath和解析逻辑即可。最关键的是始终保持对目标网站的观察,因为旅游网站的页面结构可能随时调整。当发现爬虫失效时,第一时间检查元素定位是否仍然有效,而不是盲目修改代码。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询