Python爬虫时翻页等操作URL不会改变的解决办法--以爬取携程景点点评信息为例

本文详细介绍了一种针对携程网站上景点评论信息的爬虫实现方法。面对动态加载的评论数据,文章深入分析了如何利用Python模拟HTTP请求,自动抓取指定页面的评论内容,并通过解析网页源代码获取必要的POST参数。最终,成功实现了对评论信息的批量爬取和存储。

一、需求:

      需要爬取携程的五四广场景点主页的用户点评信息。

二、爬虫时可能遇到的问题:

评论信息虽然可以在该页的源代码中获取到:

但是存在许多问题,例如:

1、评论翻页、修改评论排序方式(智能排序、有用数排序、按时间排序)并不会改变当前页的URL。

2、使用Fiddler等的抓包工具,虽然能够找到该网页用来进行评论数据传输的文件AsynCommentView的URL,但是发现翻页以及修改评论排序方式同样不会改变URL。

3、得出结论,评论信息是“动态加载的”。

三、问题分析:

1、观察景点页面的源代码,注意到关键代码:

        这行代码直接说明了,该网页的评论信息是通过POST服务的形式,向评论数据传输文件AsynCommentView的URL发送POST请求,然后获取返回的评论数据。

2、通过Chrome内核浏览器的F12工具,切换到network查看一下传输的内容,首先清空内容避免干扰,然后点击翻页或者切换排序方式,切换到Headers我们可以看到:

     发送的请求信息无处遁形~

4、那么问题来了,请求的内容参数该如何设置呢?

(1)order以及pagenow:顾名思义,是排序方式(按时间:1 ,有用数:2,智能:3)以及当前页码。

(2)star、tourist:测试发现使用0.0即可。

(3)poiID、districtId、districtEName、resourceId、resourcetype:无法轻易判断,但是通过观察网页源代码:

    发现源代码帮了大忙,他会把默认的参数储存,可以通过爬取这些参数来进行填充。

3、因此可以初步思考爬虫的解决思路:即使用自动模拟HTTP请求来解决,具体可参考我的另一篇博客:

        Python数据爬虫学习笔记(5)自动模拟HTTP请求

三、编写代码:

import re
import urllib.request
import urllib.parse

#模拟浏览器
headers=("User-Agent","Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.26 Safari/537.36 Core/1.63.6726.400 QQBrowser/10.2.2265.400")
opener=urllib.request.build_opener()
opener.addheaders=[headers]
urllib.request.install_opener(opener)

#设置URL为当前景点页面并获取内容
baseUrl="http://you.ctrip.com/sight/Qingdao5/5326.html#ctm_ref=www_hp_bs_lst"
pagedata=urllib.request.urlopen(baseUrl).read().decode("utf-8","ignore")

#爬取页面中的POST参数信息并进行处理
poiIDPat='var poiid = "(.*?)"'
districtIdPat='var districtid = "(.*?)"'
districtENamePat='var districtename = "(.*?)"'
resourceIdPat='var resourceid = "(.*?)"'
resourcetypePat='var resourcetype = "(.*?)"'

poiID=int(re.compile(poiIDPat,re.S).findall(pagedata)[0])
districtId=int(re.compile(districtIdPat,re.S).findall(pagedata)[0])
districtEName=re.compile(districtENamePat,re.S).findall(pagedata)[0]
resourceId=int(re.compile(resourceIdPat,re.S).findall(pagedata)[0])
resourcetype=int(re.compile(resourcetypePat,re.S).findall(pagedata)[0])
order=1 #排序方式,此处设置为按时间排序
star=0.0
tourist=0.0

#设定数据传输文件的URL,当Post网址无法轻易找到时,可以使用抓包分析
url="http://you.ctrip.com/destinationsite/TTDSecond/SharedView/AsynCommentView"
comments=[]#存储所有评论的列表
#以爬取评论前30页为例
for i in range(1,31):
    #设定Post的值
    mydata=urllib.parse.urlencode({
        "poiID":poiID,
        "districtId":districtId,
        "districtEName":districtEName,
        "pagenow":i,
        "order":order,
        "star":star,
        "tourist":tourist,
        "resourceId":resourceId,
        "resourcetype":resourcetype
    }).encode("utf-8")
    #发送POST请求进行爬取
    req=urllib.request.Request(url,mydata)
    commentdata=urllib.request.urlopen(req).read().decode("utf-8","ignore")
    commentPat='<span class="heightbox">(.*?)</span>'
    #获得当前页评论并存储
    comment=re.compile(commentPat,re.S).findall(pagedata)
    comments.extend(comment)
    
#写入txt文件
file_handle=open('E:/comment.txt',mode='w')
for j in range(0,len(comments)):
    text = "评论内容:"+comments[j] + '\n\n'  
    file_handle.write(text)
file_handle.close()

四、爬取结果:

<think>好的,我现在要解决用户的问题:如何在爬虫中处理URL不变的情况下实现翻页。根据用户提供的引用资料,我需要综合这些信息并给出技术方案。 首先,用户提到的引用[2]和[3]都指出,翻页URL不变的网站通常使用AJAX动态加载技术。这意味着页面内容是通过JavaScript异步请求获取的,而不是通过传统的URL跳转。因此,直接修改URL参数可能无法获取到其他页面的数据。 接下来,我需要考虑不同的技术方案。引用[3]提到,可以通过分析网络请求来找到翻页的API接口。如,使用浏览器的开发者工具(F12)查看XHR或Fetch请求,找到分页请求的规律。如,可能有一个POST或GET请求,参数中包含页码或偏移量。这样,即使URL不变,也可以通过模拟这些请求来获取不同页面的数据。 另一个方法是使用Selenium等自动化工具,如引用[4]所述。Selenium可以模拟用户操作,比如点击翻页按钮,然后等待页面加载完成后再抓取数据。这种方法适用于那些无法通过简单请求获取数据的网站,但效率可能较低,且需要处理页面元素的定位和可能的等待间。 此外,引用[2]提到AJAX动态加载,可能需要分析JavaScript生成的请求参数,比如间戳、token等,这些参数可能需要在爬虫中动态生成,以构造有效的请求。如,某些网站可能使用POST请求,参数包括当前页码和每页显示数量,如引用[3]中的子:`page=2&size=10`。 还需要注意反爬机制,比如检查请求头中的Referer、User-Agent,或者使用Cookie验证。在模拟请求,需要确保这些参数与实际浏览器发送的一致,否则可能被服务器拒绝。 最后,用户可能需要处理分页结束的条件,比如当返回的数据为空或达到预设的最大页数停止爬取。这需要根据具体网站的响应来判断,如检查返回的JSON数据中是否有`hasNextPage`字段,或者观察数据条数是否减少。 总结起来,主要技术方案有三种:分析API请求并模拟、使用自动化工具控制浏览器、逆向工程JavaScript参数。需要根据网站的具体实现选择合适的方法,并处理可能的反爬措施。</think>### 爬虫处理翻页URL不变的解决方案 #### 1. **分析动态请求接口** - **原理**:通过浏览器开发者工具(F12)的Network面板,筛选XHR/Fetch请求,观察翻页触发的API请求规律[^3]。 - **步骤**: 1. 翻页记录请求的URL、请求方法(GET/POST)、Headers(如User-Agent、Cookie)和参数(如`page=2&size=10`)。 2. 在代码中模拟相同请求,动态修改页码参数。 - **示代码**: ```python import requests headers = { "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36..." } for page in range(1, 6): params = {"page": page, "size": 20} response = requests.post("https://example.com/api/data", headers=headers, data=params) print(response.json()) ``` #### 2. **使用自动化工具(如Selenium)** - **适用场景**:适用于无法直接获取API接口或参数加密复杂的网站[^4]。 - **步骤**: 1. 使用Selenium驱动浏览器(如Chrome)模拟点击翻页按钮。 2. 通过`WebDriverWait`等待新内容加载完成。 - **示代码**: ```python 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 driver = webdriver.Chrome() driver.get("https://example.com") for _ in range(5): # 翻5页 next_button = WebDriverWait(driver, 10).until( EC.element_to_be_clickable((By.CSS_SELECTOR, ".next-page-button")) ) next_button.click() WebDriverWait(driver, 10).until(EC.presence_of_element_located((By.CLASS_NAME, "data-item"))) # 抓取当前页数据... driver.quit() ``` #### 3. **逆向工程JavaScript参数** - **原理**:某些网站会在请求中携带动态生成的参数(如间戳、加密Token),需通过解析JavaScript代码还原生成逻辑[^2]。 - **工具**:使用PyExecJS库执行JavaScript代码生成参数。 - **示**: ```python import execjs with open("encrypt.js", "r") as f: js_code = f.read() ctx = execjs.compile(js_code) token = ctx.call("generateToken", "page=2") ``` #### 4. **分页终止条件** - 当API返回空数据或状态码异常停止。 - 通过页面元素判断是否存在“下一页”按钮。 --- ###
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值