最近学习了一大堆和大数据相关的东西,Hadoop、Elastic、Python等。写一个简单的实战项目贯通一下。爬取一下某牙直播平台的人气排行。
一.确定自己需要的数据,并找到最适合爬取的页面
首先我们需要找到最适合爬取的页面。一般而言最好是一个展示列表。在这个爬虫,最适合的页面肯定是游戏分类页面。
二.分析数据所在的标签
用浏览器的开发者调试工具,可以很方便的查看标签信息。在选取标签的时候,我们最好遵循两个原则:
我们需要的是,主播名和观看人数标签,这两个标签被一个打的 li 标签所包含。不难发现每一个 li 包含一个主播的信息。隐藏这正是我们需要的信息。
三.模拟http获取服务器返回的html
分析完页面数据,终于可以开始编写爬虫代码了。
url = 'https://www.huya.com/g/wzry'
headers = {
'cookie': 'Hm_lvt_51700b6c722f5bb4cf39906a596ea41f=1564389526; __yasmid=0.40853709224889045; __yamid_tt1=0.40853709224889045; __yamid_new=C88A54814D100001D1791CD16F0019D9; _yasids=__rootsid%3DC88A54814DB0000113A7D4A71FB71BBD; PHPSESSID=vbo6lo3mjm62rmrc3hpe4o03s0; Hm_lpvt_51700b6c722f5bb4cf39906a596ea41f=1564389529; udb_passdata=3; SoundValue=0.50; alphaValue=0.80; isInLiveRoom=true',
'User-Agent': "Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/73.0.3683.103 Safari/537.36"
}
@staticmethod
def __fetch_content(self):
'''
执行网页访问
'''
req = request.Request(Spider.url, None, Spider.headers)
r = request.urlopen(req)
htmls = r.read()
htmls = str(htmls, encoding='utf-8')
return htmls
四.用正则表达式提取我们需要的信息
现在正常情况,我们可以获取到页面的html代码。如果有获取不到的情况,还是网站反爬虫方面的限制。这里就不做过多研究了。
那么如何从上千行代码中提取到自己需要的数据呢?这里就需要借助强大的正则匹配了。
上面我们分析了,我们需要获取的是 这个为开头的标签,因此正则表达式不容易就设置为
然后正常情况下,我们需要对获取的每组 li 内部的元素,再进行正则匹配,提取我们需要的数据。然而在这次的爬虫中,对方使用了接口,动态获取数据。无法通过标签获取数据,但是我们可以直接获取返回的 json 数据,然后转成dict。进行筛选处理。
root_pattern = '(?<=var LIST_DATA =).*?](?=;)'
def __analysis(self, htmls):
'''
正则匹配页面数据标签
'''
html = re.findall(Spider.root_pattern, htmls)
html = html[0].strip("'")
html = html.strip(" ")
# json转码
return json.loads(html)
五.存储和展示数据
sorted()
函数,可以很轻松的实现这个功能。贴上所有代码:
from urllib import request
import re
import json
class Spider():
url = 'https://www.huya.com/g/wzry'
root_pattern = '(?<=var LIST_DATA =).*?](?=;)'
headers = {
'cookie': 'Hm_lvt_51700b6c722f5bb4cf39906a596ea41f=1564389526; __yasmid=0.40853709224889045; __yamid_tt1=0.40853709224889045; __yamid_new=C88A54814D100001D1791CD16F0019D9; _yasids=__rootsid%3DC88A54814DB0000113A7D4A71FB71BBD; PHPSESSID=vbo6lo3mjm62rmrc3hpe4o03s0; Hm_lpvt_51700b6c722f5bb4cf39906a596ea41f=1564389529; udb_passdata=3; SoundValue=0.50; alphaValue=0.80; isInLiveRoom=true',
'User-Agent': "Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/73.0.3683.103 Safari/537.36"
}
@staticmethod
def __fetch_content(self):
'''
执行网页访问
'''
req = request.Request(Spider.url, None, Spider.headers)
r = request.urlopen(req)
htmls = r.read()
htmls = str(htmls, encoding='utf-8')
return htmls
def __analysis(self, htmls):
'''
正则匹配页面数据标签
'''
html = re.findall(Spider.root_pattern, htmls)
html = html[0].strip("'")
html = html.strip(" ")
# json转码
return json.loads(html)
def __refine(self, anchors):
'''
精炼数据
'''
datas = []
for anchor in anchors:
data = {
'name' : anchor['nick'],
'number' : anchor['totalCount']
}
datas.append(data)
return datas
def __sort(self, anchors):
# 数据排序
anchors = sorted(anchors, key=self.__sort_sedd, reverse = True)
return anchors
def __sort_sedd(self, anchor):
# 排序处理
return int(anchor['number'])
def __show(self, anchors):
'''
展示排行榜数据
'''
for anchor in anchors:
print(anchor['name'] + '----' + anchor['number'] + '人')
def go(self):
'''
入口方法
'''
htmls = self.__fetch_content(self)
anchors = self.__analysis(htmls)
anchors = self.__refine(anchors)
anchors = self.__sort(anchors)
self.__show(anchors)
spider = Spider()
spider.go()
贴上整个过程简单的思维导图( 后续还会更新 )