一、需求:
需要爬取携程的五四广场景点主页的用户点评信息。
二、爬虫时可能遇到的问题:
评论信息虽然可以在该页的源代码中获取到:
但是存在许多问题,例如:
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请求来解决,具体可参考我的另一篇博客:
三、编写代码:
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()
四、爬取结果: