Python小实战——原生爬虫
前言:在网络无处不在的今天,大数据的分析与提取也逐渐发展了起来。现在我们使用Python来做一个原生爬虫的小案例——爬取斗鱼直播平台分区下推荐视频播放量的排名,通过这个案例可以回顾前面所学的正则表达式等知识。
原生爬虫步骤:
1.模拟请求
2.用标签定位并提取数据(重点是正则表达式的编写)
3.数据精炼
4.业务处理
一.模拟请求
-
建立Spider类
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15from urllib import request
class Spider():
url = "https://www.douyu.com/g_LOL"
def __fetch_content(self):
r = request.urlopen(Spider.url)
htmls = r.read()
#此处断点调试
def go(self):
self.__fetch_content()
spider = Spider()
spider.go()调试结果
可以看出,需要对htmls进行转码:
1
htmls = str(htmls,encoding='utf-8')
再次调试后报错:
网上查阅资料后发现,是因为:
1
以"b’\x1f\x8b\x08"开头的 ,说明它是gzip压缩过的数据,这也是报错的原因,所以我们需要对我们接收的字节码进行一个解码操作。
修改代码如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21from urllib import request
from io import BytesIO
import gzip
class Spider():
#需要爬虫的URL
url = "https://www.douyu.com/g_LOL"
def __fetch_content(self):
r = request.urlopen(Spider.url)
#获取HTML字节码
htmls = r.read()
buff = BytesIO(htmls)
f = gzip.GzipFile(fileobj=buff)
result = f.read().decode('utf-8') #解码
def go(self):
self.__fetch_content()
spider = Spider()
spider.go()调试结果:
可以看到,已经爬取到了网页的HTML数据
-
上面部分可能会遇到的错误与解决方法
-
urllib.error.URLError: urlopen error [SSL: CERTIFICATE_VERIFY_FAILED]
1
2
3
4# 全局取消证书验证
import ssl
ssl._create_default_https_context = ssl._create_unverified_context
-
二.定位数据与提取、业务处理
-
第一步:观察游览器内HTML数据,尽可能选择闭合标签
如上图所示,我定位到了包含了主播名字、播放量的数据的div标签
-
第二步:编写正则表达式,抽取div标签
1
2root_pattern = '<div class="DyListCover-info">[\s\S]*?</div>'
#使用re.findall方法匹配取得一个列表后,打印其中一个元素验证是否获取成功
可以看到,我们成功获取了主播"芜湖大司马"的一个视频播放量"224.9万",但还需要精确提取
-
第三步:在div标签中抽取数据
1
2#在正则表达式中加入组()标签,即可取出中间内容
root_pattern = '<div class="DyListCover-info">([\s\S]*?)</div>'写名字、播放量的正则表达式(根据有规律的标签定位)
1
2name_pattern = '<use xlink:href="#icon-user_c95acf8"></use></svg>([\s\S]*?)</h2>'
number_pattern = '</use></svg>([\s\S]*?)</span><h2 class="DyListCover-user is-template">'然后调用函数进行匹配
1
2
3
4
5
6
7
8
9
10def __analysis(self, htmls):
root_html = re.findall(Spider.root_pattern, htmls)
anchors = []
for html in root_html:
name = re.findall(Spider.name_pattern, html)
number = re.findall(Spider.number_pattern, html)
if name!=[]:
anchor = {'name':name, 'number':number}
anchors.append(anchor)
return anchors匹配并打印anchors结果如下
可以看到,我们已经成功抓取出这部分数据了
-
第四步:数据精炼
1
2
3
4
5
6def __refine(self, anchors):
l = lambda anchor: {
'name':anchor['name'][0].strip(), #strip()为python内置函数
'number':anchor['number'][0] #用于去除字符串前后空格
}
return map(l, anchors) -
第五步:业务处理(排序)
1
2
3
4
5
6
7
8
9
10
11
12def __sort(self, anchors):
anchors = sorted(anchors,key=self.__sort_seed,reverse=True) #第二个参数为key,指定比较大小的元素,第三个参数reverse可调整顺序或倒序排序
return anchors
def __sort_seed(self, anchor):
r = re.findall('\d*',anchor['number'])
number = float(r[0])
if '万' in anchor['number']: #将万转换为10000
number *= 10000
return number -
第六步:打印数据
1
2
3
4
5def __show(self, anchors):
# for anchor in anchors:
# print(anchor['name'] + "-----" + anchor['number'])
for rank in range(0,len(anchors)):
print('rank' + str(rank+1) + ': ' + anchors[rank]['name']+' '+ anchors[rank]['number'])结果:
以上就是简单的使用Python原生爬虫的一个小案例,虽然成功爬取,但是代码复用性较差(比如只能爬取斗鱼某个区的视频播放量,如果更换其他直播平台要重写正则表达式),可以考虑使用框架(如Scrapy)。
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 515code-实验室!
评论