第三步,利用上面所提到的用户代理池进行爬取。首先建立用户代理池,从用户代理池中随机选择一项,设置UA。
import urllib.request
import re
import random
#用户代理池
uapools=[
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/51.0.2704.79 Safari/537.36 Edge/14.14393",
"Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/49.0.2623.22 Safari/537.36 SE 2.X MetaSr 1.0",
"Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; Maxthon 2.0)",
]
def UA():
opener=urllib.request.build_opener()
thisua=random.choice(uapools)
ua=("User-Agent",thisua)
opener.addheaders=[ua]
urllib.request.install_opener(opener)
print("当前使用UA:"+str(thisua))
#for循环,爬取第1页到第36页的段子内容
for i in range(0,35):
UA()
#构造不同页码对应网址
thisurl="http://www.qiushibaike.com/8hr/page/"+str(i+1)+"/"
data=urllib.request.urlopen(thisurl).read().decode("utf-8","ignore")
#利用提取段子内容
pat=".*?(.*?).*?"
rst=re.compile(pat,re.S).findall(data)
for j in range(0,len(rst)):
print(rst[j])
print("-------")
还可以定时的爬取:
Import time
#然后在后面调用time.sleep()方法
换言之,学习爬虫需要灵活变通的思想,针对不同的情况,不同的约束而灵活运用。
三、抓包分析
抓包分析可以将网页中的访问细节信息取出。有时会发现直接爬网页时是无法获取到目标数据的,因为这些数据做了隐藏,此时可以使用抓包分析的手段进行分析,并获取隐藏数据。
1)Fiddler简介
抓包分析可以直接使用浏览器F12进行,也可以使用一些抓包工具进行,这里推荐Fiddler。Fiddler下载安装。假设给Fiddler配合的是火狐浏览器,打开浏览器,如下图,找到连接设置,选择手动代理设置并确定。
假设打开百度,如下图,加载的数据包信息就会在Fiddler中左侧列表中列出来,那么网站中隐藏相关的数据可以从加载的数据包中找到。
2)第二项练习-腾讯视频评论爬虫实战
目标网站:https://v.qq.com/
需要获取的数据:某部电影的评论数据,实现自动加载。
首先可以发现腾讯视频中某个视频的评论,在下面的图片中,如果点击”查看更多评论”,网页地址并无变化,与上面提到的糗事百科中的页码变化不同。而且通过查看源代码,只能看到部分评论。即评论信息是动态加载的,那么该如何爬取多页的评论数据信息?
第一步,分析腾讯视频评论网址变化规律。点击”查看更多评论”,同时打开Fiddler,第一条信息的TextView中,TextView中可以看到对应的content内容是unicode编码,刚好对应的是某条评论的内容。
解码出来可以看到对应评论内容。
将第一条信息的网址复制出来进行分析,观察其中的规律。下图是两个紧连着的不同评论的url地址,如下图,可以发现只有cursor字段发生变化,只要得到cursor,那么评论的地址就可以轻松获得。如何找到cursor值?
第二步,查找网址中变化的cursor字段值。从上面的第一条评论信息里寻找,发现恰好在last字段值与后一条评论的cursor值相同。即表示cursor的值是迭代方式生成的,每条评论的cursor信息在其上一条评论的数据包中寻找即可。
第三步,完整代码
a.腾讯视频评论爬虫:获取”深度解读”评论内容(单页评论爬虫)
#单页评论爬虫
import urllib.request
import re
#https://video.coral.qq.com/filmreviewr/c/upcomment/[视频id]?commentid=[评论id]&reqnum=[每次提取的评论的个数]
#视频id
vid="j6cgzhtkuonf6te"
#评论id
cid="6233603654052033588"
num="20"
#构造当前评论网址
url="https://video.coral.qq.com/filmreviewr/c/upcomment/"+vid+"?commentid="+cid+"&reqnum="+num
headers={"User-Agent":"Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/49.0.2623.22 Safari/537.36 SE 2.X MetaSr 1.0",
"Content-Type":"application/javascript",
}
opener=urllib.request.build_opener()
headall=[]
for key,value in headers.items():
item=(key,value)
headall.append(item)
opener.addheaders=headall
urllib.request.install_opener(opener)
#爬取当前评论页面
data=urllib.request.urlopen(url).read().decode("utf-8")
titlepat=""title":"(.*?)""
commentpat=""content":"(.*?)""
titleall=re.compile(titlepat,re.S).findall(data)
commentall=re.compile(commentpat,re.S).findall(data)
for i in range(0,len(titleall)):
try:
print("评论标题是:"+eval("u""+titleall[i]+"""))
print("评论内容是:"+eval("u""+commentall[i]+"""))
print("------")
except Exception as err:
print(err)
b.腾讯视频评论爬虫:获取”深度解读”评论内容(自动切换下一页评论的爬虫)
#自动切换下一页评论的爬虫
import urllib.request
import re
#https://video.coral.qq.com/filmreviewr/c/upcomment/[视频id]?commentid=[评论id]&reqnum=[每次提取的评论的个数]
vid="j6cgzhtkuonf6te"
cid="6233603654052033588"
num="3"
headers={"User-Agent":"Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/49.0.2623.22 Safari/537.36 SE 2.X MetaSr 1.0",
"Content-Type":"application/javascript",
}
opener=urllib.request.build_opener()
headall=[]
for key,value in headers.items():
item=(key,value)
headall.append(item)
opener.addheaders=headall
urllib.request.install_opener(opener)
#for循环,多个页面切换
for j in range(0,100):
#爬取当前评论页面
print("第"+str(j)+"页")
#构造当前评论网址thisurl="https://video.coral.qq.com/filmreviewr/c/upcomment/"+vid+"?commentid="+cid+
"&reqnum="+num
data=urllib.request.urlopen(thisurl).read().decode("utf-8")
titlepat=""title":"(.*?)","abstract":""
commentpat=""content":"(.*?)""
titleall=re.compile(titlepat,re.S).findall(data)
commentall=re.compile(commentpat,re.S).findall(data)
lastpat=""last":"(.*?)""
#获取last值,赋值给cid,进行评论id切换
cid=re.compile(lastpat,re.S).findall(data)[0]
for i in range(0,len(titleall)):
try:
print("评论标题是:"+eval("u""+titleall[i]+"""))
print("评论内容是:"+eval("u""+commentall[i]+"""))
print("------")
except Exception as err:
print(err)
四、挑战案例
1)第三项练习-中国裁判文书网爬虫实战
目标网站:http://wenshu.court.gov.cn/
需要获取的数据:2018年上海市的刑事案件接下来进入实战讲解。
第一步,观察换页之后的网页地址变化规律。打开中国裁判文书网2018年上海市刑事案件的第一页,在换页时,如下图中的地址,发现网址是完全不变的,这种情况就是属于隐藏,使用抓包分析进行爬取。
第二步,查找变化字段。从Fiddler中可以找到,获取某页的文书数据的地址:http://wenshu.court.gov.cn/Li...
可以发现没有对应的网页变换,意味着中国裁判文书网换页是通过POST进行请求,对应的变化数据不显示在网址中。通过F12查看网页代码,再换页操作之后,如下图,查看ListContent,其中有几个字段需要了解:
Param:检索条件
Index:页码
Page:每页展示案件数量
...
重要的是最后三个字段(vl5x,number,guid)该如何获取?首先,guid即uuid,叫全球唯一标识,是利用python中的uuid随机生成的字段。其次是number字段,找到ListContent上面的GetCode请求,恰好其Response中包含了number字段的值。而GetCode又是通过POST请求的,发现请求的字段只要guid这一项,那么问题便迎刃而解。
最后,难点在于vl5x字段如何获取?打开Fiddler,在换页操作后,查看ListContent中的vl5x的值,并在此次ListContent之前出现的数据包中的TextView里寻找这个字段或值,一般的网站可以很容易找到,但中国裁判文书网是政府网站,反爬策略非常高明,寻找的过程需要极高的耐心。
事实上,中国裁判文书网的vl5x字段可以从某个js包中获得,获取的方式是通过getKey()函数。从网页源代码中找到getKey()函数的js代码,由于代码是packed状态,用unpacked工具, 将其进行解码,后利用js界面美观工具可以方便理解。
但无关紧要,只需直接将getKey()函数s代码复制到unpack_js.html中,就可以解出vl5x字段的值,其中需要用到Cookie中的vjkl5字段值。需要注意提前下载好base64.js和md5.js,并在unpack_js.html加载。
第三步,以下是中国裁判文书网爬虫完整代码:
import urllib.request
import re
import http.cookiejar
import execjs
import uuid
#随机生成guid
guid=uuid.uuid4()
print("guid:"+str(guid))
fh=open("./base64.js","r")
js1=fh.read()
fh.close()
fh=open("./md5.js","r")
js2=fh.read()
fh.close()
fh=open("./getkey.js","r")
js3=fh.read()
fh.close()
#将完整js代码都加载进来
js_all=js1+js2+js3
#在生成的CookieJar添加到opner中
cjar=http.cookiejar.CookieJar()
opener = urllib.request.build_opener(urllib.request.HTTPCookieProcessor(cjar))
#Referer常用于反爬,指来源网址
opener.addheaders=[("Referer","http://wenshu.court.gov.cn/list/list/?sorttype=1&conditions=searchWord+1+AJLX++%E6%A1%88%E4%BB%B6%E7%B1%BB%E5%9E%8B:%E5%88%91%E4%BA%8B%E6%A1%88%E4%BB%B6&conditions=searchWord+2018+++%E8%A3%81%E5%88%A4%E5%B9%B4%E4%BB%BD:2018&conditions=searchWord+%E4%B8%8A%E6%B5%B7%E5%B8%82+++%E6%B3%95%E9%99%A2%E5%9C%B0%E5%9F%9F:%E4%B8%8A%E6%B5%B7%E5%B8%82")]
urllib.request.install_opener(opener)
#用户代理池
import random
uapools=[
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/51.0.2704.79 Safari/537.36 Edge/14.14393",
"Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/49.0.2623.22 Safari/537.36 SE 2.X MetaSr 1.0",
"Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; Maxthon 2.0)",
]
#访问首页
urllib.request.urlopen("http://wenshu.court.gov.cn/list/list/?sorttype=1&conditions=searchWord+1+AJLX++%E6%A1%88%E4%BB%B6%E7%B1%BB%E5%9E%8B:%E5%88%91%E4%BA%8B%E6%A1%88%E4%BB%B6&conditions=searchWord+2018+++%E8%A3%81%E5%88%A4%E5%B9%B4%E4%BB%BD:2018&conditions=searchWord+%E4%B8%8A%E6%B5%B7%E5%B8%82+++%E6%B3%95%E9%99%A2%E5%9C%B0%E5%9F%9F:%E4%B8%8A%E6%B5%B7%E5%B8%82").read().decode("utf-8","ignore")
#将Cookie中的vjkl5字段提取出来
pat="vjkl5=(.*?)s"
vjkl5=re.compile(pat,re.S).findall(str(cjar))
if(len(vjkl5)>0):
vjkl5=vjkl5[0]
else:
vjkl5=0
print("vjkl5:"+str(vjkl5))
#将js代码中的旧Cookie的值替换为新的vjkl5的值
js_all=js_all.replace("ce7c8849dffea151c0179187f85efc9751115a7b",str(vjkl5))
#使用python执行js代码,请提前安装好对应模块(在命令行中执行pip install pyexejs)
compile_js=execjs.compile(js_all)
#获得vl5x字段值
vl5x=compile_js.call("getKey")
print("vl5x:"+str(vl5x))
url="http://wenshu.court.gov.cn/List/ListContent"
#for循环,切换第1页到10页
for i in range(0,10):
try:
#从GetCode中获取number字段值
codeurl="http://wenshu.court.gov.cn/ValiCode/GetCode"
#上面提到,GetCode中,只要guid一个字段,将其获取到
codedata=urllib.parse.urlencode({
"guid":guid,
}).encode("utf-8")
codereq = urllib.request.Request(codeurl,codedata)
codereq.add_header("User-Agent",random.choice(uapools))
codedata=urllib.request.urlopen(codereq).read().decode("utf-8","ignore")
#print(codedata)
#构造请求的参数
postdata =urllib.parse.urlencode({
"Param":"案件类型:刑事案件,裁判年份:2018,法院地域:上海市",
"Index":str(i+1),
"Page":"20",
"Order":"法院层级",
"Direction":"asc",
"number":str(codedata),
"guid":guid,
"vl5x":vl5x,
}).encode("utf-8")
#直接发送POST请求
req = urllib.request.Request(url,postdata)
req.add_header("User-Agent",random.choice(uapools))
#获得ListContent中的文书ID值
data=urllib.request.urlopen(req).read().decode("utf-8","ignore")
pat="文书ID.*?".*?"(.*?).""
allid=re.compile(pat).findall(data)
print(allid)
except Exception as err:
print(err)
如此便可批量获取中国裁判文书网中的案件信息。友情提示,如果频繁爬取该网站,需扩充用户代理池。
五、推荐内容
1)常见反爬策略与反爬攻克手段介绍
数据的隐藏可以算是一种反爬策略之一,抓包分析是该反爬策略常见的反爬攻克手段。
当然,反爬还有很多手段,比如通过IP限制、UA限制、验证码限制...等等.
2)如何深入学习Python网络爬虫(深入学习路线介绍)
通过上述的介绍,相信对网络爬虫已经有了基础的了解,以及能够写出一些简单的爬虫项目。
以下项目可以提供练习:
淘宝商品图片爬虫项目
淘宝商品爬虫项目
…
3)关于Python爬虫,推荐书籍
《Python程序设计基础实战教程》 . 清华大学出版社.2018年
《精通Python网络爬虫》.机械工业出版社.2017年4月
阅读原文
文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。
转载请注明本文地址:https://www.ucloud.cn/yun/41513.html
相关文章
-
精通Python网络爬虫(0):网络爬虫学习路线
摘要:以上是如果你想精通网络爬虫的学习研究路线,按照这些步骤学习下去,可以让你的爬虫技术得到非常大的提升。 作者:韦玮 转载请注明出处 随着大数据时代的到来,人们对数据资源的需求越来越多,而爬虫是一种很好的自动采集数据的手段。 那么,如何才能精通Python网络爬虫呢?学习Python网络爬虫的路线应该如何进行呢?在此为大家具体进行介绍。 1、选择一款合适的编程语言 事实上,Python、P...
-
Python爬虫学习路线
摘要:以下这些项目,你拿来学习学习练练手。当你每个步骤都能做到很优秀的时候,你应该考虑如何组合这四个步骤,使你的爬虫达到效率最高,也就是所谓的爬虫策略问题,爬虫策略学习不是一朝一夕的事情,建议多看看一些比较优秀的爬虫的设计方案,比如说。 (一)如何学习Python 学习Python大致可以分为以下几个阶段: 1.刚上手的时候肯定是先过一遍Python最基本的知识,比如说:变量、数据结构、语法...
-
我的 Python 高效学习法
摘要:我最开始学习编程的时候也是如此,摸索了非常久的时间,才慢慢找到自己高效学习方法。被动的学习方式听讲阅读视听演示,只能让你做到内容留存率的和的知识。而主动的学习方式,如通过讨论实践教授给他人,会将原来被动学习的内容留存率从提升到和。 showImg(https://segmentfault.com/img/remote/1460000016856679); 阅读文本大概需要 7 分钟。 ...
-
爬虫 - 收藏集 - 掘金
摘要:在这之前,还是有必要对一些概念超轻量级反爬虫方案后端掘金前言爬虫和反爬虫日益成为每家公司的标配系统。 爬虫修炼之道——从网页中提取结构化数据并保存(以爬取糗百文本板块所有糗事为例) - 后端 - 掘金欢迎大家关注我的专题:爬虫修炼之道 上篇 爬虫修炼之道——编写一个爬取多页面的网络爬虫主要讲解了如何使用python编写一个可以下载多页面的爬虫,如何将相对URL转为绝对URL,如何限速,...