今天利用抓包工具Charles进行抓取腾讯视频的评论,遇到了一个bug,查了好久资料才发现错误原因,?
先上代码
import re
import urllib.request
import ssl
#导入正则、urllib、以及ssl证书验证需要的模块
ssl._create_default_https_context = ssl._create_unverified_context
#免除ssl证书验证
headers={"User-Agent":"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/72.0.3626.119 Safari/537.36","Referer":"https://v.qq/x/cover/w0d9o4gnr8y0ghl/j00305uwiu1.html"}
#伪装浏览器,referer 为视频链接地址
url='https://v.qq/x/cover/w0d9o4gnr8y0ghl/j00305uwiu1.html'
#视频地址(播放地址,不是包里抓的评论地址)
response=urllib.request.Request(url,headers=headers)
#构建完整请求,否则评论地址的referer判定来源不为母页播放地址,无法访问评论地址
抓包过程不再详细写了,网上都有,讲一下腾讯视频评论地址的构成吧
commentid="6508316077385253890"
#每个地址在“&cursor=”后面有一串数字,每次这个数字对应着评论页的下一页
url_comment="https://video.coral.qq/varticle/3751274875/comment/v2?callback=_varticle3751274875commentv2&orinum=10&oriorder=o&pageflag=1&cursor="+commentid+"&scorecursor=0&orirepnum=2&reporder=o&reppageflag=1&source=132&_=1551849488843"
#这是我随便点击的一个电视剧网页的评论地址(用过抓包抓取)
每一次的last对应的数字就是下一页的评论id,而first对应的数字就是本页评论的id,所以爬取的大概思路就是:
1、获取第一页评论地址(已经有了)
2、设置正则、爬取第一页的所有评论
3、通过获取第一页的last,自动生成下一页的评论地址
4、重复123(利用for 循环)爬取每一页的评论
代码如下:
for i in range(0,50): #可以自己设置爬多少页
data_page=urllib.request.urlopen(url_comment).read().decode("utf-8")
next_pat='"last":"(.*?)"' #设置下一页的正则表达式
nextid=repile(next_pat).findall(data_page)[0]
#取出第一个last,其实也只有一个
pat='"content":"(.*?)"' #设置评论的正则表达式
data=repile(pat).findall(data_page)
for j in range(0,len(data)):
print("第{}-{}条评论是:".format(i,j))
print(eval("u"+"\'"+data[j]+"\'")) #源码评论是unicode,所以先用u将data的数据编码,再用eval函数将字符串输出出来
#上面这条print输出评论语编写没有错误,但是在执行时会出现错误,后面会说
url_comment="https://video.coral.qq/varticle/3751274875/comment/v2?callback=_varticle3751274875commentv2&orinum=10&oriorder=o&pageflag=1&cursor="+nextid+"&scorecursor=0&orirepnum=2&reporder=o&reppageflag=1&source=132&_=1551849488843"
执行的时候发现
错误原因:
Exception has occurred: UnicodeEncodeError
‘utf-8’ codec can’t encode characters in position 9-10: surrogates not allowed
当时以为是解码出问题,然后在decode()里加了“utf-8”没有用,又加了"ignore"还是报错
其实最好任何情况都加上ignore,防止爬虫崩溃
data_page=urllib.request.urlopen(url_comment).read().decode("utf-8","ignore")
继续报错,再改,开头添加
# -*- coding: utf-8 -*-
还是报错。。。
然后查各种资料发现,不是这个原因,decode就算不加utf-8,print语句也能执行成功
没错,不管怎么修改print中的,还是decode,每次爬取都是到第4条评论报错了
查了很多资料,发现了加入了try 后可以解决崩溃
try:
print(eval("u"+"\'"+data[j]+"\'"))
except UnicodeEncodeError as e:
print(e)
把第四条的评论源码找出来了
\u8ddf\u9aa8\u8bed\u6bd4\u54ea\u4e2a\u5bb3\u6015 \ud83d\ude31
>>> u"\u8ddf\u9aa8\u8bed\u6bd4\u54ea\u4e2a\u5bb3\u6015 \ud83d\ude31"
'跟骨语比哪个害怕 \ud83d\ude31'
原来是后面的\ud83d\ude31编码失败了,上网一查发现这家伙原来是个emoji,是个表情啊 = =汗
完整代码奉上:
import re
import urllib.request
import ssl
ssl._create_default_https_context = ssl._create_unverified_context
headers={"User-Agent":"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/72.0.3626.119 Safari/537.36","Referer":"https://v.qq/x/cover/w0d9o4gnr8y0ghl/j00305uwiu1.html"}
url='https://v.qq/x/cover/w0d9o4gnr8y0ghl/j00305uwiu1.html'
response=urllib.request.Request(url,headers=headers)
commentid="6508316077385253890"
url_comment="https://video.coral.qq/varticle/3751274875/comment/v2?callback=_varticle3751274875commentv2&orinum=10&oriorder=o&pageflag=1&cursor="+commentid+"&scorecursor=0&orirepnum=2&reporder=o&reppageflag=1&source=132&_=1551849488843"
for i in range(0,50):
data_page=urllib.request.urlopen(url_comment).read().decode("utf-8","ignore")
next_pat='"last":"(.*?)"'
nextid=repile(next_pat).findall(data_page)[0]
pat='"content":"(.*?)"'
data=repile(pat).findall(data_page)
for j in range(0,len(data)):
print("第{}-{}条评论是:".format(i,j))
try:
print(eval("u"+"\'"+data[j]+"\'"))
except UnicodeEncodeError as e:
print(e)
url_comment="https://video.coral.qq/varticle/3751274875/comment/v2?callback=_varticle3751274875commentv2&orinum=10&oriorder=o&pageflag=1&cursor="+nextid+"&scorecursor=0&orirepnum=2&reporder=o&reppageflag=1&source=132&_=1551849488843"
可以改进的地方很多,被一个表情搞的人都不好了,懒得优化了
最后请教下,有大神知道上面代码中,unicode编码成汉字的时候怎样可以过滤掉emoji表情?
更多推荐
Python3 爬取腾讯视频评论,及UnicodeEncodeError:'utf-8' codec can't encode和s
发布评论