QQ音乐评论
有些小伙伴反馈,对于爬虫的完整流程,还是不清楚,这边就按顺序,给大家梳理一下
反爬
首先查看一下,我们要爬取的网页,是否反爬(各种侵害人家服务器的事情,我们不能干)
QQ音乐网址:https://y.qq.com
要查看该网页的反爬要求,可以直接在网页后加/robots.txt
QQ音乐反爬要求就是:https://y.qq.com/robots.txt
看了一下官网不给爬的内容,没有说不可以爬评论,那我们就爬了~
今天我们爬虫,以QQ音乐,杨千嬅的《野孩子》为例,爬取评论
查看网页源代码
给大家回顾以下,静态网页是怎么爬取的?
1、用requests.get获取数据
2、确定网页返回码是200
3、查看一下数据,你要的数据,是不是都出来了
4、解析一下数据,用beautifulsoup库、正则化表达、字符串切割等方法处理数据
5、把数据保存下来
根据我们之前的操作,我们会先右击看一下网页源代码。
如果我们要的内容,就在源代码里面,那万事大吉,直接按照我们之前爬豆瓣的那一套来
但是我们爬QQ音乐的时候,很悲伤的发现,网页源代码里面,没有数据了!!!
(只有一大堆看不懂的英文,连个中文字都没了!)
怎么办呢?我们去找,这个评论数据在哪里
获取网址
现在我们去找数据,和数据对应的网址
XHR
XHR 全称 XMLHttpRequest,它是浏览器内置的对象,使得 JavaScript 可以发送 HTTP 请求。
我们先右击打开“审查元素”,勾选Network—>勾选XHR—>查找我们要的内容
理论上,我们可以双击Name列表中的链接,一个一个找
有个小技巧,包含评论数据的东西,应该是比较大的,不至于只有几个B
所以我们翻了一下,发现有个链接有8.8KB,感觉相对大一点,我们打开链接看一下
看到了comment。没错,是了,数据就在里面
可以看到,这里面就包含了昵称、评论等内容
敏感一点的同学可以意识到,这其实就是一个字典啊!
我们点会到Headers,看一下这个网址,网址的获取方式是GET
我们先用这个网址,发现这时候,就已经包含评论数据了
import requests
headers = {
'user-agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.100 Safari/537.36'
}
res = requests.get('https://c.y.qq.com/base/fcgi-bin/fcg_global_comment_h5.fcg?g_tk_new_20200303=5381&g_tk=5381&loginUin=0&hostUin=0&format=json&inCharset=utf8&outCharset=GB2312¬ice=0&platform=yqq.json&needNewCode=0&cid=205360772&reqtype=2&biztype=1&topid=1406731&cmd=8&needmusiccrit=0&pagenum=0&pagesize=25&lasthotcommentid=&domain=qq.com&ct=24&cv=10101010', headers=headers)
print(res.text)
参数
然后我们来重写这个网址,其实网址后面那一串参数,在Query String Parameters
把网址写法改一下,参数加上去
import requests
headers = {
'user-agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.100 Safari/537.36'
}
params = {
'g_tk_new_20200303': '5381',
'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': '1406731',
'cmd': '8',
'needmusiccrit': '0',
'pagenum':'0',
'pagesize': '25',
'lasthotcommentid': '',
'domain': 'qq.com',
'ct': '24',
'cv': '10101010'
}
res = requests.get('https://c.y.qq.com/base/fcgi-bin/fcg_global_comment_h5.fcg', headers=headers, params=params)
print(res.text)
处理数据
JSON
JSON(JavaScript Object Notation)是一种轻量级的数据交换格式。 它的本质,是一个字符串,然后里面可能是字典,也可能是列表。
# 字典
dict = {'pagesize': 25}
# JSON
json = '{"pagesize": 25}'
# 列表
list = ['x', 'y', 'z']
# JSON
json = '["x", "y", "z"]'
我们需要用.json()来转换
为什么需要转换,而不是直接就是个字典?
因为 JSON是一种通用格式,不仅适用于Python,其他语言可以用。只是在Python里,它对应的是字典和列表
data = res.json() # data是字典格式
处理字典数据,是我们熟悉的部分
for item in data['comment']['commentlist']:
print('{}:{}'.format(item['nick'], item['rootcommentcontent']))
至此,我们就把第一页的数据读出来了,完整代码如下
import requests
headers = {
'user-agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.100 Safari/537.36'
}
params = {
'g_tk_new_20200303': '5381',
'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': '1406731',
'cmd': '8',
'needmusiccrit': '0',
'pagenum':'0',
'pagesize': '25',
'lasthotcommentid': '',
'domain': 'qq.com',
'ct': '24',
'cv': '10101010'
}
res = requests.get('https://c.y.qq.com/base/fcgi-bin/fcg_global_comment_h5.fcg', headers=headers, params=params)
data = res.json()
# 这是[最新评论]列表
for item in data['comment']['commentlist']:
print('{}:{}'.format(item['nick'], item['rootcommentcontent']))
# 这是[精彩评论]列表
for item in data['hot_comment']['commentlist']:
print('{}:{}'.format(item['nick'], item['rootcommentcontent']))
翻页
经过观察,我们发现,每次翻页,Query String Parameters 里面,只有两个参数变了。
其中pagenum比较好理解,就是每一次翻页,数字加一
我们重点来找一下,lasthotcommentid 这个参数在哪里
发现这个单词,就是last hot comment id,最后一个评论的ID
因为QQ音乐有两种评论,最新评论和精彩评论,我们不确定到底是哪个ID,所以我们需要翻页确认一下
我们观察一下data['comment']和data['hot_comment'],最后发现,数据在data['comment']中
import requests
import time
headers = {
'user-agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/76.0.3809.132 Safari/537.36'
}
# 第一次 lasthotcommentid 为空
lasthotcommentid = ''
# 前五页
for pagenum in range(5):
params = {
'g_tk_new_20200303': '5381',
'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': '1406731',
'cmd': '8',
'needmusiccrit': '0',
'pagenum': pagenum,
'pagesize': '25',
'lasthotcommentid': lasthotcommentid,
'domain': 'qq.com',
'ct': '24',
'cv': '10101010'
}
res = requests.get('https://c.y.qq.com/base/fcgi-bin/fcg_global_comment_h5.fcg', headers=headers, params=params)
data = res.json()
print('==================================\n爬虫QQ音乐:{}第{}页\n=================================='.format(data['topic_name'],pagenum+1))
for item in data['comment']['commentlist']:
print('{}:{}'.format(item['nick'], item['rootcommentcontent']))
# 当前页最后一个评论的 commentid 作为下一页的 lasthotcommentid
lasthotcommentid = data['comment']['commentlist'][-1]['commentid']
# 防止爬取太快被封
time.sleep(1)
保存数据
import requests
import time
import xlwt
headers = {
'user-agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/76.0.3809.132 Safari/537.36'
}
lasthotcommentid = ''
params = {
'g_tk_new_20200303': '5381',
'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': '1406731',
'cmd': '8',
'needmusiccrit': '0',
'pagenum': 0,
'pagesize': '25',
'lasthotcommentid': lasthotcommentid,
'domain': 'qq.com',
'ct': '24',
'cv': '10101010'
}
def GetComment(headers, params):
res = requests.get('https://c.y.qq.com/base/fcgi-bin/fcg_global_comment_h5.fcg', headers=headers, params=params)
data = res.json()
return data
workbook = xlwt.Workbook()
row = 1
for pagenum in range(5):
params['pagenum'] = pagenum
params['lasthotcommentid'] = lasthotcommentid
data = GetComment(headers, params)
print('爬虫QQ音乐:{}第{}页'.format(data['topic_name'],pagenum+1))
if pagenum == 0:
sheet = workbook.add_sheet(data['topic_name'])
head = ['昵称', '评价']
for h in range(len(head)):
sheet.write(0, h, head[h])
for item in data['comment']['commentlist']:
sheet.write(row, 0, item['nick'])
sheet.write(row, 1, item['rootcommentcontent'])
row += 1
lasthotcommentid = data['comment']['commentlist'][-1]['commentid']
time.sleep(1)
workbook.save('QQ音乐评论.xls')
print('写入excel成功')