一篇万字博文带你入坑爬虫这条不归路
本文已参与「掘力星计划 (opens new window)」,赢取创作大礼包,挑战创作激励金。
👻最近,很多粉丝私信我问——爬虫到底是什么?学习爬虫到底该从何下手?👻
😬其实,我想说的也是曾经的我身为小白的时候某些大牛对我说过的——很多时候我们都有一颗想要学习新知识的心,却总是畏惧于对想要学习内容的无知,这也是多数人失败甚至后悔终身的:因为他们从来没有开始过!😬
😜借一位几年前带我入坑的前辈的话——坑就在你面前,别总是犹豫徘徊,大胆一点:向前一步,入了这个坑,莽着头就是往前冲,别多想,别回头,终有一天——>你也会成为别人的前辈!😜
今日份鸡汤已成功送达,目的地:your heart! 💗💗💗
回归正题~~~ 博主写本文的初衷也是想借助本文达到的一个效果:
带领那些想要学习爬虫却一直迟迟不敢下手,或者说那些对爬虫有兴趣想要好好学一学这门技术的童鞋们——正式入坑!!!
💩<-🐷首先,我来回答第一个问题——什么是爬虫?🐷->💩
👉其实你百度也可以百度到一大篇官方化的定义,但是那些对新人不友好,爬虫!总结一句话:就是**模拟浏览器发送请求,获取响应!**👈
🎈至于第二个问题:学习爬虫到底该从何下手?等你们认认真真看完本篇博文之后再考虑这个问题你们还需不需要我来解答。🎈
# 1.爬虫的概念
# (1)爬虫的概念(专业化定义):
网络爬虫也叫网络蜘蛛,它特指一类自动批量下载网络资源的程序,这是一个比较口语化的定义。 更加专业和全面对的定义是:网络爬虫是*伪装*成客户端与服务端进行数据交互的程序。
# (2)爬虫的应用:
数据采集 大数据时代来临,数据就是核心,数据就是生产力,越来越多的企业开始注重收集用户数据,而爬虫技术是收集数据的一种重要手段。
比如:抓取微博评论(机器学习舆情监控) 抓取招聘网站的招聘信息(数据分析,挖掘) 百度新闻网站 复制代码
1
2
3
4搜索引擎 百度,谷歌等搜索引擎都是基于爬虫技术。(PS:爬虫界大佬!)
知识补给站: 知名的某头条就是靠爬虫发家致富的哦!!! 复制代码
1
2
3模拟操作 爬虫也被广泛用于模拟用户操作,测试机器人,灌水机器人等。
软件测试 爬虫之自动化测试 虫师
网络安全 短信轰炸 web漏洞扫描
# (3)爬虫的分类:
🎈 根据不同的标准,爬虫分类也有所不同,常见的三大分类标准及其分类如下: 🎈
第一个:根据爬取的数量不同进行分类: ①通用爬虫:通常指搜索引擎的爬虫。 通用爬虫是搜索引擎抓取系统 (baidu,goole,yahoo等)的重要组成部分 。主要目的是将互联网的网页下载到本地 ,形成一个互联网内容的镜像备份。(但是有一个很大的问题就是它们具有很大的局限性:大部分内容没有用——不同的搜索目的,返回的内容相同!)
②聚焦爬虫:针对特定网站的爬虫。 是面向特定主题需求的一种网络爬虫程序 ,它与通用搜索引擎爬虫的区别在于 : 聚焦爬虫在实施页面抓取时会对内容进行处理筛选,尽量保证只抓取与需求相关的网页信息!
第二个:根据是否获取数据为目的进行分类: ①功能性爬虫: 比如,投票,点赞... ②数据增量爬虫: 比如招聘信息...
第三个:根据url地址和对应的页面内容是否改变,数据增量爬虫又可分为: ①基于url地址变化,内容也随之变化的数据增量爬虫; ②url地址不变,内容变化的数据增量爬虫。
# (4)爬虫的一般开发流程:
①最简单的单一页面数据的爬取: url——>发送请求,获取响应——>提取数据——>保存数据 ②多页面数据的爬取: 发送请求,获取响应——>提取url地址,继续请求
# (5)爬虫开发的重难点:
爬虫难点主要分为两个方向:
- 数据的获取(PS:自己人何苦为难自己人嘞!) 网络公共资源都是为用户准备的,为了避免被爬虫采集,服务端会设置非常多的图灵测试,阻止爬虫的恶意爬取,也即是反爬措施 (opens new window)。爬虫开发工程师在开发爬虫时,需要解决这些反爬措施。我们在开发爬虫的过程中,有很大一部分的工作就是处理这些反爬措施。
- 采集的速度 大数据时代,需要巨大的数据量,动辄千万条的级别,甚至上亿条。如果采集速度跟不上,耗时过长,那么就达不到商业要求。一般我们会采取并发以及分布式来解决速度上的问题。这也是爬虫开发过程中的另外一个重心。
知识点补给站: robots协议:网站通过robots协议,告诉我们搜索引擎哪些页面可以抓取,哪些页面不能抓取, 但它仅仅是道德层面上的约束。
# 2.HTTP和HTTPS
知识点补给站:
大多数商业应用采用的架构:
1.c/s 即 client(客户端) server(服务端)
2.b/s 即 browser(浏览器) server(服务端)
3.m/s 即 moblie(移动端) server(服务端)
以上统称为客户端与服务端!!!
复制代码
2
3
4
5
6
7
8
9
10
网络爬虫是伪装成客户端与服务端进行数据交互的程序。那么,客户端和服务端该怎样进行数据交互呢?就像我们中国人用中文交流,说的中国的语法,我们可以正常沟通。客户端与服务端如果不统一一下,那不就乱套了,所以在网络传输方面产生了众多协议,HTTP就是其中一种。
# (1)HTTP协议
目前互连网上90%的网络传输都是基于http协议(补充:http协议是一个应用层协议)。(注意:爬取想要的数据前,一定要明确其使用的是什么协议!虽然90%都是基于http协议,但是仍有10%采用的是其他的协议,比如:弹幕可能采取的是websocket协议!这样的话,我们采取传统的爬虫就无法爬取到了。)
HTTP是Hyper Text Transfer Protocol(超文本传输协议)的缩写,是用于从万维网(WWW:World Wide Web )服务器传输超文本到本地浏览器的传送协议。
HTTP是基于TCP/IP通信协议来传递数据的(HTML 文件, 图片文件, 查询结果等)。 注意:TCP/IP有个面向连接的特性!(意义:保证数据的完整性) 让咱们生动的了解一下TCP/IP通信协议中的三次握手四次挥手:
- 三次握手建立连接: 🔑客户端说:嘿,服务端girl!我想和你建立连接。(打招呼) 🔒服务端说:好的呢,我听你的。 🔑客户端说:真好,那咱们开始数据交互吧(羞羞)。 . .(干羞羞的事ing,进行数据交互) .
- 四次挥手断开连接: 🔑客户端说:我已经和你交互完数据了,咱断开连接吧!(打招呼) 🔒服务端说:你确定断开连接嘛?(不舍) 🔒服务端又说:那你断开连接吧! 🔑客户端说:好的,那我断开连接了!
# (2)HTTP请求流程:
我们日常用浏览器搜索东西,输入的是URL,浏览器会将其自动转换为HTTP协议。
一次http请求的基本流程是,有客户端向服务端发起一次请求(request), 而服务器在接收到以后返回给客户端一个响应(response)。所以一次完整的http请求包含请求和响应两部分。
# 浏览器发送http请求的过程:
1.域名解析 -->
2.发起TCP的3次握手 -->
3.建立TCP连接后发起http请求 -->
4.服务器响应http请求,浏览器得到html代码 -->
5.浏览器解析html代码,并请求html代码中的资源(如js、css、图片等) -->
6.浏览器对页面进行渲染呈现给用户.
知识点补给站:
在网页的右键检查里Network->Name->Request Headers view parsed下
的Connection:keep-alive保持常连接,就不用频繁的三次握手和四次挥手!
复制代码
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
浏览器获取的内容(elements的内容)包含:url地址对应的响应+js+css+pictures 爬虫会获取:url地址对应的响应 爬虫获取的内容和elements的内容不一样,进行数据提取的时候,需要根据url地址对应的响应为准!
# (3)URL(浏览器搜索框里的内容!)
发送http请求时,通过url对网络资源进行定位。
URL(Uniform Resource Locator),中文叫统一资源定位符。是用来标识某一处资源的地址。也即是我们常说的网址。以下面这个URL为例,介绍下普通URL的各部分组成: 协议+域名(端口默认80)+路径+参数
注意: 1.http协议的端口号默认为80可以不写;https协议的端口号默认为443可以不写(注意:域名可以确定是哪一台电脑;而端口号是为了确定是那台电脑的哪一个应用!) 2.域名通常是IP地址的映射,端口号通常是默认的就不写。我们平常搜索时,比如进入百度:www.baidu.com/,这里的https协议… (opens new window)
# (4)HTTP请求格式
客户端(也就是我们用户)发送一个HTTP请求到服务器的请求消息包括以下部分:请求行,请求头,空行和请求数据。
一般格式: 注意:上图中请求行的URL是指(2)URL中的路径!
# 1.请求方法:
# (1)分类
根据http标准,http请求可以使用多种请求方法。
五种请求方法:OPTIONS,PUT,DELETE,TRACE和CONNECT方法。
# (2)分类讲解
常用方法 是 GET和POST。
GET
1.主要是负责从服务器获取数据 2.URL中添加请求参数,显示在地址栏 3.请求字符串限制 1024个字节 比POST
更加高效和方便。POST
1.主要负责向服务器提交数据 2.没有大小限制(但一般是2M) 比'GET'传递数据量大,安全性高。
# (3)
# 2.请求头:
# 3.HTTP请求正文(请求数据)
请求正文通常是使用POST方法进行发送的数据,GET方法是没有请求正文的。
请求正文跟上面的消息报头由一个空行隔开。
来个承上启下!既然现在请求格式已经OK了,也就是说我们可以让服务端听懂我们说的话了;下面要做的就是让我们能听懂服务端给我们说的话了。
# (6)HTTP响应格式
HTTP响应也由四个部分组成,分别是:状态行(响应行)、消息报头、空行和响应正文。 一般格式:
# 1.HTTP响应状态码:(这里面就有熟悉的404哦!)
当客户端向服务端发起一次请求后,服务端在返回的响应头中会包含一个HTTP状态码(我们在进行爬虫实战的时候可以通过判断此状态码得知目前的爬虫代码是否OK!)。
HTTP的状态码是由三位数字来表示的,由第一位数字来表示状态码的类型,一般来说有五种类型:
注意:重定向就相当于一个中介转接。(所有HTTP响应状态码详解点我查看! (opens new window))
# 2.HTTP响应报头:
# (7)总结:
# 1.HTTP流程总结:
# 2.HTTP协议的特点:
HTTP三点注意事项:
- HTTP是无连接的:无连接的含义是限制每次连接只处理一个请求。服务器处理完客户的请求,并收到客户的应答后,即断开连接。采用这种方式可以节省传输时间。
- HTTP是媒体独立的:这意味着,只要客户端和服务器知道如何处理的数据内容,任何类型的数据都可以通过HTTP发送。
- HTTP是无状态的:HTTP协议是无状态协议。无状态是指协议对于事务处理没有记忆能力。缺少状态意味着如果后续处理需要前面的信息,则它必须重传,这样可能导致每次连接传送的数据量增大。另一方面,在服务器不需要先前信息时它的应答就较快。
无状态HTTP官方详解:
HTTP的无状态是指HTTP协议对事务处理是没有记忆能力的,也就是说服务器不知道客户端是什么状态。当我
们向服务器发送请求后,服务器解析此请求,然后返回对应的响应,服务器负责完成这个过程,而且这个过程是完全
独立的,服务器不会记录前后状态的变化,也就是缺少状态记录。这意味着如果后续需要处理前面的信息,则必须重
传,这导致需要额外传递一些前面的重复请求,才能获取后续响应,然而这种效果显然不是我们想要的。为了保持前
后状态,我们肯定不能将前面的请求全部重传一次,这太浪费资源了,对于这种需要用户登录的页面来说,更是棘手。
这时两个用于保持HTTP连接状态的技术就出现了,它们分别是会话和Cookies。下面会介绍到哦!
复制代码
2
3
4
5
6
7
8
注意: 无状态的意思是,比如你再一个网页中输入了账号密码登录了QQ空间,但是由于HTTP是无状态的,所以你再在QQ空间里登录QQ邮箱需要再输入一次账号和密码,登录的状态是没有被记忆的。但是可以利用会话技术解决。
# 3.HTTPS协议:
加强版的HTTP,公鸡中的战斗机一枚!!! HTTPS(全称:Hyper Text Transfer Protocol over Secure Socket Layer 或 Hypertext Transfer Protocol Secure,超文本传输安全协议),是以安全为目标的HTTP通道,简单讲是HTTP的安全版!
http协议是基于tcp/ip协议的,而https是在http协议的基础之上,再加了一层SSL/TLS协议,数据在传输过程中是加密的。
注意:HTTPS协议的默认端口是443。
http因为是明文传输,而https是密文传输,所以HTTPS比http更安全,
但是性能低,因为解密需要消耗时间!
复制代码
2
3
# 3.解决http无状态 之 会话技术
http是无状态的,那服务端怎么区分同一个用户的连续请求呢,这就用到了会话技术:cookie和session。
# (1)Cookie
Cookie有时也用其复数形式 Cookies。 指某些网站为了辨别用户身份、进行 session 跟踪而储存在用户本地终端上的数据(通常经过加密)。最新的规范是 RFC6265 。
Cookie可以理解为一个凭证
- 1.实际是由服务器发给客户端的特殊信息,
- 2.这些信息以文本文件的方式存放在客户端,
- 3.客户端每次向服务器发送请求的时候都会带上这些特殊的信息。
- 4.服务器在接收到Cookie以后,会验证Cookie的信息,以此来辨别用户的身份。
爬虫中为什么要使用cookie?
- 带上cookie的好处: ①能够访问登录页面。 ②正常的浏览器在请求服务器的时候肯定会带上cookie(第一次请求除外),所以对方服务器有可能会通过是否携带cookie来判断我们是否是一个爬虫,对应的能够起到一定的反爬作用。
- 带上cookie的坏处: ①一套cookie往往对应的是一个用户的信息,请求太频繁有更大的可能性被对方识别为爬虫。 ②一般使用多账号解决。
# (2)Session
Session,中文经常翻译为会话, 其本来的含义是指有始有终的一系列动作/消息,比如打电话时从拿起电话拨号到挂断电话这中间的一系列过程可以称之为一个session。这个词在各个领域都有在使用。
而我们web&爬虫领域,一般使用的是其本义,一个浏览器窗口从打开到关闭这个期间。
Session的目的则是,在一个客户从打开浏览器到关闭浏览器这个期间内,发起的所有请求都可以被识别为同一个用户。 而实现的方式则是,在一个客户打开浏览器开始访问网站的时候,会生成一个cookie,SessionID(注意:SessionID包含于cookie中),这个ID每次的访问都会带上,而服务器会识别这个SessionID并且将与这个SessionID有关的数据保存在服务器上。由此来实现客户端的状态识别。因此session是基于cookie的!
Session与Cookie相反,Session是存储在服务器上的数据,只由客户端传上来的SessionId来进行判定,所以相对于Cookie,Session的安全性更高。
一般SessionID会在浏览器被关闭时丢弃,或者服务器会验证Session的活跃程度,例如30分钟某一个SessionID都没有活跃,那么也会被识别为失效。
session的作用——用来实现客户端和服务的的会话保持! 会话(状态)保持:①保存cookie;② 实现和服务端的长连接。
# (3)cookie和session的区别:
- cookie数据存放在客户的浏览器上,session数据放在服务器上;
- cookie不是很安全,别人可以分析存放在本地的cookie并进行cookie欺骗;
- session会在一定时间内保存在服务器上,当访问增多,会比较占用服务器的性能;
- 单个cookie保存的数据不能超过4k,很多浏览器都限制一个站点最多保存20个cookie。
# (4)来个图理解理解那么枯燥的文字:
用户首次登录时: 会在服务器生成一个session表,里面的key是hash生成的数据,value是一系列信息。 同时在客户端本地生成一个文本文件cookie,这里面包含sessionid,而这个sessionid的值为服务器中的hash形式的key。 用户再次登录时: 会自动携带sessionid及其值,这个值与服务器里的hash形式的key比较,判断用户是否曾登录成功,如果成功,则获取用户登录的数据,然后返回给用户请求的界面。
# (5)实操一波看看Cookies的属性结构:
(以QQ空间为例!)
F12打开浏览器开发者工具,然后按如图步骤即为Cookies:(可以看到有很多条目,其中每个条目可以称为Cookie。)
属性名 | 属性值讲解 |
---|---|
Name | 该Cookie的名称。一旦创建,无法修改! |
Value | 该Cookie的值。如果值为Unicode字符,需要为字符编码;如果值为二进制数据,则需要使用BASE64编码。 |
Domain | 可以访问该Cookie的域名。 |
Max Age | 该Cookie失效的时间,单位为S,通常和Expires一起使用,通过它可以计算出其有效时间。Max Age如果为正数,则该Cookie在Max Age秒后失效;如果为负数,则关闭浏览器时失效,浏览器也不会以任何形式保存该Cookie。 |
Path | 该Cookie的使用路径。如果设置为/path/,则只有路径为/path/的页面可以访问该Cookie;如果设置为/,则本域名下的所有页面都可以访问该Cookie。 |
Size | 此Cookie的大小。 |
HTTP字段 | Cookie的httponly属性。若此属性为true,则只有在HTTP头中会带有此Cookie 的信息,而不能通过document.cookie来访问此Cookie。 |
Secure | 该Cookie是否仅被使用安全协议传输。安全协议有HTTPS和SSL等,在网络上传输数据之前先将数据加密。默认为false。 |
# 4.爬虫实战:利用socket下载一张图片
# (1)socket学习
socket国外翻译为插座;同时,由于其具备了“套接”和“字”的概念,所以又称为套接字。
知识补给站:(混个眼熟就行了!)
Socket是一种进程间通信机制,提供一种供应用程序
访问通信协议的操作系统调用,使得网络读写数据
和读写本地文件一样容易;Socket是一序列的“指令” ;
已经具备了“套接”(建立网络通讯或进程间通讯)和“字”(可交互的有序指令串)的概念。
复制代码
2
3
4
5
6
# ①使用socket简单建造一个服务端:(点我观看另一篇进阶版搭建的TCP服务器端文章 (opens new window))
import socket
# 服务器对象
server = socket.socket()
'''
等同于:server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
socket.AF_INET:使用IPV4;
socket.SOCK_STREAM:创建一个socket套接字。
'''
# 1.绑定服务器
server.bind(("0.0.0.0",8800)) #0.0.0.0是允许所有人来访问;8800是端口号
# 2.监听
server.listen(5)
while True:
# 3.等待连接
# accept是一个阻塞的方法(你不来我就不动!),等待连接,每建立一个连接就会创建一个单独的通道。
# conn:通道参数;addr:通道地址。
conn,addr=server.accept()
# 4.接收数据
data=conn.recv(1024)
print(data)
response="HTTP/1.1 200 OK\r\nContent-Type: text/html;charset=utf-8;\r\n\r\n<h1 style='color:black'>我很帅!<h1>"
# 5.发送数据
conn.send(response.encode())
print("已经响应")
# 6.关闭
server.close()
复制代码
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
在本地浏览器中输入:127.0.0.1:8800即可访问到此服务端:
# ②使用socket简单建造一个客户端:(爬取百度首页整个界面)
import socket
# 建立服务器对象 通过打印这个client服务器对象可知:默认使用的是IPV4,协议是TCP。
client=socket.socket()
# 1.建立连接
client.connect(("www.baidu.com",80))
# 构造请求报文
data=b"GET / HTTP/1.1\r\nHost: www.baidu.com\r\n\r\n"
# 2.发送请求
client.send(data)
res=b""
# 3.接收数据
temp=client.recv(4096)
while temp:
print("*"*50)
res += temp
temp = client.recv(4096)
print(temp.decode())
# 4.断开连接
client.close()
复制代码
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
# (2)实战:使用socket来爬取一张漂亮MM的图片:
据说搜狗是没有设置反爬的,刚入门的话就挑软柿子捏,所以我们就来爬爬它。
# 1.首先,分析网页:
而我们要爬取的图片的URL就在头信息里的Request URL中。CV大法即可!
# 2.上代码:
#搜狗图片 下载一张
import socket
import re
#搜狗图片
img_url="https://i02piccdn.sogoucdn.com/a3ffebbb779e0baf"
''' 拓展:如何使用HTTPS请求
#HTTPS请求
import ssl
client = ssl.wrap_socket(socket.socket()) #ssl.wrap_socket 一个装饰器
client.connect(('i02piccdn.sogoucdn.com',443))
'''
client = socket.socket()
# 创建连接 注意上面我们爬的是https协议的url,但是我们使用http也行的原因是自动进行了重定向
client.connect(("i02piccdn.sogoucdn.com",80)) #连接服务器,ip地址的映射可以定位到它的服务器
# 构造请求报文
data = "GET /a3ffebbb779e0baf HTTP/1.1\r\nHost:i02piccdn.sogoucdn.com\r\n\r\n"
# 发送数据
client.send(data.encode()) #报文要以字节码的形式
# 接收数据
first_data = client.recv(1024)
print("first_data",first_data)
length = int(re.findall(b"Content-Length: (.*?)\r\n",first_data)[0]) #在列表里,所以加0; 响应的也是字节码形式,所以加b
print(length) #内容长度
# 写这句的原因是在双\r\n后面可能有数据,也可能没有,如果有就直接拿到了
# .*是匹配除了\r\n换行符之外的,后面加个re.S,则也可以匹配\r\n换行符,变成无敌的了!
image_data = re.findall(b"From Inner Cluster \r\n\r\n(.*?)",first_data,re.S)
if image_data:
image_data = image_data[0]
else:
image_data = b""
# 拼接拿到相应长度的数据
while True:
temp = client.recv(1024)
image_data += temp
if len(image_data)>=length:
break
# 4.断开连接
client.close()
# 写入文件
with open("girl.jpg","wb") as f:
f.write(image_data)
复制代码
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
# 3.实现效果:
控制台输出为: first_data b'HTTP/1.1 200 OK\r\nServer: nginx\r\nDate: Thu, 08 Jul 2021 17:04:43 GMT\r\nExpires: Fri, 08 Jul 2022 17:04:43 GMT\r\nX-NWS-UUID-VERIFY: 1266ff4f6f6197f273f603ca87522cc9\r\nExpiration-Time: Sun, 26 Dec 2021 13:11:13 GMT\r\nX-Daa-Tunnel: hop_count=3\r\nAccept-Ranges: bytes\r\nX-Cache-Lookup: Cache Miss\r\nLast-Modified: Sun, 27 Jun 2021 01:11:13 GMT\r\nCache-Control: max-age=31536000\r\nContent-Length: 19594\r\nX-NWS-LOG-UUID: 14051802991302897940\r\nConnection: keep-alive\r\nX-Cache-Lookup: Hit From Inner Cluster\r\n\r\n' 19594`
# 5.In the end!
从现在做起,坚持下去,一天进步一小点,不久的将来,你会感谢曾经努力的你!
作者:孤寒者 链接:https://gu-han-zhe.blog.csdn.net 来源:CSDN 著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。