【python爬虫】6.爬虫实操(带参数请求数据)

文章目录

  • 前言
  • 项目:狂热粉丝
  • 分析过程
    • 什么是带参数请求数据
    • 如何带参数请求数据
  • 代码实现
  • 被隐藏的歌曲清单
    • 什么是Request Headers
    • 如何添加Request Headers
  • 复习

前言

先来复习一下上一关的主要知识吧,先热个身。

Network能够记录浏览器的所有请求。我们最常用的是:ALL(查看全部)/XHR(仅查看XHR)/Doc(Document,第0个请求一般在这里),有时候也会看看:Img(仅查看图片)/Media(仅查看媒体文件)/Other(其他)。最后,JS和CSS,则是前端代码,负责发起请求和页面实现;Font是文字的字体;而理解WS和Manifest,需要网络编程的知识,倘若不是专门做这个,你不需要了解。

在这里插入图片描述
在Network,有非常重要的一类请求是XHR(或Fetch),因为有它的存在,人们不必刷新/跳转网页,即可加载新的内容。随着技术发展,XHR的应用频率越来越高,我们常常需要在这里找我们想要的数据。

XHR的功能是传输数据,其中有非常重要的一种数据是用json格式写成的,和html一样,这种数据能够有组织地存储大量内容。json的数据类型是“文本”,在Python语言当中,我们把它称为字符串。我们能够非常轻易地将json格式的数据转化为列表/字典,也能将列表/字典转为json格式的数据。

如何解析json数据?答案如下:

在这里插入图片描述
总之,在上一关,我们最后把代码写成这副模样:

import requests
# 引用requests模块
res_music = requests.get('https://c.y.qq.com/soso/fcgi-bin/client_search_cp?ct=24&qqmusic_ver=1298&new_json=1&remoteplace=txt.yqq.song&searchid=60997426243444153&t=0&aggr=1&cr=1&catZhida=1&lossless=0&flag_qc=0&p=1&n=20&w=%E5%91%A8%E6%9D%B0%E4%BC%A6&g_tk=5381&loginUin=0&hostUin=0&format=json&inCharset=utf8&outCharset=utf-8&notice=0&platform=yqq.json&needNewCode=0')
# 调用get方法,下载这个字典
json_music = res_music.json()
# 使用json()方法,将response对象,转为列表/字典
list_music = json_music['data']['song']['list']
# 一层一层地取字典,获取歌单列表
for music in list_music:
# list_music是一个列表,music是它里面的元素print(music['name'])# 以name为键,查找歌曲名print('所属专辑:'+music['album']['name'])# 查找专辑名print('播放时长:'+str(music['interval'])+'秒')# 查找播放时长print('播放链接:https://y.qq.com/n/yqq/song/'+music['mid']+'.html\n\n')# 查找播放链接

项目:狂热粉丝

我们接着上一关说,如果仅仅只是拿到20首歌曲的相关信息,实际上并不能让一个狂热的粉丝感到喜悦。他会在心里呐喊:“我,全都要!”

那就全都给他吧!在这一关,我们要完成的项目是:让上一关的代码得到进化,使它能爬取很多很多歌曲,而不只是爬取20个。

但是,在这之前,我们会以歌曲《七里香》作为案例,去爬取它的歌曲评论:

在这里插入图片描述
在Get到“爬取《七里香》评论”的技能后,我们会再回到爬取更多歌曲的项目当中。就好像你在玩游戏时,会先到新手村杀小怪涨经验再出村解锁新地图一样,爬取评论就是我们用来练手的“新手村”。

当然了,如果你开心,我们还可以把“爬取歌词”作为本关卡的练习。

在这个过程当中,我们会学到带参数请求数据的知识,以及关于Request Headers的知识。此刻你或许还不清楚我在说什么,没关系,答案很快会揭晓。

分析过程

你可能会疑惑,为什么不能直接爬取周杰伦的更多歌曲,来吧,先来打开偶像的qq音乐搜索链接:

https://y.qq.com/portal/search.html#page=1&searchid=1&remoteplace=txt.yqq.top&t=song&w=%E5%91%A8%E6%9D%B0%E4%BC%A6

如果仔细观察页面的内容,你可能会摇摇头,认为爬取更多的歌曲信息是一个不可能完成的任务,因为如今的qq音乐已经不支持更多歌曲的翻阅功能,正常访问的途径都没有了,我们的“虫”(代码)上哪爬取去?

在这里插入图片描述
退而求其次,咱们来看看评论这边的情况,目前qq音乐的评论页面结构是这样的:

在这里插入图片描述
评论区分成了两部分,分别是精彩评论和最新评论,精彩评论可以通过点击加载更多获得更多数据,最新评论则需要翻页来进行数据更新。

也就是说,爬取更多的评论数据的难点似乎在翻页和点击加载更多。

显然这种数据的加载模式还是我们上一关熟悉的“动态加载”,即点击一个按钮(加载更多或者第n页),服务器就会根据新的XHR更新页面信息。

这样一来,若我们想要获得更多的评论数据,就需要:1️⃣点击按钮获得新的XHR 2️⃣根据新的XHR获得json数据 3️⃣解析json数据,如此循环往复,直至精神崩溃。

如果python有情绪,它的脸上现在肯定写满了嫌弃和拒绝。所以,看在python的面上,只要我们能找到每个请求之间的规律,这种重复的工作就交给它了好吗?

相比较爬取我们“看不见”(更多歌曲信息)的数据,评论这个能通过点击页码或加载更多按钮看到更多数据的“柿子”看起来比较软一点,就先捏它吧~

不过,解决评论的问题,需要用到“带参数请求数据”。学会这个,所有的问题都不再是问题。

什么是带参数请求数据

我不知道你有没有认真地观察过一个完整url的组成,如果没有,我们现在来试试看:

当你在豆瓣搜索“海边的卡夫卡”,它的网址会是这样:

https://www.douban.com/search?q=%E6%B5%B7%E8%BE%B9%E7%9A%84%E5%8D%A1%E5%A4%AB%E5%8D%A1

当你在知乎搜索“宇宙大爆炸”,它的网址会是这样:

https://www.zhihu.com/search?type=content&q=%E5%AE%87%E5%AE%99%E5%A4%A7%E7%88%86%E7%82%B8

现在,我要揭晓规律:

在上面,我们能看到每个url都由两部分组成。前半部分大多形如:https://xx.xx.xxx/xxx/xxx

后半部分,多形如:xx=xx&xx=xxx&xxxxx=xx&……

两部分使用?来连接。举例刚刚的豆瓣网址,前半部分就是:

icon
https://www.douban.com/search

icon
后半部分则是:q=%E6%B5%B7%E8%BE%B9%E7%9A%84%E5%8D%A1%E5%A4%AB%E5%8D%A1

它们的中间使用了?来隔开。

这前半部分是我们所请求的地址,它告诉服务器,我想访问这里。而后半部分,就是我们的请求所附带的参数,它会告诉服务器,我们想要什么样的数据。

这参数的结构,会和字典很像,有键有值,键值用=连接;每组键值之间,使用&来连接。

就像豆瓣。我们请求的地址是https://www.douban.com/search

而我们的请求所附带的参数是“海边的卡夫卡”:q=%E6%B5%B7%E8%BE%B9%E7%9A%84%E5%8D%A1%E5%A4%AB%E5%8D%A1(那段你看不懂的代码,它是“海边的卡夫卡”使用utf-8编码的结果)。

技能点学满了吧?那现在,我们要以《七里香》为例,爬取用户的精彩评论。

首先,进入网址:

https://y.qq.com/n/yqq/song/004Z8Ihr0JIu5s.html

打开Network,选中All,点击刷新。

在这里插入图片描述
上一关我们说到,第0个请求一般都会是html。我们点开第0个请求来看看(看Preview或Response都可以),看里面有没有我们想要的评论信息。

显然是没有的。我们现在去看XHR。

在这里插入图片描述
这次的XHR还挺多,有四五十个。常规来说我们有两种方法来寻找XHR:阅读它们的name看看哪个可能是评论;或者是一个一个翻。

现在再给你介绍一个简单的小技巧:先把Network面板清空,再点击一下精彩评论的点击加载更多,看看有没有多出来的新XHR,多出来的那一个,就应该是和评论相关的啦。

在这里插入图片描述

总结这个技巧,就是:

在这里插入图片描述
我们点开这个请求的Preview,能够在[‘comment’][‘commentlist’]里找到评论列表。列表的每一个元素都是字典,字典里键rootcommentcontent对应的值,就是我们要找的评论。

在这里插入图片描述

好嘞,于是我们就在找到拥有评论数据的页面链接(请求的Headers栏:General中的Request URL):

https://c.y.qq.com/base/fcgi-bin/fcg_global_comment_h5.fcg?g_tk=5381&loginUin=0&hostUin=0&format=json&inCharset=utf8&outCharset=GB2312&notice=0&platform=yqq.json&needNewCode=0&cid=205360772&reqtype=2&biztype=1&topid=102065756&cmd=6&needmusiccrit=0&pagenum=1&pagesize=15&lasthotcommentid=song_102065756_3202544866_44059185&domain=qq.com&ct=24&cv=10101010

显然,这样一个长链接,阅读体验非常之差。Network面板提供了一个更友好的查看方式,我来带你看看它。

回到上面我们找到XHR的地方,选中Headers,保持General打开,保持Response Headers和Request Headers关闭。我们点开Query String Parameters。

在这里插入图片描述
它里面的内容有没有感觉眼熟?正是链接请求中所附带的参数,对吧!Query String Parameters,它的中文翻译是:查询字符串参数。

这个面板用类似字典的形式,呈现了各个参数的键值,阅读体验会好一些。我们可以常来此处看看。

如何带参数请求数据

在上一关当中,我们直接用requests.get()请求了url。在这一关,如果我们想拿到更多精彩评论。就要读懂url的各个参数。修改它们,重新发起请求。

读懂参数,有两个重要的方法是“观察”和“比较”。“观察”指的是阅读参数的键与值,尝试理解它的含义。“比较”指的是比较两个相近的XHR——它们有哪些不同,对应的页面显示内容有什么不同。

现在,我们来观察比较,依然在“七里香”的歌曲详情页,点击精彩评论的点击加载更多按钮,此时Network会多加载出更多的XHR,但是Name为fcg_global_comment_h5…才是我们关心的XHR。

在这里插入图片描述
分别点开它们的Query String Parameters,比较参数之间有什么不同。点击Enter(回车)键,告诉你答案。

在这里插入图片描述
事实上答案已经很明显了,只要我们多点耐心就会发现,链接的众多参数中,只有一个参数在变化。这个参数是pagenum,第一次点击加载更多的值为1,第二第三次点击它的值就变成了2和3。

当然,pagenum这个复合英文本身也说明了问题,指的可不就是页码嘛!也就是说,pagenum=1等于告诉服务器:我要歌曲信息列表第一页的数据,pagenum=2:我要歌曲信息列表第二页的数据。

这样一来,按照之前学的知识,你大约会想:我们写一个循环,每次循环都去更改pagenum的值,这样不就能实现爬取好多好多精彩评论了吗?

代码实现

你可以尝试这样做,来,请书写代码,实现这一点。备注:虽然这样能爬到我们的数据,但我并不推荐你在课堂里把所有的评论都爬取下来。一来是等待时间较长,二来虽然QQ音乐没有对爬虫做限制,但是我们也应该尽可能减少对服务器的压力。所以,循环不要超过5个。

参考代码:

import requests
# 引用requests模块
for n in range(1,6):res_comments = requests.get('https://c.y.qq.com/base/fcgi-bin/fcg_global_comment_h5.fcg?g_tk=5381&loginUin=0&hostUin=0&format=json&inCharset=utf8&outCharset=GB2312&notice=0&platform=yqq.json&needNewCode=0&cid=205360772&reqtype=2&biztype=1&topid=102065756&cmd=6&needmusiccrit=0&pagenum='+str(n)+'&pagesize=15&lasthotcommentid=song_102065756_3202544866_44059185&domain=qq.com&ct=24&cv=10101010')# 调用get方法,下载评论列表json_comments = res_comments.json()# 使用json()方法,将response对象,转为列表/字典list_comments = json_comments['comment']['commentlist']# 一层一层地取字典,获取评论列表for comment in list_comments:# list_comments是一个列表,comment是它里面的元素print(comment['rootcommentcontent'])# 输出评论print('-----------------------------------')# 将不同的评论分隔开来

有点不太对劲,发生了什么?!

如果你单独把那些评论收集起来,会发现:相同的评论出现了5次。

也就是说,我们并没有通过循环修改pagenum的值,获取到后面的评论,而是将第一页的评论循环爬取了5次。

这是怎么回事呢?要怎么才能真正爬取到后续的精彩评论呢?

好吧,这是前端的一种特殊的处理机制,这里的pagenum并不是实际意义上的页码。真正令更多精彩评论展示发挥作用的字段其实是pagesize。

如果你想获得前5页的内容?那就相当于15 * 5 = 75条评论,也就是pagesize = 75。

那么应该怎么修改呢,请想一想。

参考代码:

import requests
# 引用requests模块res_comments = requests.get('https://c.y.qq.com/base/fcgi-bin/fcg_global_comment_h5.fcg?g_tk=5381&loginUin=0&hostUin=0&format=json&inCharset=utf8&outCharset=GB2312&notice=0&platform=yqq.json&needNewCode=0&cid=205360772&reqtype=2&biztype=1&topid=102065756&cmd=6&needmusiccrit=0&pagenum=1&pagesize=75&lasthotcommentid=song_102065756_3202544866_44059185&domain=qq.com&ct=24&cv=10101010')
# 调用get方法,下载评论列表
json_comments = res_comments.json()
# 使用json()方法,将response对象,转为列表/字典
list_comments = json_comments['comment']['commentlist']
# 一层一层地取字典,获取评论列表
for comment in list_comments:
# list_comments是一个列表,comment是它里面的元素print(comment['rootcommentcontent'])# 输出评论print('-----------------------------------')# 将不同的评论分隔开来

运行一下,是不是可以了?
这样写代码,的确能够完成我们的目标。只是修改链接的参数实在太麻烦了,显然不够优雅,因为它实在太长了。

素有“人工智能之父”的唐纳德·克努特(Donald Ervin Knuth)讲过一句话让我印象深刻,他说:代码写出来是让人读的,只是顺便拿去让机器执行。

在这里插入图片描述
我们来让这个代码变好看些。事实上,requests模块里的requests.get()提供了一个参数叫params,可以让我们用字典的形式,把参数传进去。它的官方文档,是这样描述:

在这里插入图片描述
所以,其实我们可以把Query String Parameters里的内容,直接复制下来,封装为一个字典,传递给params。只是有一点要特别注意:要给他们打引号,让它们变字符串。

所以,代码最后可能长这样:

import requests
# 引用requests模块
url = 'https://c.y.qq.com/base/fcgi-bin/fcg_global_comment_h5.fcg'
# 请求歌曲评论的url参数的前面部分for i in range(5):params = {'g_tk':'5381','loginUin':'0', 'hostUin':'0','format':'json','inCharset':'utf8','outCharset':'GB2312','notice':'0','platform':'yqq.json','needNewCode':'0','cid':'205360772','reqtype':'2','biztype':'1','topid':'102065756','cmd':'6','needmusiccrit':'0','pagenum':str(i),'pagesize':'15','lasthotcommentid':'song_102065756_3202544866_44059185','domain':'qq.com','ct':'24','cv':'10101010'   }# 将参数封装为字典res_comments = requests.get(url,params=params)# 调用get方法,下载这个字典json_comments = res_comments.json()list_comments = json_comments['comment']['commentlist']for comment in list_comments:print(comment['rootcommentcontent'])print('-----------------------------------')

你可以尝试运行它试试看:
怎么样,这样是不是也可以正常运行!

被隐藏的歌曲清单

好了,现在回到一开始遇到的难题:我想要爬取周杰伦更多的歌曲信息,但是qq音乐告诉我:想要查看更多内容,请下载一个客户端。

在这里插入图片描述
这一次,我们所向披靡的爬虫难道踢到了钢板,从此要金盆洗脚息步于江湖?

作为一名忠实的狂热粉丝,再挣扎一下吧!

前面我们提到,一个完整url是由两部分组成的,前半部分大多形如:https://xx.xx.xxx/xxx/xxx,后半部分则是xx=xx&xx=xxx&xxxxx=xx&,中间有时候会用?来连接。

来看看我们搜索的首页:

https://y.qq.com/portal/search.html#page=1&searchid=1&remoteplace=txt.yqq.top&t=song&w=周杰伦

不出所料,这个链接的前半部分是https://y.qq.com/portal/search.html,后半部分是page=1&searchid=1&remoteplace=txt.yqq.top&t=song&w=周杰伦,然而,分隔这两部分的符号不是?,而是#。

其实在这里,#和?的功能是一样的,作用都是分隔,若把链接的#替换成?,访问的效果是一样的(注意:用?分隔的url不一定可以用#代替)。

既然如此,我们是不是可以跟前面一样,对参数下手了呢?

观察一下后半部分的参数
page=1&searchid=1&remoteplace=txt.yqq.top&t=song&w=周杰伦,page(中文:页面),searchid(中文:搜索id),remoteplace(中文:远程位置),后面的t和w这俩参数虽然不知道是什么,但根据他们的值(song和周杰伦)可窥得一斑,应该是指类型和关键字。

前面我们在爬取评论的时候知道,改变pagenum就可以加载更多的数据。举一反三,试想,如果改变搜索页面(https://y.qq.com/portal/search.html#page=1&searchid=1&remoteplace=txt.yqq.top&t=song&w=周杰伦)的page这个参数我们是否可以访问到其他页面的数据呢?

在这里插入图片描述
为了验证猜想,老师将网页链接中的page=1改成了page=2,果然就访问到了下一页数据,嘿嘿嘿,来吧,可以造作起来了!

还记得更快查找XHR的骚操作吗?1️⃣先把Network面板清空,2️⃣再修改page值按回车键,3️⃣查看Network多出来的新XHR,也就是这个client_search_cp…。

剩下的事情就简单了,重复上面的步骤,找到Headers,找到最下面的client_search_cp…,点开Query String Parameters,观察参数的变化规律。

找到了吗?

实际上,p值和searchid都在变化,但通过前面的网页测试来看,searchid的值都为1仍然成功翻页,由此可知,searchid的变化并不影响大局。

关键来看p值的变化:

在这里插入图片描述
这个参数是p,第1页XHR的参数p值为1,第2、3页XHR的参数p值则为2和3,说明在这个client_search_cp…的请求中,代表页码的参数是p(page的缩写)。

依然是爬取歌曲的相关信息(歌曲名、所属专辑、播放时长、播放链接),只不过这一次,可以爬取的可不止是第一页的数据。

如此,代码应该如下(同上,不推荐循环超过5次):

# 直接运行代码就好
import requests
# 引用requests模块
url = 'https://c.y.qq.com/soso/fcgi-bin/client_search_cp'
for x in range(5):params = {'ct':'24','qqmusic_ver': '1298','new_json':'1','remoteplace':'sizer.yqq.song_next','searchid':'59091538798969282','t':'0','aggr':'1','cr':'1','catZhida':'1','lossless':'0','flag_qc':'0','p':str(x+1),'n':'20','w':'周杰伦','g_tk':'5381','loginUin':'0','hostUin':'0','format':'json','inCharset':'utf8','outCharset':'utf-8','notice':'0','platform':'yqq.json','needNewCode':'0'    }# 将参数封装为字典res_music = requests.get(url,params=params)# 调用get方法,下载这个字典json_music = res_music.json()# 使用json()方法,将response对象,转为列表/字典list_music = json_music['data']['song']['list']# 一层一层地取字典,获取歌单列表for music in list_music:# list_music是一个列表,music是它里面的元素print(music['name'])# 以name为键,查找歌曲名print('所属专辑:'+music['album']['name'])# 查找专辑名print('播放时长:'+str(music['interval'])+'秒')# 查找播放时长print('播放链接:https://y.qq.com/n/yqq/song/'+music['mid']+'.html\n\n')# 查找播放链接

运行结果(节选部分)

退后
所属专辑:依然范特西
播放时长:261秒
播放链接:https://y.qq.com/n/yqq/song/001L1lqm4UAdyo.html最长的电影
所属专辑:我很忙
播放时长:235秒
播放链接:https://y.qq.com/n/yqq/song/003ZrdgZ0UnjDl.html发如雪
所属专辑:十一月的萧邦
播放时长:299秒
播放链接:https://y.qq.com/n/yqq/song/0027oMO61wWi55.html夜的第七章
所属专辑:依然范特西
播放时长:228秒
播放链接:https://y.qq.com/n/yqq/song/0010ibBn4bYFTk.html我不配
所属专辑:我很忙
播放时长:288秒
播放链接:https://y.qq.com/n/yqq/song/001T3JAT15palI.html爱在西元前
所属专辑:范特西
播放时长:234秒
播放链接:https://y.qq.com/n/yqq/song/002usg9o4GTAKf.html彩虹
所属专辑:我很忙
播放时长:263秒
播放链接:https://y.qq.com/n/yqq/song/004bRWFg3fej9y.html本草纲目
所属专辑:依然范特西
播放时长:209秒
播放链接:https://y.qq.com/n/yqq/song/001bo9Wy1NfHpb.html说好不哭(with 五月天阿信)
所属专辑:说好不哭(with 五月天阿信)
播放时长:222秒
播放链接:https://y.qq.com/n/yqq/song/001qvvgF38HVc4.html反方向的钟
所属专辑:Jay
播放时长:258秒
播放链接:https://y.qq.com/n/yqq/song/0017K7gL4WYnw2.html阳光宅男
所属专辑:我很忙
播放时长:222秒
播放链接:https://y.qq.com/n/yqq/song/001bnNGN127Kbq.html龙卷风
所属专辑:Jay
播放时长:250秒
播放链接:https://y.qq.com/n/yqq/song/002l8JN71d2Dxy.htmlMojito
所属专辑:Mojito
播放时长:185秒
播放链接:https://y.qq.com/n/yqq/song/001glaI72k8BQX.html我是如此相信
所属专辑:我是如此相信
播放时长:266秒
播放链接:https://y.qq.com/n/yqq/song/001PLl3C4gPSCI.html不该 (with aMEI)
所属专辑:周杰伦的床边故事
播放时长:290秒
播放链接:https://y.qq.com/n/yqq/song/000sxzol11raSd.html屋顶
所属专辑:K情歌10
播放时长:319秒
播放链接:https://y.qq.com/n/yqq/song/001wXiwd0eRSes.html周大侠
所属专辑:2007世界巡回演唱会
播放时长:134秒
播放链接:https://y.qq.com/n/yqq/song/003nLOYI4gJ6U0.html晴天
所属专辑:周杰伦地表最强世界巡回演唱会
播放时长:249秒
播放链接:https://y.qq.com/n/yqq/song/004Fs2FP1EvZYc.html兰亭序
所属专辑:2011年春节联欢晚会歌曲
播放时长:240秒
播放链接:https://y.qq.com/n/yqq/song/004bsJxD1n2Gjk.html断了的弦
所属专辑:寻找周杰伦
播放时长:297秒
播放链接:https://y.qq.com/n/yqq/song/003ZdxP61ClQZ5.html黑色毛衣
所属专辑:十一月的萧邦
播放时长:252秒
播放链接:https://y.qq.com/n/yqq/song/003iY6cU4YG0xi.html我落泪情绪零碎
所属专辑:跨时代
播放时长:257秒
播放链接:https://y.qq.com/n/yqq/song/0022b7OX2STU86.html暗号
所属专辑:八度空间
播放时长:271秒
播放é¾接:https://y.qq.com/n/yqq/song/000NQDjk4BA0W3.html开不了口
所属专辑:范特西
播放时长:284秒
播放链接:https://y.qq.com/n/yqq/song/0020qX4u2JJRxK.html借口
所属专辑:七里香
播放时长:260秒
播放链接:https://y.qq.com/n/yqq/song/002XWgfo0IKPOH.html说了再见
所属专辑:跨时代
播放时长:282秒
播放链接:https://y.qq.com/n/yqq/song/00265Jxe3JzXOJ.html大笨钟
所属专辑:十二新作
播放时长:242秒
播放链接:https://y.qq.com/n/yqq/song/002jkBM53MLB9Q.html甜甜的
所属专辑:我很忙
播放时长:243秒
播放链接:https://y.qq.com/n/yqq/song/000xdZuV2LcQ19.html回到过去
所属专辑:八度空间
播放时长:233秒
播放链接:https://y.qq.com/n/yqq/song/003rxgIM2eOFSF.html

悄悄地告诉你,如果你将这个代码里’w’关键字参数值换成另一个歌手/歌曲名,那么它也能爬到这个歌手/同名歌曲的信息。如果你愿意,可以在本关卡结束后,练习做这件事。

当然,qq音乐的产品经理肯定是不希望我们能访问到第2页的内容,他们更希望我们能下载客户端,从客户端访问数据。

为此,服务器就可能会对我们这些“投机取巧”的爬虫做限制处理。一来可以降低服务器的访问压力,毕竟成千上万次的访问对代码来说就是一个for循环的事儿;二来可以拦截那些想要通过爬虫窃取数据的竞争者。

那这就有一个问题,服务器怎么判断访问者是一个普通的用户(通过浏览器),还是一个爬虫者(通过代码)呢?

这需要我们回到浏览器中,重新认识一个新的信息栏:请求头Request Headers。

什么是Request Headers

就是这个:

在这里插入图片描述

每一个请求,都会有一个Request Headers,我们把它称作请求头。它里面会有一些关于该请求的基本信息,比如:这个请求是从什么设备什么浏览器上发出?这个请求是从哪个页面跳转而来?

如上图,user-agent(中文:用户代理)会记录你电脑的信息和浏览器版本(如我的,就是windows10的64位操作系统,使用谷歌浏览器)。

origin(中文:源头)和referer(中文:引用来源)则记录了这个请求,最初的起源是来自哪个页面。它们的区别是referer会比origin携带的信息更多些。

如果我们想告知服务器,我们不是爬虫,而是一个正常的浏览器,就要去修改user-agent。倘若不修改,那么这里的默认值就会是Python,会被服务器认出来。

有趣的是,像百度的爬虫,它的user-agent就会是Baiduspider,谷歌的也会是Googlebot……如是种种。

而对于爬取某些特定信息,也要求你注明请求的来源,即origin或referer的内容。比如我有试过,在爬取歌曲详情页里的歌词时,就需要注明这个信息,否则会拿不到歌词。你可以在写练习的时候进行尝试。

如何添加Request Headers

Requests模块允许我们去修改Headers的值。点击它的官方文档,搜索“user-agent”,你会看到:

在这里插入图片描述
如上,只需要封装一个字典就好了。和写params非常相像。

而修改origin或referer也和此类似,一并作为字典写入headers就好。就像这样:

import requests
url = 'https://c.y.qq.com/soso/fcgi-bin/client_search_cp'headers = {'origin':'https://y.qq.com',# 请求来源,本案例中其实是不需要加这个参数的,只是为了演示'referer':'https://y.qq.com/n/yqq/song/004Z8Ihr0JIu5s.html',# 请求来源,携带的信息比“origin”更丰富,本案例中其实是不需要加这个参数的,只是为了演示'user-agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/71.0.3578.98 Safari/537.36',# 标记了请求从什么设备,什么浏览器上发出}
# 伪装请求头params = {
'ct':'24',
'qqmusic_ver': '1298',
'new_json':'1',
'remoteplace':'sizer.yqq.song_next',
'searchid':'59091538798969282',
't':'0',
'aggr':'1',
'cr':'1',
'catZhida':'1',
'lossless':'0',
'flag_qc':'0',
'p':'1',
'n':'20',
'w':'周杰伦',
'g_tk':'5381',
'loginUin':'0',
'hostUin':'0',
'format':'json',
'inCharset':'utf8',
'outCharset':'utf-8',
'notice':'0',
'platform':'yqq.json',
'needNewCode':'0'    
}
# 将参数封装为字典
res_music = requests.get(url,headers=headers,params=params)
# 发起请求,填入请求头和参数

鉴于这个代码你已经写过也运行过,所以在这里我们不再做练习。 只需要记得Request Headers(请求头)的含义和用法就好。

如果有一天,你真的需要爬取一万多条信息,将for循环执行成百上千次。

那么,你最好将自己的爬虫伪装成真实的浏览器(填写请求头)—— 因为在那种情况下,服务器很可能拒绝爬虫访问。甚至有的网站,一开始就不允许爬虫访问。如,知乎、猫眼电影。

复习

在本关卡,我们主要学习了带参数请求数据和Request Headers的用法。

对于前者,我们认识到一个url由两部分组成,?(有时候是“#”)之前是我们请求的地址,?之后是我们的请求所附带的参数。通常,我们会把参数封装成一个字典,添加进请求中去。

通过对参数进行修改,我们能爬到许多信息。

大约在第8关,我们还会学习另一种数据请求的类型post,它区别于我们今天所使用的get请求,但用法却是大同小异。

而对于后者,Request Headers,我们把它称作请求头。它里面会有一些关于该请求的基本信息,比如:这个请求是从什么设备什么浏览器上发出?这个请求是从哪个页面跳转而来?

它最大的应用是帮助我们应对“反爬虫”技术,将Python爬虫伪装成真正的浏览器,不为服务器所辨识;同时也可以标记这个请求的来源是什么,最终帮助我们拿到想要的信息。

除此之外,我们还通过项目实操,学会如何判断我们想要的信息是在Html,还是在XHR里:

在这里插入图片描述
利用这张图来分析网页,你能找到几乎所有你想要的信息。剩下的,只是请求、解析、提取、存储罢了。其中解析和提取你已经学过,存储我们将在下一关学习。在未来,我们会学习更多的请求方式,更快的请求方式。

最后用一个代码复习本关卡所学,就是:

import requests
url = 'https://c.y.qq.com/soso/fcgi-bin/client_search_cp'headers = {'origin':'https://y.qq.com',# 请求来源,本案例中其实是不需要加这个参数的,只是为了演示'referer':'https://y.qq.com/n/yqq/song/004Z8Ihr0JIu5s.html',# 请求来源,携带的信息比“origin”更丰富,本案例中其实是不需要加这个参数的,只是为了演示'user-agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/71.0.3578.98 Safari/537.36',# 标记了请求从什么设备,什么浏览器上发出}
# 伪装请求头params = {
'ct':'24',
'qqmusic_ver': '1298',
'new_json':'1',
'remoteplace':'sizer.yqq.song_next',
'searchid':'59091538798969282',
't':'0',
'aggr':'1',
'cr':'1',
'catZhida':'1',
'lossless':'0',
'flag_qc':'0',
'p':'1',
'n':'20',
'w':'周杰伦',
'g_tk':'5381',
'loginUin':'0',
'hostUin':'0',
'format':'json',
'inCharset':'utf8',
'outCharset':'utf-8',
'notice':'0',
'platform':'yqq.json',
'needNewCode':'0'    
}
# 将参数封装为字典
res_music = requests.get(url,headers=headers,params=params)
# 发起请求,填入请求头和参数

我们下一关见!

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

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

相关文章

Laravel 表单验证器的常用的2种使用方法

1、使用控制器的 validate 方法进行参数验证 场景一:前后端未分离 /*** 保存一篇新的博客文章。** param Request $request* return Response*/ public function store(Request $request) {$this->validate($request, [title > required|unique:posts|max:2…

Postgresql JSON对象和数组查询

文章目录 一. Postgresql 9.5以下版本1.1 简单查询(缺陷:数组必须指定下标,不推荐)1.1.1 模糊查询1.1.2 等值匹配1.1.3 时间搜索1.1.4 在列表1.1.5 包含 1.2 多层级JSONArray(推荐)1.2.1 模糊查询1.2.2 模糊查询 NOT1.2.3 等值匹配…

OpenCV(八):图像二值化

目录 1.固定值二值化 2.自适应阈值二值化 3.Android JNI完整代码 1.固定值二值化 固定阈值二值化是OpenCV中一种简单而常用的图像处理技术,用于将图像转换为二值图像。在固定阈值二值化中,像素值根据一个预定义的阈值进行分类,大于阈值的…

c# 本地化中英文切换

区域 线程默认区域为当前计算机所选区域 设置当前区域: Thread.CurrentThread.CurrentCulture new CultureInfo(“zh-cn”); 获取当前区域: Console.WriteLine(Thread.CurrentThread.CurrentCulture.ToString()); 区域名称: “zh-cn” 中文…

解决 .csv 文件上传到 pgsql 的字符报错问题

目录 背景问题解决办法 背景 上传 .csv 文件进行数据导入到 pg 时,报错显示如下: ods.tbl_inp_fee_detail.csv数据上传失败 报错信息:org.postgresql.util.PSQLException: ERROR: invalid byte sequence for encoding "UTF8": 0x00 Where: C…

「黄钊的AI日报·第一季」免费试读!最后5天,早鸟价60元~

1、每天5条AI内容点:不是常见的新闻汇总模式,而是站在AI产品经理的视角,把每篇AI干货的最核心内容,直接拎出来、甚至用自己的话来描述,是在展示“what I see”,和原文已经不是一个东西了! 2、已…

独家首发!openEuler 主线集成 LuaJIT RISC-V JIT 技术

RISC-V SIG 预期随主线发布的 openEuler 23.09 创新版本会集成 LuaJIT RISC-V 支持。本次发版将提供带有完整 LuaJIT 支持的 RISC-V 环境并带有相关软件如 openResty 等软件的支持。 随着 RISC-V SIG 主线推动工作的进展,LuaJIT 和相关软件在 RISC-V 架构下的支持也…

C# 试图加载格式不正确的程序。 (异常来自 HRESULT:0x8007000B)

C# 在调用Cdll时,可能会出现 :试图加载格式不正确的程序。 (异常来自 HRESULT:0x8007000B)这个错误。 一般情况下是C#目标平台跟Cdll不兼容,64位跟32位兼容性问题, a.客户端调用Cdll报的错则, 1)允许的话把C#客户端…

数据结构 -作用及基本概念

为什么要使用数据结构 学习数据结构是计算机科学和软件工程领域中非常重要的一门课程。以下是学习数据结构的几个重要原因: 组织和管理数据:数据结构提供了一种组织和管理数据的方式。通过学习不同的数据结构,你可以了解如何有效地存储和操作…

[dasctf]misc3 chrchrchr.pcapng

webshell 流量分析 php代码部分没啥看的,主要在标黄的部分,裁剪掉前面的字符可base解码 能看到在向a.txt中写入数据 wp # tshark.exe -r chrchrchr.pcapng -T fields -e urlencoded-form.value -Y "urlencoded-form.keyzd2ebbfb26dd" >…

xss前十二关靶场练习

目录 一、xss原理和分类 1.原理 2.分类:xss分为存储型和反射型以及dom型 (1)反射性 (2)存储型 (3)dom型 二、靶场关卡练习​编辑 1.第一关 2.第二关 3.第三关 4.第四关 5.第五关 6…

Rn实现省市区三级联动

省市区三级联动选择是个很频繁的需求,但是查看了市面上很多插件不是太老不维护就是不满足需求,就试着实现一个 这个功能无任何依赖插件 功能略简单,但能实现需求 核心代码也尽力控制在了60行左右 pca-code.json树型数据来源 Administrative-d…