爬虫虎牙网站lol主播人气和姓名(附人气值排名新方法)
大家好,我是bd,新人小白,这是我第一次尝试将自己对于爬虫知识的一些心得分享给大家。由于是最近刚接触python,所以在学习完爬虫这个知识点后自己动手尝试了一下,对象就是虎牙lol主播姓名和人气值排名的爬取,废话不多说,直接开始。(在编写的过程中参考了作者一曲无痕奈何的避坑贴士,让自己顺利编码,感谢!附链接/qq_41479464/article/details/91048147)import refrom urllib import requestclass Spider( ):url = '/g/wzry'# 正则root_pattern = '<span class="txt">([\s\S]*?)</li>' #结尾</span>并没有包含 人气值,这种情况下需要结尾处再往下找name_pattern = '<i class="nick" title="([\s\S]*?)">([\s\S]*?)</i>' #此时会输出元组,包含两个名字,注意此处的用法number_pattern='<i class="js-num">([\s\S]*?)</i>'#获取要爬取的htmldef __fetch_content(self): #定义私密实例方法r=request.urlopen(Spider.url)#类调用类变量htmls=r.read()htmls=str(htmls,encoding='utf-8')return htmls#利用正则表达式匹配需要数据def __analysis(self,htmls):root_html=re.findall(Spider.root_pattern,htmls)anchors=[]for html in root_html:name=re.findall(Spider.name_pattern,html)#正则表达式返回列表,name列表[('姓名'),('姓名')]number=re.findall(Spider.number_pattern,html)anchor={'name':name,'number':number}anchors.append(anchor)print(anchors[0:10])return anchors#过滤重复名字以及将anchor和number里内容以字符串输出def __refine(self,anchors):l=lambda anchor:{'name':anchor['name'][0][0],'number':anchor['number'][0]}r=map(l,anchors) #map格式需要转化成list,才能输出# print(list(r))return r# 排序,按照人气值数值大小def __sort(self,anchors):anchors=sorted(anchors,key=self.__sort_seed,reverse=True)return anchors#将人气值数值取出来,作比较 单个anocherdef __sort_seed(self,anchor):r=re.findall('[\d.]*',anchor['number'])number=float(r[0])print(r,number)if ',' in anchor['number']:number=number*1000+float(r[2])print(number)if '万' in anchor['number']:number*=10000print(number)return numberdef __show(self,anchors):for rank in range(0,len(anchors)):print('rank'+':'+str(rank+1)+' '+anchors[rank]['name']+':'+anchors[rank]['number'])def go(self):htmls=self.__fetch_content() #获取爬取页面htmlsanchors=self.__analysis(htmls) #解析获取页面htmls,寻找到所需姓名和人气anchors=list(self.__refine(anchors))anchors=self.__sort(anchors)self.__show(anchors)spider=Spider()spider.go()
上述代码中有三点要和大家分享,下面一一来叙述
(1)虎牙网站主播姓名和人气值正则表达式的匹配
这是参考博主的方法,不然我就要炸了
root_pattern = '<span class="txt">([\s\S]*?)</li>' #结尾</span>并没有包含 人气值,这种情况下需要结尾处再往下找name_pattern = '<i class="nick" title="([\s\S]*?)">([\s\S]*?)</i>' #此时会输出元组,包含两个名字,注意此处的用法number_pattern='<i class="js-num">([\s\S]*?)</i>'
(2)人气值与主播姓名的提炼
从上图可以看出,在源代码中主播姓名出现了两次,因此精炼数据时值需要出现1次即可
def __refine(self,anchors):l=lambda anchor:{'name':anchor['name'][0][0],'number':anchor['number'][0]}r=map(l,anchors) #map格式需要转化成list,才能输出return r
name列表:[('姓名','姓名')],因此采用anchor['name'][0][0]提取
(3)!!!!!人气值排名!!!!
由于学习资料和查询的博主都是采用这种方式,但是我在实操的过程中出现了不能正确匹配的情况,这主要是人气值超过1000万时,在python正则表达式输出时会是[‘1’,’ ',‘000’],选择浮点数输出时只会输出‘1’,因此会出现错误。我自己想了一个更正的办法,即加入if()函数,使人气超过1000万时也可以正常显示。代码如下:
r=re.findall('[\d.]*',anchor['number'])number=float(r[0])print(r,number)if ',' in anchor['number']:number=number*1000+float(r[2])print(number)
加入该函数后可以保证人气在9999万以下正确输出,人气过亿就得重调代码了,目前主播人气在线人气还没有破亿的吧,2333。
以上就是我这个代码小白在学习python原生爬虫遇到的问题,希望分享给大家,顺利跳坑。