思路解析:

  1、我们需要明确爬取数据的目的:为了按热度查看主播的在线观看人数

  2、浏览网页源代码,查看我们需要的数据的定位标签

  3、在代码中发送一个http请求,获取到网页返回的html(需要注意的是,许多网页都有反爬虫机制,所以需要在请求中添加user-agent,伪装成客户端访问)

  4、对获取到的html进行分析,使用正则表达式提取我们需要的部分(需要注意的是要把主播名称和观看人数所在的块整个提取,分别提取的话如果网页设计不规律的话很难对应)

  5、将得到的单个主播的数据存储在字典中,并把所有主播的数据存储在list中

  6、如果抓取到的数据中包含空格换行等无用字符,还需要对数据进行精炼。

  7、对抓取到的数据从大到小进行排序(需要注意的是:我们抓取到的数据是字符串,并且单位可能是人或者万人,所以要对观看人数进行处理)

  8、将排好序的数据遍历输出。

由于斗鱼网站的网页是采用模板实现的,案例是抓取王者荣耀的主播的数据,想抓取别的类目的话,只需要修改url即可~

代码实现:

'''
爬取斗鱼网站的王者荣耀分类主播的观看人数和主播名字,并按热度排名
'''
from urllib import request
from io import BytesIO
import gzip
import re class Spider():
url = 'https://www.douyu.com/g_wzry' # 根节点的字符串匹配正则表达式,匹配除了根节点中间的所有字符,非贪婪模式,找到第一个</div>就结束
root_pattern = '<div class="DyListCover-info">([\s\S]*?)</div>' headers = {'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/71.0.3578.80 Safari/537.36'} # 观看人数匹配字符串
number_pattern_str = '<span class="DyListCover-hot is-template">([\s\S]*?)</span>'
# 观看人数的字符串,删除前面的icon部分
number_pattern = '<svg><use xlink:href="#icon-hot_8a57f0b"></use></svg>' name_pattern_str = '<h2 class="DyListCover-user is-template">([\s\S]*?)</h2>'
name_pattern = '<svg><use xlink:href="#icon-user_c95acf8"></use></svg>' # 抓取自定网页内容并解码
def __fetch_content(self):
# 发送一个http的请求,获取返回的html代码
req = request.Request(Spider.url, headers=Spider.headers)
htmls = request.urlopen(req).read() # 解码
buff = BytesIO(htmls)
f = gzip.GzipFile(fileobj=buff)
htmls = f.read().decode('utf-8')
return htmls # 分析抓取内容,选取标签时尽量选取闭合标签,标签成组的选择好对应
def __analysis(self, htmls):
# 获取到需要的全部数据
root_html = re.findall(Spider.root_pattern, htmls)
# 由于网页中一个块有两个相同的class类,其中第一个主播介绍
# 第二个才是需要的数据,所以选取奇数下标元素
root_info_html = root_html[1::2] # 最后获取到的数据列表
anchors = []
# 遍历列表,提取用户名和观看人数
for html in root_info_html:
# 提取到的是带icon的部分
watch_num_str = re.findall(Spider.number_pattern_str, html)
# 剔除icon部分
watch_num = re.sub(Spider.number_pattern, '', watch_num_str[0]) # 提取带icon的name的部分
name_str = re.findall(Spider.name_pattern_str, html)
name = re.sub(Spider.name_pattern, '', name_str[0]) # 将名字和观看人数用字典存储,最后再用列表存储每个主播的数据
anchor = {'name': name, 'number': watch_num}
anchors.append(anchor) return anchors # 精炼函数
# def __refine(self, anchors):
# lam = lambda anchor: {'name': anchor['name'][0], 'number': anchor['number'][0]}
# return map(lam, anchors) # 排序
def __sort(self, anchors):
anchors = sorted(anchors, key=self.__sort_key, reverse=True)
return anchors # 排序规则
def __sort_key(self, anchor):
# 提取数字并计算
r = re.findall('\d*', anchor['number'])
number = float(r[0])
if '万' in anchor['number']:
number *= 10000
return number # 显示数据
def __show(self, anchors):
# for anchor in anchors:
# print(anchor['name'], ':', anchor['number'])
for rank in range(0, len(anchors)):
print("Rank ", rank+1, ": ", anchors[rank]['name'], " ", anchors[rank]['number']) # 入口方法
def go(self):
htmls = self.__fetch_content()
anchors = self.__analysis(htmls)
anchors = self.__sort(anchors)
self.__show(anchors) spider = Spider()
spider.go()

  

最新文章

  1. CoreData __ 基本原理
  2. Ubuntu14.04环境下Samba报错排错过程
  3. Hadoop第5周练习—MapReduce计算气象温度等例子
  4. 受限玻尔兹曼机(RBM)学习笔记(七)RBM 训练算法
  5. Python全栈开发之MySQL(三)视图,存储过程触发器,函数,事务,索引
  6. 去掉MySQL字段中的空格
  7. avi格式详细介绍
  8. mysql数据库定时备份
  9. ibatis 参数和结果的映射处理
  10. charles支持https抓包配置
  11. 9.5、Libgdx加速度计
  12. 【easy】215. Kth Largest Element in an Array 第K大的数
  13. Linux上的文件查找工具之locate与find
  14. Linux常用基础操作命令大全(超实用精心整理)
  15. KVM -&gt; 虚拟机在线热添加技术_04
  16. HTML Viewer展示不同字体
  17. jQuery的ready()事件与js中的onload事件的区别
  18. CentOS 7.0 Firewall防火墙配置
  19. 【Struts2】Struts2与Spring整合后,如何指定Action为多例模式
  20. python常用模块及面向对象(一)

热门文章

  1. Chaoter07 面向对象 (Object)
  2. 0x01 向日葵日志溯源
  3. VS Code远程链接报错Could not establish connection to “hz.matpool.com”
  4. Ghost:凛冬散尽,长夜终明
  5. ELKB-ElasticSearch-Logstash-Kibana-beats 个人理解
  6. win server 2012下安装IIS 8后配置ASP网站的注意事项
  7. 程序语言与编程实践2-&gt; 蓝桥杯C/C++备赛记录1 | 入门了解与首周训练
  8. [源码解析] TensorFlow 分布式环境(2)---Master 静态逻辑
  9. SQL Server2012安装教程
  10. Spring系列26:Spring AOP 通知与顺序详解