爬虫精进(四) ------ 带参请求/伪装成真实浏览器
一.通过Query String Parametres查看参数
请你使用浏览器打开QQ音乐官网,搜索周杰伦。然后打开检查面板里的Network
,刷新这个页面。当然,你也可以点击这个链接直达:
https://y.qq.com/portal/search.html#page=2&searchid=1&remoteplace=txt.yqq.top&t=song&w=%E5%91%A8%E6%9D%B0%E4%BC%A6
找到隐藏有歌曲列表的那个XHR
,它的名字应该叫client_search……
之类,点开它,选中Headers
,你的页面看上去会像这样:
![](https://img.haomeiwen.com/i17787668/02be861e2c4df44c.png)
我们来到一个熟悉的界面,你能看到Request Url
,很长的一个地址。现在,保持General
打开,保持Response Headers
和Request Headers
关闭。我们点开Query String Parametres
。
它里面的内容,正是请求所附带的参数,Query String Parametres,它的中文翻译是:查询字符串参数。
二.如何带参数请求数据
可以把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')
# 查找播放链接
爬虫小技巧 : 先把Network面板清空,再点击一下评论(你要找的)翻页,看看有没有多出来的新XHR,多出来的那一个,就应该是和评论相关的啦。
![](https://img.haomeiwen.com/i17787668/c884565c4713cde6.png)
![](https://img.haomeiwen.com/i17787668/e9f30430134d057c.png)
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,准备开始下一次循环
三.伪装成真实浏览器
每一个请求,都会有一个Requests Headers,我们把它称作请求头。它里面会有一些关于该请求的基本信息,比如:这个请求是从什么设备什么浏览器上发出?这个请求是从哪个页面跳转而来?
![](https://img.haomeiwen.com/i17787668/1f654b43b15842cb.png)
如上图,user-agent会记录你电脑的信息和浏览器版本(如我的,就是windows10的64位操作系统,使用谷歌浏览器)。origin和referer则记录了这个请求,最初的起源是来自哪个页面。它们的区别是referer会比origin携带的信息更多些。
如果我们想告知服务器,我们不是爬虫是一个正常的浏览器,就要去修改user-agent。倘若不修改,那么这里的默认值就会是Python,会被浏览器认出来。
有趣的是,像百度的爬虫,它的user-agent就会是Baiduspider,谷歌的也会是Googlebot……如是种种。
而对于爬取某些特定信息,也要求你注明请求的来源,即origin或referer的内容。比如我有试过,在爬取歌曲详情页里的歌词时,就需要注明这个信息,否则会拿不到歌词。你可以在写练习的时候进行尝试。
请求歌曲评论案例 :
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)
# 发起请求
请求前五页歌曲的歌词 :
import requests
from bs4 import BeautifulSoup
import re
url = 'https://c.y.qq.com/soso/fcgi-bin/client_search_cp'
font = {}
for x in range(5):
headers = {
'origin': 'https://y.qq.com',
# 请求来源,本案例中其实是不需要加这个参数的,只是为了演示
'referer': 'https://y.qq.com/portal/search.html',
# 请求来源,携带的信息比“origin”更丰富,本案例中其实是不需要加这个参数的,只是为了演示
'user-agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.142 Safari/537.36'
# 标记了请求从什么设备,什么浏览器上发出
}
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 = requests.get(url,params=params,headers=headers)
json_music = res.json()
list_song = json_music['data']['song']['list']
for oneSong in list_song:
MusicID = oneSong['id']
MusicName = oneSong['name']
MusicMid = oneSong['mid']
header = {
'origin': 'https://y.qq.com',
# 请求来源,本案例中其实是不需要加这个参数的,只是为了演示
'referer': 'https://y.qq.com/n/yqq/song/'+ str(MusicMid)+'.html',
# 请求来源,携带的信息比“origin”更丰富,本案例中其实是不需要加这个参数的,只是为了演示
'user-agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.142 Safari/537.36'
# 标记了请求从什么设备,什么浏览器上发出
}
param = {
'nobase64': '1',
'musicid': str(MusicID),
'-': 'jsonp1',
'g_tk': '5381',
'loginUin': '0',
'hostUin': '0',
'format': 'json',
'inCharset': 'utf8',
'outCharset': 'utf - 8',
'notice': '0',
'platform': 'yqq.json',
'needNewCode': '0'
}
songurl = 'https://c.y.qq.com/lyric/fcgi-bin/fcg_query_lyric_yqq.fcg'
songRes = requests.get(songurl,headers = header,params=param)
songfont = songRes.json()
fontstr = re.sub("[A-Za-z0-9\!\%\[\]\,\。#&;]", " ", songfont['lyric'])
fontstr1 = ",".join(fontstr.split())
font[str(MusicName)] = fontstr1
print(font)