爬虫探索时 [ 哎哟,不错哟 ]

版权声明:Hi,I m Debroon【Q:23609099,青睐互动 https://blog.csdn.net/qq_41739364/article/details/87905360
  • Network、XHR知识

  • json 模块

  • 爬取 jay 的歌曲

  • 网址格式的解析

  • 爬取 all singers 歌曲

  • 爬取 歌曲评论 的小技巧

  • 练习 爬虫实现获取快递信息

爬虫初体验 之后的 寻找周杰伦 爬虫计划。

在练习之前,打开 youtube 吧在语言都不能表达的情感里去感受那靓亮的相逢~     表示需要打开 VPN

全屏操作(win:F11;Mac:control+command+F)


计划 : 爬取 jay 的歌曲

地点 : QQ音乐


请您务必新建一个浏览器标签,跟随我操作 -- 点击 QQ音乐的官网 。

首先,在 QQ音乐官网后 + /robots.txt (统一小写),查看QQ音乐的Robots协议  https://y.qq.com/robots.txt

明确指出,这是代表禁止所有SE(搜索引擎)收录网站的有 playlist、yqq/playlist、n/yqq/playlist,文末我会放上Robots协议的资料。

从robots协议看,只是禁止了playlist相关的信息爬取,问题不大,放心去吧!


start ...

登录QQ音乐网址 : https://y.qq.com 

搜索 jay 的页面 ,TA 的网址是: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您已经知道了,获取数据这一步完成,接着打印网页源代码找歌曲;【 建议先写一遍再看 】

import requests

URL = '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'
# jay 网页的第一页
res = requests.get(URL)
print(res.text)  # 打印网页源代码

程序运行后 

我翻了翻,好奇怪歌曲呢??是不是中文的歌曲名会乱码所以找不到了。只好去看看网页网页源代码,鼠标右击 [ 检查 ] --》(Windows快捷方式,是ctrl+shift+i)

这是Chrome浏览器的,看到最左边的箭头点击一下TA(Windows快捷方式是ctrl+shift+c)。再把鼠标放到对应歌曲名上,显示HTML语言的文本框会跟随您的操作变化。

进此一步,还可以修改对应的歌曲信息。如,把 告白气球 变成 终于下气球了。

看,改好了。好好利用这个技巧,也许以后可以帮助您呢?

我们所修改的是元素内的普通文本内容,您可以试一下修改周杰伦为 jay。

话回到歌名的话题上,我想说我们的确在网页源代码找到了歌曲名还可以找到歌手、专辑、时间、链接。不过我们还没学习如何解析网页源代码,所以呢我打算先教一种有助于理解爬虫原理的方式,我们下一篇博客再教解析网页源代码的方式。

我们在使用浏览器上网的时候。从本质上来讲,只有两种动作:一种是从服务器那儿拿数据,称作Get;一种是把我们这里的信息交给服务器去处理,称作Post。

不论是Get也好,Post也好。它们都被记录在【Network】里。现在,请你调用 [ 检查 ]工具,去看看TA。

流程如: 右击鼠标 -> 检查  -> Network

打开后,发现空空如也,

这是因为Network记录的是实时网络请求。现在网页都已经加载完了,当然不会有东西。

刷新,浏览器会重新访问网络,这样就会有记录。

Network能够记录浏览器的所有请求。我们最常用的是:ALL(查看全部)/XHR(仅查看XHR)/Doc(Document,第0个请求一般在这里),有时候也会看看:Img(仅查看图片)/Media(仅查看媒体文件)/Other(其他)。最后,JS和CSS,则是前端代码,负责发起请求和页面实现;Font是文字的字体。

先讲主干,解释这个面板留在文末~~~~~~

我们平时在使用浏览器上网的时候,经常会有这样的情况:网址没变,但是网页里面的一部分内容却变了。

如购物网站,下滑自动加载出更多商品。在线翻译网站,输入中文翻译英文。这说明,即便我们没有进行翻页/跳转/刷新的操作,浏览器也在和服务器实时地传输一些数据。这个动作,就通过XHR(XHR and Fetch)来实现。

其实我们的歌曲名,就是藏在XHR里。我们点击的XHR,这样屏幕上的请求就都是XHR类型,或者是Fetch类型。它们两者并没有本质区别,只是Fetch出现得比XHR更晚一些,所以对一些开发人员来说会更好用,但作用都是一样的。

fetch + xhr = 19,一共19个。我们要从里面找出带有歌单的那一个。

这方面我阅历丰富呀,因为见名知意。编程的基本要求 : 用一个几个字母数字抽象出TA的作用。

所以去尝试阅读它们的名字。比如你一眼就看到:client_search(客户端搜索)……而且它最大,有10.9KB(看Size),我们来点击它。如果文件较少,一个一个去试也很快的。另外有一个更快的方法,我放在了博客末尾。

打开其中任何一个,都可以看见几个固定标签如 Headers、Preview、Response、Cookies、Timing。Headers:标头(介绍信息)、Preview:预览、Response:原始信息、Timing:时间。

点击Preview,你能在里面发现我们想要的信息:歌名就藏在里面

只是有点难找,需要你一层一层展开:data->song->list->0->name,然后就能看到“告白气球”

现在知道了需要数据的在XHR文件里面。可是因为我们重新打开了一个文件,所以我们就不要用之前的网址。

歌曲名就在这里,它的键是“name”。理解这句话:这个XHR是一个字典,键“data”对应的值也是一个字典;在该字典里,键“song”对应的值也是一个字典;在该字典里,键“list”对应的值是一个列表;在该列表里,一共有20(0-19)个元素;每一个元素都是一个字典;在每个字典里,键“name”的值,对应的是歌曲名。

我们来看看这个XHR的Headers,里面都有什么。如下所示它被分为了四个模块。

点击 General 右边的小三角▶️

名称 释义
Requests URL 请求链接的地址,这个就是我们需要的URL啦
Requests Method 请求方式,这里是 GET
Status Code 状态码,200代表正常响应
Remote Address 服务器的ip地址和端口
Referrer Policy 记录请求来源的信息

利用requests.get访问这个链接(Requests URL),把这个列表下载到本地。然后去读取它的每个元素内,隐藏的歌曲名。

import requests
# 引用requests模块。

res = 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方法,下载这个文件,准备提取里面的20个列表。

print(res.text)
# 把res的源代码以字符串形式打印出来。

代码写到一半,就写不下去。目前知识还不够用呀。

在这串代码里,res有两种方法。一个是text,一个是content。前者是字符串,后者是二进制的bytes数据。TA们都不方便我们提取我们想要的内容,我们需要一个字典。现在我来给您一个解决方案:在Python当中有这样一个模块,它的名字叫json。它的技能是text进去,字典出来。

json模块的 json.loads函数可以让字符串转为字典。

如果学习过html,它通过标签、属性来实现分层和对应。json则是另一种组织数据的格式,长得和Python中的列表/字典非常相像。TA和html一样,常用来做网络数据传输。刚刚我们在XHR里查看到的列表/字典,严格来说其实它不是列表/字典,它是json。

而json和XHR之间的关系:XHR用于传输数据,TA能传输很多种数据,json是被传输的一种数据格式。就是这样而已。

我们总是可以将json格式的数据,转换成正常的列表/字典,也可以将列表/字典,转换成json。json实现通用是因为所有编程语言都有字符串类型,以这个做媒介。

import requests, json
# 引用json,json是一种跨平台的轻量级数据交换语言。这是一个系统预装模块,你不需要手动安装。

res = 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方法,下载这个文件准备提取里面的20个列表。

json_res = json(res.text)
# 字符串转为列表,那么参数肯定是字符串哦。

print(type(json_res))
# 输出 json_res 的数据类型

正常情况下,您会发现此时的json_res已经是字典。那么我们就可以使用对待字典的方式,来提取我们想要的数据。

import requests,json
# 引用json,json是一种跨平台的轻量级数据交换语言。这是一个系统预装模块,你不需要手动安装。
url = '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'

res = requests.get(url)
#下载该网页,赋值给res
json_res = json.loads(res.text)
# 使用 json 来解析res.text

music = json_res['data']['song']['list']
# 一层一层地取字典,获取歌单的列表 取得第一首歌告白气球的路径  data->song->list->0->name

for x in music:
# music是一个列表,x是它里面的元素
    print("歌名:> "+ x['name'])
    # 以name为键,查找歌曲名。

输出结果如下:

接着,继续找歌曲另外的信息。如专辑、播放时常、播放链接,这些看名字就可以才出来啦!!

import requests,json
# 引用json,json是一种跨平台的轻量级数据交换语言。这是一个系统预装模块,你不需要手动安装。
url = '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'

res = requests.get(url)
#下载该网页,赋值给res
json_res = json.loads(res.text)
# 使用 json 来解析res.text

music = json_res['data']['song']['list']
# 一层一层地取字典,获取歌单的列表 取得第一首歌告白气球的路径  data->song->list->0->name

for x in music:
# music是一个列表,x是它里面的元素
    print("歌名:> "+ x['name'])
    # 以name为键,查找歌曲名。
    print('所属专辑:'+x['album']['name'])
    #查找专辑名
    print('播放时长:'+str(x['interval'])+'秒')
    #查找播放时长
    print('播放链接:https://y.qq.com/n/yqq/song/'+x['mid']+'.html\n\n')
    #查找播放链接

输出结果 : 

而如果你肯多翻查几个页面,多加载几个XHR,你能找到它们所请求的网址之间的规律,从而,你能拿到周杰伦在QQ音乐上的所有歌曲信息。就像这样:

认真观察你会发现,网址变化的,只有一个“p=1”,“p=2”,“p=3”。你可以写一个循环,来自动生成所有的链接。

import requests,json
# 引用json,json是一种跨平台的轻量级数据交换语言。这是一个系统预装模块,你不需要手动安装。
for i in range(1,4):
    url = '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(i) +'&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'

    res = requests.get(url)
    #下载该网页,赋值给res
    json_res = json.loads(res.text)
    # 使用 json 来解析res.text

    music = json_res['data']['song']['list']
    # 一层一层地取字典,获取歌单的列表 取得第一首歌告白气球的路径  data->song->list->0->name
    print("第"+str(i)+"页")
    for x in music:
    # music是一个列表,x是它里面的元素
        print("歌名:> "+ x['name'])
        # 以name为键,查找歌曲名。
        print('所属专辑:'+x['album']['name'])
        #查找专辑名
        print('播放时长:'+str(x['interval'])+'秒')
        #查找播放时长
        print('播放链接:https://y.qq.com/n/yqq/song/'+x['mid']+'.html\n\n')
        #查找播放链接

稍稍为服务器考虑一下,我就取前 3 页吧因为我是写教程不是自己爬。如果看我教程的每个人都爬到页数尽头,那对服务器会造成一定的压力。至于页数尽头是多少,这个问题就交给您了~ 甚至还可以加上评论信息呢 ~~~

end ...


文末:

            Robots 资料: https://baike.baidu.com/item/robots/5243374?fr=aladdin

            

           现在补充面板的内容,

左边红色的圈圈⭕️是启用监控,右边的圈圈是清空面板信息

     这是一个时间轴,描述每个时间节点发生的事项

Name 名字
Status 请求完成的状态
Type 类型 --显示是异步请求还是图片
Initiator 该请求通过什么发送
Size 大小
Time 耗时
Waterfall 瀑布流,描述起止时间

小结

   如果网页源代码没有对应数据  --查看XHR

   首先打开Network -> xhr -> 阅读名字 -> 翻看每个直到找到对应数据的 ->  操作加载新的XHR

分享

    json 资料: https://docs.python.org/3/library/json.html

    json.loads(res.text) 还可以用  res.json() 方法代替,功能是把Response对象转为字典。

    网址URL:

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(i) +'&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'

    可以封装一下,因为这么长的网址实在不好改动某个参数。

   每个URL都由两部分组成。

   前半部分大多形如:https://xx.xx.xxx/xxx/xxx

   两部分使用?来连接

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

   

前半部分是我们所请求的地址,TA告诉服务器,我想访问这里。而后半部分,就是我们的请求所附带的参数,它会告诉服务器,我们想要什么。这参数的结构,会和字典很像,有键有值,键值用=连接;每组键值之间,使用&来连接。

    https://c.y.qq.com/soso/fcgi-bin/client_search_cp? 为client_search_cp?文件路径,QQ音乐官网 -> Jay的歌曲页。

    URL = ' https://c.y.qq.com/soso/fcgi-bin/client_search_cp?'

    ct、qqmusic_ver、到最后 needNewCode 都可以封装为字典。

    以 ct 为例其TA同,ct = 24 ,以字典方式即 'ct' = '24' , &是分割符,用 逗号(,) 代替即可。

    如果不想推,也可以直接查看浏览器的,如图。

    路径 :Network -> xhr  ->  client_search_cp?(注意: 不同文件参数不一) -> Headers  -> Query String Parameters

 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(i+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'    
    }
    # 将参数封装为字典

    联合在一起,代码如下:

import requests,json

sing = input('请输入歌手:> ')   # 爬取 QQ音乐任意歌手歌曲
for i in range(4):            # 页数可调,建议做一个判断如果没有页数了就结束
    url = 'https://c.y.qq.com/soso/fcgi-bin/client_search_cp?'
    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(i + 1),   # 页数项在这
        'n': '20',
        'w': sing,         # 这个参数改动为歌手的名字
        'g_tk': '5381',
        'loginUin': '0',
        'hostUin': '0',
        'format': 'json',
        'inCharset': 'utf8',
        'outCharset': 'utf-8',
        'notice': '0',
        'platform': 'yqq.json',
        'needNewCode': '0'
    }
    # 将参数封装为字典
    res = requests.get(url, params=params) # 关键字传参, 可以这样描述是因为,requests模块里的requests.get()提供了一个参数叫params,可以让我们用字典的形式,把参数传进去,下面有图示。
    #json_res = json.loads(res.text)
    json_res = res.json()

    music = json_res['data']['song']['list']
    print("第"+str(i)+"页")
    for x in music:
    # music是一个列表,x是它里面的元素
        print("歌名:> "+ x['name'])
        # 以name为键,查找歌曲名。
        print('所属专辑:'+x['album']['name'])
        #查找专辑名
        print('播放时长:'+str(x['interval'])+'秒')
        #查找播放时长
        print('播放链接:https://y.qq.com/n/yqq/song/'+x['mid']+'.html\n\n')
        #查找播放链接

params参数的官方文档描述部分: 

886~


如果爬歌曲评论的话,我给您支支招。

打开评论界面,右击检查,查看Network,查看XHR。

会发现有好多好多XHR,这时候,按右边黑色的圈圈请空面板。

点击第2页,这时候会多出来俩个xhr,点击进去看Preview,能够在['comment']['commentlist']里找到评论列表。列表的每一个元素都是字典,字典里键rootcommentcontent对应的值,就是我们要找的评论。


练习  

     换另一位喜欢的歌手爬取前 3 页内容 --歌名、所属专辑、时长和播放链接。

     或者 以json的方式爬取 快递100网站 ,实现输入快递名称和单号就可以查询最新物流状态~

猜你喜欢

转载自blog.csdn.net/qq_41739364/article/details/87905360