今天利用抓包工具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