第一节:理解网络爬虫
1.1网络爬虫的定义
网络爬虫(又被称为网页蜘蛛,网络机器人)就是模拟浏览器发送网络请求,接收请求响应,一种按照一定的规则,自动地抓取互联网信息的程序。另外一些不常使用的名字还有蚂蚁、自动索引、模拟程序或者蠕虫。
原则上,只要是浏览器(客户端)能做的事情,爬虫都能够做。
当今最大的网络是互联网,最大的爬虫就是各类搜索引擎,包括谷歌丶百度等。网络爬虫就是按照一定规则去爬去人类所需要的信息的程序,主要通过对URL的请求来实现。一般来说,从搜索引擎这类爬虫搜索到的信息是非常宽泛的,而且夹杂着各种广告,信息是不纯粹的,也有可能不是我们需要的。这种时候,就需要一些聚焦于某一方面信息的爬虫来为我们服务,比方说,专门爬取某一类书的信息,在网站上浏览的时候,可能会有形形色色的图片和一些其他信息干扰我们,如果编写网络爬虫的话,就可以单单把自己想要的信息存储下来,以便数据分析,提取有用的信息。
像我们平时用的,谷歌浏览器、火狐浏览器、IE浏览器等,这些浏览器不是搜索引擎,主要的作用是:渲染我们的这些网页。
其实,这个浏览器和我们平时写的小爬虫最大的区别就是:我们平时的小爬虫抓取的网页源代码的不渲染的,直接把网页的源代码 HTML 展现出来,而浏览器是会加载 HTML 相关的 CSS、JS 等。爬虫是不会执行这些关联的文件。
1.2网络爬虫的原理
我们写了一个简单的网络爬虫,
实际上也就是利用python的一些第三方库,来模拟浏览器的一个 get 请求。
比如你 get 了一下 : http://www.baidu.com 百度这个页面。
当你运行,这个代码的时候。也就是利用Request等请求服务器,也就是向百度的服务器请求那个网页的 HTML 源代码资源(这个底层是用 socket 实现的,现在程序员们已经将其封装为现成的库供我们使用)
如果是用浏览器的话,浏览器是会给渲染然后展示出页面也就是 Elements里面展示的代码,而爬虫行为则只有 HTML 源代码。(本质就是请求资源的过程)
而我们平时写的爬虫,大部分都是主题爬虫,只是请求了网页的一些资源,并没有执行它那些 Js CSS代码,也就不会渲染。(只是简单的请求资源和返回资源的过程)
而我们需要这些资源本身是没有什么用的,我们得到这些资源之后还需要有个 Parser 的过程。也就是解析这个页面,拿到我们需要的信息的时候,之后存到我们的数据库中。
存储方式有很多,可以存储到你的硬盘里面(Disk),如存储在csv,txt,word,txt,word,excel,或者存储到 MySql,Mongodb,Redis等数据库(不占空间,方便管理,规范化编写)。
普及知识:
数据库相比较我们直接存储这些txt、world、Excel、CSV等文件,有什么区别呢?
其实,学过计算机原理都会了解,我们直接存储在硬盘里面(Disk)存储的速度是比较慢的。
在存储的时候,我们的操作系统,会把它压入一个高速缓冲区,之后再慢慢的刷新到我们的硬盘里面。
相比之下,我们直接操作 CPU 就非常之快了,而内存型数据库 Redis 就是直接存储在数据库中,相比较于硬盘里面的高速缓冲区,快了不止十倍。
所以,Redis 现在是默认程序员掌握的。
但是,Redis 存储也有缺点,内存溢出,和断电故障
内存溢出就是数据过多,超出了其承载,而断电的话,数据也会全部消失,所以,用 CPU 这样的方法,还是要有集群方案,和容灾措施、及时的备份、以及日志。
从以上的经讲解爬虫工作的流程,我们可以发现网络爬虫需要注意的几点:
1.如何快速请求数据 (现在我们常讲高并发)如如何使用:多线程、多进程、异步抓取下来
2.如何高效的抓取提取信息(解析我们获取到的数据)
3.如何高效的存储数据
常用库:urlib,requests库等
一般流程如图所示:
1)从基础URL开始爬行
2)从初始页面抓取到我们需要的URL
3)对新的URL继续解析,再次抓取新的URL
基本流程:请求 响应 解析 入库
请求:请求获取网站资源
响应:如果网站返回 status_code 是200,服务器就会返回资源
解析:Parser 来解析我们得到的资源(数据清洗)
可以用来解析的库
BeautifulSoup
PyQuery
Xpath
re (正则表达式)
入库:存储我们需要的资源
1.3网络爬虫的类型
现在的网络爬虫大体可以分为四类:全网爬虫,主题爬虫,增量式爬虫和深层爬虫。
全网爬虫:也就是谷歌百度等搜索引擎,这类爬虫会从一些非常基础的URl出发,一直延伸到整个网站,这类爬虫庞大臃肿,需要很大的存储空间以及极高的爬行速度。
主题爬虫:满足特定人的特定需求,不同于全网爬虫,它是有选择地爬行与需求相关的信息。
重点:增量式爬虫:对已经下载的页面采取增量式更新的爬虫,只爬取新产生的或者发生变化的网页,一定程度上可以保证爬取得页面是最新的,减少了空间的浪费,但是复杂度较高。
比如抓取某一个热搜下面的评论,最有效的方式就是增量爬取,每次仅爬起新出现的或者被修改的,当你第一次抓取,抓取全部数据,几千几万条。所需的抓取时间比如:12h,那等你第二天再抓取该微博热搜榜,不可能继续再重新全部抓取一遍和存储,这就需要应用增量式爬虫爬取,只爬取那些新增的或者修改的,也就需要我们的爬虫要识别这种变化,回顾爬虫原理,我们可以思考一下:
- 发送请求前——判断这个url是不是之前爬取过
- 解析内容后——判断这部分内容是不是之前爬取过(建立数据库池进行比对)
- 存储数据时——判断内容是不是已经在介质中存在(如果出现不入库,如果修改入库替换之前那个旧数据)
通过之上的分析,我们可以得知
其实增量式爬虫最难的那部分,就是数据的比对,
而一种方法就是利用哈希
哈希是利用熵的方法计算出的一些独一无二的数字,如下列代码:
text1='ss'
text2="sb"
text3="ss"
print(hash(text1))
print(hash(text2))
print(hash(text3))
输出为:
-4731542979092136643
-5033844661982332490
-4731542979092136643
可以看到text1,text3两个变量数据一致,而哈希后数字才相同,而text2因为变量数据不同,与两者哈希数字不同。
那这个 hash 生成的随机数,如何来帮助我们实现 增量式爬虫呢?
我们可以,在每一条得到的数据入库之前,哈希一下。然后可以把它的数字比如存进一个集合里面,就能轻松实现数据的重复对比。
当然也可以采用指纹和布隆过滤器的方法,这里不多加赘述。
深层网络爬虫:不能通过静态URL访问,隐藏在表单后,只有用户提交一些关键词才能得到的页面。
深度网络爬虫也就是我们所说的暗网,我们一般日常接触到就是一些 POST 表单,如登录页面之类的,让你输入账号和密码,你输入账户密码之后,点击登录。
我们的爬虫没有设置的话是爬不到里面的,而是被隔离在表单之外,必须设置一些参数才能进入。
举个例子:比如我写了一个网络爬虫。要求它从百度开始遍历所有网站,它遇到有验证码的有登录的就进不去了。因为,它之后的页面是隐藏在表单之后的。
普及知识:
我们日常使用的搜索引擎所无法寻找到的,仅能在电脑上进行一系列特殊的操作设置或在特殊软件的辅助之下又或对本机的特殊授权之后方能进入访问的一种网络——即称之为“暗网”。(可通过洋葱路由器登陆暗网)
1.4爬虫遵守君子协定
robots.txt(统一小写)是一种存放于网站根目录下的ASCII编码的文本文件,它通常告诉网络搜索引擎的漫游器(网络蜘蛛),此网站中的哪些内容是不应该被搜索引擎的漫游器获取的,哪些是可以被漫游器获取的
因为一些系统中的URL是大小写敏感的,所以robots.txt的文件名应统一小写
robots.txt应放置于网站的根目录下。
robots.txt协议并不是一个规范,而只是约定俗成的,所以并不能保证网站的隐私
也就是,利用请求头来规定,哪些请求头可以爬取什么数据。
例如我们可以查看百度的君子协定:https://www.baidu.com/robots.txt
截取部分:
User-agent: Baiduspider
Disallow: /baidu
Disallow: /s?
Disallow: /ulink?
Disallow: /link?
Disallow: /home/news/data/
Disallow: /bh
User-agent: Googlebot
Disallow: /baidu
Disallow: /s?
Disallow: /shifen/
Disallow: /homepage/
Disallow: /cpro
Disallow: /ulink?
Disallow: /link?
Disallow: /home/news/data/
Disallow: /bh
U
User-agent: Sogou inst spider
Disallow: /baidu
Disallow: /s?
Disallow: /shifen/
Disallow: /homepage/
Disallow: /cpro
Disallow: /ulink?
Disallow: /link?
Disallow: /home/news/data/
Disallow: /bh
User-agent: Sogou spider2
Disallow: /baidu
Disallow: /s?
Disallow: /shifen/
Disallow: /homepage/
Disallow: /cpro
Disallow: /ulink?
Disallow: /link?
Disallow: /home/news/data/
Disallow: /bh
User-agent: EasouSpider
Disallow: /baidu
Disallow: /s?
Disallow: /shifen/
Disallow: /homepage/
Disallow: /cpro
Disallow: /ulink?
Disallow: /link?
Disallow: /home/news/data/
Disallow: /bh
User-agent: *
Disallow: /
我们可以看到:其对普通的爬虫没有禁止
User-agent: *
Disallow: /
当然你也可以利用下述代码来获取robots.txt
from urllib import robotparser
rp = robotparser.RobotFileParser()
rp.set_url('https://www.baidu.com/robots.txt')
url = 'https://www.baidu.com/'
print(rp.can_fetch('Python', url))
君子协定为网站后端人员书写的,一般存在大网站,还望读者能够遵守约定。
1.5识别网站技术
利用爬虫我们可以爬取Json 图片 视频等数据,而识别网站技术也很关键,我们可以利用builtwith识别网站采取的技术手段:
首先安装模块:pip install builtwith
运行代码:
import builtwith
from pprint import pprint
url = "https://www.csdn.net/"
res = builtwith(url)
pprint(res)
当然这个包因为多年未更新的缘故,导致一些新的技术不能识别,但因为网站大部分也很老,都已经建立了多年,还是有一定作用的。
1.5网络爬虫的搜索策略
网络爬虫过的搜搜策略一般分为三种
1)深度优先
DFS(Depth-First-Search)深度优先搜索算法,是搜索算法的一种。是一种在开发爬虫早期使用较多的方法,它的目的是要达到被搜索结构的叶结点(即那些不包含任何超链的HTML文件) 。
深度优先指的是当某个页面的URL被选择后,对被选择的URL进行深度优先搜索,搜索后得到新的页面,再从新的页面继续选择URL,循环往复,直到新的请求页面没有URL为止。
2)广度优先
BFS(Breadth First Search)广度优先搜索算法,属于一种盲目搜寻法,目的是系统地展开并检查图中的所有节点,以找寻结果。换句话说,它并不考虑结果的可能位置,彻底地搜索整张图,直到找到结果为止。
广度优先指的是爬取完一个页面的全部URL之后,再选择一个URL进行深入,当把新的URL请求的页面的URL全部爬取完毕,再继续深入。
3)聚焦爬虫
聚焦爬虫会通过给下载好的页面打分的形式,根据得分把页面插入队列中,这样就有可能优先追踪那些最有价值的页面。
相对于通用网络爬虫,聚焦爬虫解决三个主要问题:
(1)对抓取目标的描述或定义
(2)对网页或 数据的分析与过滤
(3)对URL的搜索策略
抓取目标的描述和定义是决定网页分析算法与URL搜索策略如何制定的基础
而网页分析算法和候选URL排序算法是决定搜索引擎所提供的服务形式和爬虫网页抓取行为的关键所在。这两个部分的算法又是紧密相关的
1.6常见反爬虫技术与解决方案
下面是常见的几种反爬虫手段,后面我们会详细介绍,现在大体概述一下
1)用户请求headers
从用户请求过来的request headers中查看是否存在User-Agent,如果不存在会在中间件中将请求过滤,不会返回正常response。还有一些网站会通过请求头里边的Referer进行检测,一些资源网站的防止盗链技术就是通过这个来实现。对于这种反爬虫机制,我们只需要在headers中添加user-agent与referer就可以解决。
user-agent:说明我是个浏览器,而不是爬虫
Referer:说明我来自那里
比较经典的就是天涯社区的图片,如果单独访问不利用user-agent,referer的话会显示如下:
而采用后(下述代码)
import requests
url = 'http://img3.laibafile.cn/p/m/310277586.jpg'
headers = {
'Referer': 'http://bbs.tianya.cn/pic-no04-2829676.shtml'}
img = requests.get(url, headers = headers)
with open('refer.jpg', 'wb') as f:
f.write(img.content)
会正常显示:
2)用户访问频率
有些网站通过用户请求网站的频率来判断请求者是用户还是爬虫,爬取过快的话会被forbid,比如豆瓣会对访问频率过高的爬虫进行封禁,这就需要我们控制请求网站的速度,或者是建立IP代理池来解决。
3)字体反爬虫
实习僧等网站会把常用字和数字自己建立一套关系映射,通过前端渲染,得不到字体映射关系只会看到乱码。
4)网站目录数据加载(Ajax交互)
上述反爬虫技术是在静态网站,还有一些网站会通过Ajax交互,遇到这种情况,需要我们找到Ajax访问接口,分析具体的参数和结构,在爬虫中模拟Ajax,就可以获得所需数据。
举个例子就是百度图片,这个你直接 Get 是请求不到的,之后会有找 Json 接口、API 构造一些参数来获取。
5)通过数据加密
有些网站会通过JavaScripts对一些参数加密,这些加密代码可以在js文件中找到,分析代码需要掌握前端技术,但是耗费时间较多,难度大。另一种解决方案是通过selenium,调用浏览器模拟人类行为,slelenium可以完美触发网页的js,基本上解决这类问题,不过爬取速度较慢。一般只有在迫不得已的时候才会使用。
6)基于验证码识别
早期的验证码主要是数字验证码,可以调用第三方平台或者OCR识别技术解决。不过现在出现了图片验证码,目前仍然需要人类去操作;滑块验证码的破解已经有了成熟的技术,就是利用PIL模块与selenium来实现,比如B站登陆时候的滑块验证码。
来源:CSDN
作者:ZEVIN LI
链接:https://blog.csdn.net/AI_LINNGLONG/article/details/104415623