Python+Selenium自动化爬取携程动态加载游记

1. 引言

在旅游行业数据分析、舆情监测或竞品研究中,获取携程等平台的游记数据具有重要价值。然而,携程的游记页面通常采用动态加载(Ajax、JavaScript渲染),传统的**<font style="color:rgb(64, 64, 64);background-color:rgb(236, 236, 236);">Requests</font>**+**<font style="color:rgb(64, 64, 64);background-color:rgb(236, 236, 236);">BeautifulSoup</font>**方案难以直接获取完整数据。

解决方案:使用**<font style="color:rgb(64, 64, 64);background-color:rgb(236, 236, 236);">Selenium</font>**模拟浏览器行为,配合**<font style="color:rgb(64, 64, 64);background-color:rgb(236, 236, 236);">BeautifulSoup</font>****<font style="color:rgb(64, 64, 64);background-color:rgb(236, 236, 236);">lxml</font>**解析动态加载的游记内容。本文将详细介绍如何利用**<font style="color:rgb(64, 64, 64);background-color:rgb(236, 236, 236);">Python+Selenium</font>**爬取携程动态加载的游记,并存储至**<font style="color:rgb(64, 64, 64);background-color:rgb(236, 236, 236);">CSV</font>**文件。

2. 技术选型与工具准备

2.1 技术栈

  • Python 3.8+(推荐使用最新稳定版)
  • Selenium(浏览器自动化工具)
  • BeautifulSoup4(HTML解析库)
  • Pandas(数据存储与处理)
  • ChromeDriver(与Chrome浏览器配合使用)

2.2 环境安装

2.3 下载浏览器驱动

  • ChromeDriver:下载地址(需与本地Chrome版本匹配)
  • GeckoDriver(Firefox):下载地址

3. 爬取携程动态加载游记的步骤

3.1 分析携程游记页面结构

目标URL示例(以“北京”为例):

https://you.ctrip.com/travels/beijing1/t3.html

关键观察点

  1. 动态加载:游记列表通过滚动或点击“加载更多”动态获取。
  2. Ajax请求:可通过浏览器开发者工具(F12→Network→XHR)查看数据接口。
  3. 反爬机制
    • User-Agent检测
    • IP限制(需代理或控制请求频率)
    • 登录验证(部分内容需登录)

3.2 Selenium 模拟浏览器操作

from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
import time
import pandas as pd
from bs4 import BeautifulSoup# 配置ChromeDriver路径
driver_path = "chromedriver.exe"  # 替换为你的驱动路径
options = webdriver.ChromeOptions()
options.add_argument("--headless")  # 无头模式(可选)
options.add_argument("--disable-gpu")
options.add_argument("user-agent=Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36")driver = webdriver.Chrome(executable_path=driver_path, options=options)

3.3 访问目标页面并滚动加载数据

def scroll_to_bottom(driver, max_scroll=5):"""模拟滚动加载"""for _ in range(max_scroll):driver.execute_script("window.scrollTo(0, document.body.scrollHeight);")time.sleep(2)  # 等待数据加载url = "https://you.ctrip.com/travels/beijing1/t3.html"
driver.get(url)
scroll_to_bottom(driver)  # 滚动加载更多游记

3.4 解析游记数据

def parse_travel_notes(driver):soup = BeautifulSoup(driver.page_source, 'html.parser')notes = soup.find_all('div', class_='journalslist')  # 游记列表容器data = []for note in notes:title = note.find('a', class_='journal-title').get_text(strip=True)author = note.find('a', class_='nickname').get_text(strip=True)date = note.find('span', class_='time').get_text(strip=True)views = note.find('span', class_='num').get_text(strip=True)content = note.find('p', class_='journal-content').get_text(strip=True)data.append({"标题": title,"作者": author,"发布时间": date,"阅读量": views,"内容摘要": content})return datatravel_data = parse_travel_notes(driver)

3.5 存储数据至CSV

df = pd.DataFrame(travel_data)
df.to_csv("ctrip_travel_notes.csv", index=False, encoding="utf_8_sig")  # 避免中文乱码

4. 完整代码实现

from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from bs4 import BeautifulSoup
import pandas as pd
import time
from selenium.webdriver.chrome.options import Optionsdef scroll_to_bottom(driver, max_scroll=5):"""模拟滚动加载"""for _ in range(max_scroll):driver.execute_script("window.scrollTo(0, document.body.scrollHeight);")time.sleep(2)def parse_travel_notes(driver):"""解析游记数据"""soup = BeautifulSoup(driver.page_source, 'html.parser')notes = soup.find_all('div', class_='journalslist')data = []for note in notes:title = note.find('a', class_='journal-title').get_text(strip=True)author = note.find('a', class_='nickname').get_text(strip=True)date = note.find('span', class_='time').get_text(strip=True)views = note.find('span', class_='num').get_text(strip=True)content = note.find('p', class_='journal-content').get_text(strip=True)data.append({"标题": title,"作者": author,"发布时间": date,"阅读量": views,"内容摘要": content})return datadef main():# 代理配置proxyHost = "www.16yun.cn"proxyPort = "5445"proxyUser = "16QMSOML"proxyPass = "280651"# 初始化浏览器配置options = Options()# 设置User-Agentoptions.add_argument("user-agent=Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36")# 设置代理(带认证)proxy_options = {'proxy': {'http': f'http://{proxyUser}:{proxyPass}@{proxyHost}:{proxyPort}','https': f'https://{proxyUser}:{proxyPass}@{proxyHost}:{proxyPort}','no_proxy': 'localhost,127.0.0.1'}}# 添加代理扩展(适用于需要认证的代理)from selenium.webdriver.chrome.service import Servicefrom selenium.webdriver.common.proxy import Proxy, ProxyType# 方法1:使用ChromeOptions添加代理(基础方法,可能不支持认证)# options.add_argument(f'--proxy-server=http://{proxyUser}:{proxyPass}@{proxyHost}:{proxyPort}')# 方法2:使用插件方式添加认证代理(推荐)# 需要先创建一个代理认证插件manifest_json = """{"version": "1.0.0","manifest_version": 2,"name": "Chrome Proxy","permissions": ["proxy","tabs","unlimitedStorage","storage","<all_urls>","webRequest","webRequestBlocking"],"background": {"scripts": ["background.js"]},"minimum_chrome_version":"22.0.0"}"""background_js = """var config = {mode: "fixed_servers",rules: {singleProxy: {scheme: "http",host: "%s",port: parseInt(%s)},bypassList: ["localhost"]}};chrome.proxy.settings.set({value: config, scope: "regular"}, function() {});function callbackFn(details) {return {authCredentials: {username: "%s",password: "%s"}};}chrome.webRequest.onAuthRequired.addListener(callbackFn,{urls: ["<all_urls>"]},['blocking']);""" % (proxyHost, proxyPort, proxyUser, proxyPass)# 创建临时插件目录import osimport tempfileimport zipfileplugin_dir = tempfile.mkdtemp()with open(os.path.join(plugin_dir, "manifest.json"), 'w') as f:f.write(manifest_json)with open(os.path.join(plugin_dir, "background.js"), 'w') as f:f.write(background_js)# 打包插件proxy_plugin_path = os.path.join(plugin_dir, "proxy_auth_plugin.zip")with zipfile.ZipFile(proxy_plugin_path, 'w') as zp:zp.write(os.path.join(plugin_dir, "manifest.json"), "manifest.json")zp.write(os.path.join(plugin_dir, "background.js"), "background.js")# 添加插件到ChromeOptionsoptions.add_extension(proxy_plugin_path)try:# 初始化浏览器(带代理)driver = webdriver.Chrome(executable_path="chromedriver.exe", options=options)# 访问页面并滚动加载url = "https://you.ctrip.com/travels/beijing1/t3.html"driver.get(url)scroll_to_bottom(driver)# 解析数据travel_data = parse_travel_notes(driver)# 存储数据df = pd.DataFrame(travel_data)df.to_csv("ctrip_travel_notes.csv", index=False, encoding="utf_8_sig")print("数据爬取完成,已保存至 ctrip_travel_notes.csv")finally:driver.quit()# 清理临时插件文件import shutilshutil.rmtree(plugin_dir)if __name__ == "__main__":main()

5. 进阶优化

5.1 反反爬策略

  • 随机User-Agent:使用**<font style="color:rgb(64, 64, 64);background-color:rgb(236, 236, 236);">fake_useragent</font>**库动态切换UA。
  • IP代理池:结合**<font style="color:rgb(64, 64, 64);background-color:rgb(236, 236, 236);">requests</font>**+**<font style="color:rgb(64, 64, 64);background-color:rgb(236, 236, 236);">proxies</font>**绕过IP限制。
  • 模拟登录:处理需要登录才能查看的游记。

5.2 数据增强

  • 情感分析:使用**<font style="color:rgb(64, 64, 64);background-color:rgb(236, 236, 236);">SnowNLP</font>****<font style="color:rgb(64, 64, 64);background-color:rgb(236, 236, 236);">TextBlob</font>**分析游记情感倾向。
  • 关键词提取:利用**<font style="color:rgb(64, 64, 64);background-color:rgb(236, 236, 236);">jieba</font>**分词提取热门景点关键词。

5.3 分布式爬虫

  • Scrapy+Redis:提升爬取效率。
  • 多线程/异步爬取:使用**<font style="color:rgb(64, 64, 64);background-color:rgb(236, 236, 236);">asyncio</font>****<font style="color:rgb(64, 64, 64);background-color:rgb(236, 236, 236);">aiohttp</font>**优化请求速度。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/pingmian/89563.shtml
繁体地址,请注明出处:http://hk.pswp.cn/pingmian/89563.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

ESP8266服务器建立TCP连接失败AT+CIPSTART=“TCP“,“192.168.124.1“,8080 ERROR CLOSED

1.检查服务器端口8081是否开启监听2.检查路由项是否被防火墙拦截方法 1&#xff1a;使用 netsh查看防火墙规则​netsh advfirewall firewall show rule nameall dirout | findstr "8081"如果无输出&#xff0c;说明防火墙未针对该端口设置规则&#xff08;可能默认拦…

Linux 内存管理(2):了解内存回收机制

目录一、透明大页1.1 原理1.2 透明大页的三大优势1.3 透明大页控制接口详解1.4 使用场景与最佳实践1.5 问题排查与监控1.6 与传统大页的对比二、Linux伙伴系统水位机制详解2.1 三种核心水位详解2.2 水位在伙伴系统中的实现2.3 水位触发机制的实际行为2.4 水位关键操作接口2.5 水…

前端学习7:CSS过渡与动画--补间动画 (Transition) vs 关键帧动画 (Animation)

一、补间动画&#xff08;Tween Animation&#xff09;vs 关键帧动画&#xff08;Keyframe Animation&#xff09;概念对比表&#xff1a;补间动画 (Transition)关键帧动画 (Animation)定义元素从初始状态到结束状态的过渡效果通过定义多个关键帧控制动画的中间状态触发方式需要…

PyTorch 损失函数详解:从理论到实践

目录 一、损失函数的基本概念 二、常用损失函数及实现 1. 均方误差损失&#xff08;MSELoss&#xff09; 2. 平均绝对误差损失&#xff08;L1Loss/MAELoss&#xff09; 3. 交叉熵损失&#xff08;CrossEntropyLoss&#xff09; 4. 二元交叉熵损失&#xff08;BCELoss&…

MinIO深度解析:从核心特性到Spring Boot实战集成

在当今数据爆炸的时代&#xff0c;海量非结构化数据的存储与管理成为企业级应用的关键挑战。传统文件系统在TB级数据面前捉襟见肘&#xff0c;而昂贵的云存储服务又让中小企业望而却步。MinIO作为一款开源高性能对象存储解决方案&#xff0c;正以其独特的技术优势成为开发者的首…

腾讯云服务上下载docker以及使用Rabbitmq的流程

执行以下命令&#xff0c;添加 Docker 软件源并配置为腾讯云源。sudo yum-config-manager --add-repohttps://mirrors.cloud.tencent.com/docker-ce/linux/centos/docker-ce.repo sudo sed -i "s/download.docker.com/mirrors.tencentyun.com\/docker-ce/g" /etc/yu…

UE5 一些关于过场动画sequencer,轨道track的一些Python操作

删除多余的轨道 import unreal def execute():movie_scene_actors []sequence_assets []data 0.0# 获取编辑器实用工具库lib unreal.EditorUtilityLibrary()selected_assets lib.get_selected_assets()for asset in selected_assets:if asset.get_class() unreal.LevelS…

前端性能优化“核武器”:新一代图片格式(AVIF/WebP)与自动化优化流程实战

前端性能优化“核武器”&#xff1a;新一代图片格式(AVIF/WebP)与自动化优化流程实战 当你的页面加载时间超过3秒时&#xff0c;用户的跳出率会飙升到40%以上。而在所有的前端性能优化手段中&#xff0c;图片优化无疑是投入产出比最高的一环。一张未经优化的巨大图片&#xff0…

单元测试学习+AI辅助单测

标题单元测试衡量指标具体测试1、Resource2、MockBean3、Test4、Test模板5、单测示例H2数据库JSON1、使用方式AI辅助单测使用方法单元测试 单元测试一般指程序员在写好代码后&#xff0c;提交测试前&#xff0c;需要验证自己的代码是否可以正常工作&#xff0c;同时将自己的代…

Spring Cloud Gateway与Envoy Sidecar在微服务请求路由中的架构设计分享

Spring Cloud Gateway与Envoy Sidecar在微服务请求路由中的架构设计分享 在现代微服务架构中&#xff0c;请求路由层承担着流量分发、安全鉴权、流量控制等多重职责。传统的单一网关方案往往面临可扩展性和可维护性挑战。本文将从真实生产环境出发&#xff0c;分享如何结合Spri…

GitHub Pages+Jekyll 静态网站搭建(二)

GitHub PagesJekyll 静态网站搭建&#xff08;二&#xff09;GitHub PagesJekyll 静态网站搭建&#xff08;二内容简介搭建模板网站部署工作流程GitHub PagesJekyll 静态网站搭建&#xff08;二 内容简介 &#x1f6a9; Tech Contents 该文主要涉及Jekyll主题的下载与使用。Gi…

Django 实战:I18N 国际化与本地化配置、翻译与切换一步到位

文章目录一、国际化与本地化介绍定义相关概念二、安装配置安装 gettext配置 settings.py三、使用国际化视图中使用序列化器和模型中使用四、本地化操作创建或更新消息文件消息文件说明编译消息文件五、项目实战一、国际化与本地化介绍 定义 国际化和本地化的目标&#xff0c;…

通过国内扣子(Coze)搭建智能体并接入discord机器人

国内的扣子是无法直接授权给discord的&#xff0c;但是用国外的coze的话&#xff0c;大模型调用太贵&#xff0c;如果想要接入国外的平台&#xff0c;那就需要通过调用API来实现。 1.搭建智能体&#xff08;以工作流模式为例&#xff09; 首先&#xff0c;我们需要在扣子平台…

【办公类-107-02】20250719视频MP4转gif(削减MB)

背景需求 最近在写第五届智慧项目结题(一共3篇)写的昏天黑地,日以继夜。 我自己《基于“AI技术”的幼儿园教学资源开发和运用》提到了AI绘画、AI视频和AI编程。 为了更好的展示AI编程的状态,我在WORD里面插入了MP4转gif的动图。 【教学类-75-04】20241023世界名画-《蒙…

一文讲清楚React的render优化,包括shouldComponentUpdate、PureComponent和memo

文章目录一文讲清楚React的render优化&#xff0c;包括shouldComponentUpdate、PureComponent和memo1. React的渲染render机制2. shouldComponentUpdate2.1 先上单组件渲染&#xff0c;验证state变化2.2 上父子组件&#xff0c;验证props2. PureComponent2.1 单组件验证state2.…

物联网iot、mqtt协议与华为云平台的综合实践(万字0基础保姆级教程)

本学期的物联网技术与应用课程&#xff0c;其结课设计内容包含&#xff1a;mqtt、华为云、PyQT5和MySQL等结合使用&#xff0c;完成了从华为云配置产品信息以及转发规则&#xff0c;到mqtt命令转发&#xff0c;再到python编写逻辑代码实现相关功能&#xff0c;最后用PyQT5实现面…

使用IntelliJ IDEA和Maven搭建SpringBoot集成Fastjson项目

使用IntelliJ IDEA和Maven搭建SpringBoot集成Fastjson项目 下面我将详细介绍如何在IntelliJ IDEA中使用Maven搭建一个集成Fastjson的SpringBoot项目&#xff0c;包含完整的环境配置和代码实现。 一、环境准备 软件要求 IntelliJ IDEA 2021.x或更高版本JDK 1.8或更高版本&#x…

Java从入门到精通!第九天, 重点!(集合(一))

十一、集合1. 为什么要使用集合(1) 数组存在的弊端1) 数组在初始化之后&#xff0c;长度就不能改变&#xff0c;不方便扩展。2) 数组中提供的属性和方法比较少&#xff0c;不便于进行添加、删除、修改等操作&#xff0c;并且效率不高&#xff0c;同时无法直接存储元素的个数。3…

为什么使用时序数据库

为什么使用时序数据库&#xff1f; 时序数据库&#xff08;Time-Series Database, TSDB&#xff09;是专为时间序列数据优化的数据库&#xff0c;相比传统关系型数据库&#xff08;如MySQL&#xff09;或NoSQL数据库&#xff08;如MongoDB&#xff09;&#xff0c;它在以下方面…

计算机网络:(十一)多协议标记交换 MPLS

计算机网络&#xff1a;&#xff08;十一&#xff09;多协议标记交换 MPLS前言一、传统网络的问题二、MPLS&#xff1a;给数据包贴个“标签”三、MPLS的工作流程1. 入站2. 中间3. 出站四、MPLS的能力前言 前面我们讲解了计算机网络中网络层的相关知识&#xff0c;包括网络层转发…