Chapter05 | 抓取策略与爬虫持久化
互联网中的网络之间互相连接,构成一个巨大的网络图:
网络爬虫就是从这个巨大复杂的网络体中,根据给定的策略,抓取所需要的内容
实例代码如下:
import requests,re
# import time
# from collections import Counter
count = 20
r = re.compile(r'href=[\'"]?(http[^\'">]+)')
seed = 'https://www.baidu.com/more/'
queue = [seed]
used = set() # 设置一个集合,保存已经抓取过的URL
storage = {}
while len(queue) > 0 and count > 0 :
try:
url = queue.pop(0)
html = requests.get(url).text
storage[url] = html #将已经抓取过的URL存入used集合中
used.add(url)
new_urls = r.findall(html) # 将新发行未抓取的URL添加到queue中
print(url+"下的url数量为:"+str(len(new_urls)))
for new_url in new_urls:
if new_url not in used and new_url not in queue:
queue.append(new_url)
count -= 1
except Exception as e :
print(url)
print(e)
我们可以感受下一个一级网页到下一级网页的链接能有多么多
一、抓取策略
从网络爬虫的角度来看,整个互联网可以划分为:
- 在网络爬虫的组成部分中,待抓取URL队列是最重要一环
- 待抓取队列中的URL以什么样的顺序排列,这涉及到页面抓取的先后问题
- 决定待抓取URL排列顺序的方法,成为抓取策略
- 网络爬虫使用不同的抓取策略,实质是使用不同的方法确定待抓取URL队列中URL的先后顺序
- 爬虫的多种抓取策略目标基本一致:优先抓取重要的网页
- 网页的重要想,大多数采用网页的流动性来进行度量
1、数据抓取策略
- 非完全PageRank策略
- OCIP策略
- 大站优先策略
- 合作抓取策略
- 图遍历算法策略
1.1、非完全PageRank策略
-
PageRank
算法,是一种著名的超链接分析算法,用来进行网页排名,以谷歌创始人Larry Page
命名 -
PageRank策略算法基于以下的思想对网页的重要性进行评分:
①一个网页被很多其他网页链接,该网页比较重要,PageRank分数回相对较高
② 一个PageRank
分数高的网页链接到一个其他的网页,被链接到的网页的PageRank
分数会相应提高
通常来讲,一个网页的PageRank分数计算如下:
- PageRank算法计算的对象是整个互联网页面的集合;而非完全PageRank策略则关注的是以下的页面集合:
①网络爬虫已经下载的页面
②待抓取URL队列的URL - 之后由两者组成的页面子集中,计算PageRank分数
- 根据PageRank分数,按照从高到低的顺序,将待抓取URL队列重排,形成新的待抓取URL队列
1.2、OPIC策略
OPIC
,是Online Page Importance Computation
的缩写,是一种改进的PageRank
算法
OPIC策略的基本思想
- 将互联网的页面初始cash值设为1/N
- 每当网络爬虫下载页面a,将a的cash值平均分配给页面中包含的链接,再将自己的cash值设为零
- 将待抓取URL队列中的URL按照cash值进行降序排列,优先处理cash值高的网页
1.3、大站优先策略(比较粗暴)
大站优先策略的思路简单明了:
- 依据网站决定网页重要性,对于待爬取URL队列中的网页根据所属网站归类
- 等待下载的页面最多的网站,会得到网络爬虫的“优先考虑”
“大战”通常具有以下特点:
- 稳定的服务器,良好的网站结构
- 优秀的用户体验,及时的咨询内容
- 权威的相关资料,丰富的内容类型
- 海量的网页数,高质量的外链
如何识别要抓取的目标网站是否为大战?
- 人工整理大站名单,通过已知的大站发现其他大站
- 根据大站的特点,对将要爬取的网站进行评估(架构,内容,传播速度等)
1.4、合作抓取策略(需要一个规范的URL地址)
为了提高抓取网页的速度,常见的选择是增加网络爬虫的数量
如何给这些爬虫分配不同的工作量,确保独立分工,避免重复爬取,这是合作抓取策略的目标
合作抓取策略通常使用以下两种方式:
- 通过服务器的IP地址来分解,让爬虫仅抓取某个地址段的网页
- 通过网页域名来分解,让爬虫仅抓取某个域名段的网页
1.5、图的遍历算法策略
图的遍历算法主要分成两种:
- 深度优先(DFS,Depth First Search)
- 广度优先(BFS,Breadth First Search)
1、深度优先
深度优先从根节点开始,沿着一条路径尽可能深地访问,直到遇到叶节点时才回溯
- 深度优先由自己的优点,但更容易陷入无限循环
2、广度优先
使用广度优先策略的原因:
- 重要的网页往往离种子站点距离较近
- 互联网的深度没有那么深,但却出乎意料地宽广
广度优先遍历策略地基本思路
- 将新下载网页中发现的链接直接插入待抓取URL队列的末尾。也就是指网络爬虫会先抓取起始网页中链接的所有网页
- 再选择其中一个链接网页,继续抓取在此网页中链接的所有网页
广度优先策略从根节点开始,尽可能访问离根节点最近的节点
3、代码实现
用list模拟队列,实现BFS算法:
import requests,re
count = 20
r = re.compile(r'href=[\'"]?(http[^\'">]+)')
seed = 'http://httpbin.org/'
queue = [seed]
storage = {}
while len(queue) > 0 and count > 0 :
try:
url = queue.pop(0)
html = requests.get(url).text
storage[url] = html #将已经抓取过的URL存入used集合中
used.add(url)
new_urls = r.findall(html) # 将新发行未抓取的URL添加到queue中
print(url+"下的url数量为:"+str(len(new_urls)))
for new_url in new_urls:
if new_url not in used and new_url not in queue:
queue.append(new_url)
count -= 1
except Exception as e :
print(url)
print(e)
用list模拟队列,实现DFS算法:
import requests,re
count = 20
r = re.compile(r'href=[\'"]?(http[^\'">]+)')
seed = 'http://httpbin.org/'
queue = [seed]
storage = {}
while len(stack) > 0 and count > 0 :
try:
url = stack.pop(-1)
html = requests.get(url).text
new_urls = r.findall(html)
stack.extend(new_urls)
print(url+"下的url数量为:"+str(len(new_urls)))
storage[url] = len(new_urls)
count -= 1
except Exception as e :
print(url)
print(e)
统计:
真的会陷入无限循环吗?
- 我们发现其中包含了一些重复的URL
- 重复时因为网页的链接形成一个闭环
- 要标记已经抓取过的URL,防止浪费无谓的资源
2、数据更新策略
- 抓取策略关注待抓取URL队列,也就是互联网中的待下载页面的合集
- 针对已下载的网页来说,互联网实时变化,页面随时会有变化
- 更新策略决定何时更新之前已经下载过的页面
常见的更新策略有以下几种:
- 历史参考策略:根据页面历史数据,预测页面的变化
- 用户体验策略:总和用户的浏览偏好,更新用户关注度高的网页
- 聚类抽样策略:根据页面的类别,确定页面的更新周期
聚类策略的基本思路
二、爬虫持久化
持久化方法:
- 依赖URL管理的数据结构
- 依赖爬虫爬取策略
- 依赖爬虫的更新策略
- 依赖临时存储和永久存储