爬虫笔记五----第五关

爬虫笔记五----第五关

来自风变编程。
在这一关,我们要完成的项目是:让上一关的代码得到进化,使它能爬取很多很多歌曲,而不只是爬取20个。同时,作为附赠,我们还要以歌曲《七里香》作为案例,去爬取它的歌曲评论。就像:
在这里插入图片描述

在这个过程当中,我们会学到带参数请求数据的知识,以及关于Requests Headers的知识。
分析过程
爬取歌曲信息也好,爬取歌词评论也好,对今天的我们来说,都不算难题。难题是:怎么翻页啊!
在这里插入图片描述
什么是带参数请求数据
我不知道你有没有认真地观察过一个完整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
当你在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
现在,我要揭晓规律:
在上面,我们能看到每个url都由两部分组成。前半部分大多形如:https://xx.xx.xxx/xxx/xxx
后半部分,多形如:xx=xx&xx=xxx&xxxxx=xx&……
两部分使用?来连接。

这前半部分是我们所请求的地址,它告诉服务器,我想访问这里。而后半部分,就是我们的请求所附带的参数,它会告诉服务器,我们想要什么。这参数的结构,会和字典很像,有键有值,键值用=连接;每组键值之间,使用&来连接。
在这里插入图片描述
在这里插入图片描述
如何带参数请求数据
在上一关当中,我们直接用requests.get()请求了url。在这一关,如果我们想拿到更多歌曲清单。就要读懂它的各个参数。修改它们,重新发起请求。
读懂参数,有两个重要的方法是“观察”和“比较”。“观察”指的是阅读参数的键与值,尝试理解它的含义。“比较”指的是比较两个相近的XHR——它们有哪些不同,对应的页面显示内容有什么不同。
现在,我们来观察比较,不同页码的歌曲列表,它们url的不同。依然在搜索“周杰伦”的结果页,点击第2页、第3页进行翻页,此时Network会多加载出2个XHR,它们的Name都是client_search…。
分别点开它们的Query String Parametres,比较参数之间有什么不同。点击Enter(回车)键,告诉你答案。
在这里插入图片描述

在此,只有一个参数变化。这个参数是p。第1页p的值为1,第二、第三页的值则为2和3。说明p代表的应该就是页码。
如果你再去对比它们的url,也能发现同样的事实:url整个儿都是一样的,只有p的值发生变化。
按照之前的知识,你大约会想:我们去写一个循环,每次循环去更改p的值,这样不就能实现爬取好多好多歌曲了吗?
代码实现

import requests
# 引用requests模块
for x in range(5):
    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='+str(x+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')
        # 查找播放链接

这样写代码,的确能够完成我们的目标。但是,这样写代码显然不够优雅——它太长了。
我们来让这个代码变好看些。事实上,requests模块里的requests.get()提供了一个参数叫params,可以让我们用字典的形式,把参数传进去。它的官方文档,是这样描述:
在这里插入图片描述
,其实我们可以把Query String Parametres里的内容,直接复制下来,封装为一个字典,传递给params。只是有一点要特别注意:要给他们打引号,让它们变字符串。

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':'64405487069162918',
    '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')
        # 查找播放链接

如果你将这个代码里’w’参数的值换成另一个喜欢的歌手,那么它也能爬到这个歌手的所有歌曲信息。如果你愿意,可以在本关卡结束后,练习做这件事。

《七里香》的评论

截止当前,我们已经掌握如何爬取歌曲列表。下面,我们要以《七里香》为例,爬取用户评论。我们来快捷地实现它。首先,进入网址: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对应的值,就是我们要找的评论。
在这里插入图片描述
剩下的事情就简单了。我们去模拟这个请求,解析json,提取想要的内容就好。
。我们去模拟这个请求,解析json,提取想要的内容就好。
点击Headers,在General里看链接,在Query String Parametres里看参数,多翻几页评论列表,总结参数的规律。
在这里插入图片描述
在这里你会遇到一个难点,XHR有两个参数在不断变化:一个是pagenum,一个lasthotcommentid。其中pagenum好理解,就是页码,但是lastcommentid是什么?我们来阅读这个英文lasthotcommentid,它的含义是:上一条热评的评论id。我们要验证这个猜想,需要确认:首先,每个评论存在commentid这个东西;其次,是验证这种对应关系。
如此,代码能写了。代码应该如下(同上,不推荐循环超过5次):

import requests
# 引用requests模块
url = 'https://c.y.qq.com/base/fcgi-bin/fcg_global_comment_h5.fcg'
commentid = ''
# 设置一个初始commentid
for x 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':'8',
    'needcommentcrit':'0',
    'pagenum':str(x),
    'pagesize':'25',
    'lasthotcommentid':commentid,
    'domain':'qq.com',
    'ct':'24',
    'cv':'101010  '
    }
    # 将参数封装为字典,其中pagenum和lastcommentid是特殊的变量
    res_comment = requests.get(url,params=params)
    # 调用get方法,下载评论列表
    json_comment = res_comment.json()
    # 使用json()方法,将response对象,转为列表/字典
    list_comment = json_comment['comment']['commentlist']
    # 一层一层地取字典,获取评论列表
    for comment in list_comment:
    # list_comment是一个列表,comment是它里面的元素
        print(comment['rootcommentcontent'])
        # 输出评论
    commentid = list_comment[24]['commentid']
    # 将最后一个评论的id赋值给comment,准备开始下一次循环

什么是Request Headers
在这里插入图片描述
每一个请求,都会有一个Requests Headers,我们把它称作请求头。它里面会有一些关于该请求的基本信息,比如:这个请求是从什么设备什么浏览器上发出?这个请求是从哪个页面跳转而来?
如上图,user-agent会记录你电脑的信息和浏览器版本(如我的,就是windows10的64为操作系统,使用谷歌浏览器)。origin和referer则记录了这个请求,最初的起源是来自哪个页面。它们的区别是referer会比origin携带的信息更多些。
如果我们想告知服务器,我们不是爬虫是一个正常的浏览器,就要去修改user-agent。倘若不修改,那么这里的默认值就会是Python,会被浏览器认出来。
有趣的是,像百度的爬虫,它的user-agent就会是Baiduspider,谷歌的也会是Googlebot……如是种种。
而对于爬取某些特定信息,也要求你注明请求的来源,即origin或referer的内容。
如何添加Requests Headers
Requests模块允许我们去修改Headers的值。点击它的官方文档,搜索“user-agent”,你会看到:
在这里插入图片描述
如上,只需要封装一个字典就好了。和写params非常相像。而修改origin或referer也和此类似,一并作为字典写入headers就好。就像这样:

import requests
url = 'https://c.y.qq.com/base/fcgi-bin/fcg_global_comment_h5.fcg'
# 这是那个,请求歌曲评论的url
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 = {
'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':'8',
'needcommentcrit':'0',
'pagenum':0,
'pagesize':'25',
'lasthotcommentid':'',
'domain':'qq.com',
'ct':'24',
'cv':'101010  '
    }

res_music = requests.get(url,headers=headers,params=params)
# 发起请求

只需要记得Request Headers(请求头)的含义和用法就好。

复习

在本关卡,我们主要学习了带参数请求数据和Request Headers的用法。对于前者,我们认识到一个url由两部分组成,?之前是我们请求的地址,?之后是我们的请求所附带的参数。通常,我们会把参数封装成一个字典,添加进请求中去。
通过对参数进行修改,我们能爬到许多信息。
而对于后者,Requests Headers,我们把它称作请求头。它里面会有一些关于该请求的基本信息,比如:这个请求是从什么设备什么浏览器上发出?这个请求是从哪个页面跳转而来?
它最大的应用是帮助我们应对“反爬虫”技术,将Python爬虫伪装成真正的浏览器,不为服务器所辨识;同时也可以标记这个请求的来源是什么,最终帮助我们拿到想要的信息。
除此之外,我们还通过项目实操,学会如何判断我们想要的信息是在Html,还是在XHR里:
在这里插入图片描述
最后用一个代码复习本关卡所学,就是:

import requests
url = 'https://c.y.qq.com/base/fcgi-bin/fcg_global_comment_h5.fcg'
# 这是那个,请求歌曲评论的url
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 = {
'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':'8',
'needcommentcrit':'0',
'pagenum':0,
'pagesize':'25',
'lasthotcommentid':'',
'domain':'qq.com',
'ct':'24',
'cv':'101010  '
    }

res_music = requests.get(url,headers=headers,params=params)
# 发起请求
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

大数据AI铭仔

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值