编写这个原生爬虫项目的3个主要目的:
1.巩固 python 基础知识
2.了解合理的编码规范和方式
3.了解爬虫基本原理
项目分析:
1.爬取网站: 熊猫TV(https://www.panda.tv/cate/lol)
2.爬虫目的: 爬取英雄联盟游戏分类下面所有主播的人气排行
3.爬虫步骤:
(1).明确要爬取的网站数据
(2).分析并了解所要爬取的网站结构,找到数据所在标签位置
(3).确定定位标签
确定定位标签原则:
①尽量选取具有唯一标识的标签
②尽量选取最接近所要提取数据的标签
③尽量选取可以闭合的标签
(4).编写代码
①通过 urllib 库模拟 http 请求, 向服务器发送这个请求, 获取到服务器返回的 html(通常会是网页完整的 html)
②用正则表达式提取需要的数据(主播的用户名、人气)
③对所爬取的数据进行清洗, 提炼出符合格式的数据
④根据业务需求对爬取到的数据进行排序
⑤展示数据
网页分析:
-
分析页面, 图中标记的两个数据分别是要爬取的用户名和观看人数
01. 爬虫所要爬取的页面
-
找到包含 "用户名和观看人数" 所在标签, 可以发现 "用户名和观看人数" 分别位于 class 为 "video-nickname" 和 "video-number" 的两个 <span> 标签中, 将 class 为 "video-info" 所在的 <div> 标签作为定位标签
02. 找到包含 "用户名和观看人数" 所在标签
03. 确定定位标签
项目完整代码:
import re
from urllib import request
class Spider(object):
"""
爬取熊猫TV 网站英雄联盟游戏分类下面所有主播的人气排行
"""
# 用类变量 url 来保存所要爬取的网页的地址
url = "https://www.panda.tv/cate/lol"
# 定义所需的正则匹配模式
root_pattern = '<div class="video-info">([\s\S]*?)</div>'
name_pattern = '</i>([\s\S]*?)</span>'
number_pattern = '<span class="video-number">([\s\S]*?)</span>'
def __fetch_content(self):
"""
获取网页内容
"""
# 用变量 r 来保存通过 request 请求网址所返回的 response 对象
r = request.urlopen(Spider.url)
# 用 read 方法读取出 r 对象的数据, 并将得到的 html 数据赋值给 htmls 变量
htmls = r.read()
# 因为通过 r.read() 获取的 htmls 是 bytes(字节码),
# 而我们最终想要获取 str(字符串), 所以这里需要转码
htmls = str(htmls, encoding="utf-8")
return htmls
def __analysis(self, htmls):
"""
分析并提取所要爬取的数据
"""
# 利用正则匹配出定位标签里的数据
root_htmls = re.findall(Spider.root_pattern, htmls)
# anchors 列表用来存储所要提取的数据
anchors = []
for html in root_htmls:
# 利用正则将定位标签里获取的数据再次匹配, 提取出用户名和观看人数
name = re.findall(Spider.name_pattern, html)
number = re.findall(Spider.number_pattern, html)
# 将用户名和观看人数组装成字典
anchor = {"name": name, "number": number}
anchors.append(anchor)
return anchors
def __refine(self, anchors):
"""
数据精炼, 对数据进行清洗
"""
for anchor in anchors:
anchor["name"] = anchor["name"][0].strip()
anchor["number"] = anchor["number"][0].strip()
return anchors
def __sort(self, anchors):
"""
对数据进行排序
"""
anchors = sorted(anchors, key=self.__sort_seed, reverse=True)
return anchors
def __sort_seed(self, anchor):
"""
排序方法 __sort 的种子方法, 可以通过此方法来确定排序依据
"""
r = re.findall("\d*", anchor["number"])
number = float(r[0])
if "万" in anchor["number"]:
number *= 10000
return number
def __show(self, anchors):
"""
打印数据
"""
for rank in range(0, len(anchors)):
print("rank %s: %s %s" % (rank+1, anchors[rank]["name"], anchors[rank]["number"]))
def go(self):
"""
入口方法(总控方法), Spider 类内部所有方法的调用都通过 go 方法来调用
"""
htmls = self.__fetch_content()
anchors = self.__analysis(htmls)
anchors = self.__refine(anchors)
anchors = self.__sort(anchors)
self.__show(anchors)
spider = Spider()
spider.go()
测试代码:

网友评论