爬虫基本原理

爬虫基本原理

爬虫原理 — 本质就是可见皆可爬

1 确认目标url

如何抓包?

  • 获取数据之前需要做生成数据包的操作,即清空数据包,点击生成(例如点击翻译按钮、点击评论信息所在的评论按钮)
  • 寻找数据包,查看preview预览图或者response响应数据是否有你想要的数据(ctrl+f可以进行搜索)

url的定义

url:统一资源定位符,如一个网页、一张图片、一个视频等都可以用一个url唯一来确定

url的组成

协议:// [用户名和密码] 主机地址(域名或ip地址) [端口号] [路径] [查询参数] [片段]

  • 协议:http、https、ftp等,但爬虫抓取的页面是基于http和https协议的
  • HTTP:超文本传输协议,表示超出文本的数据可以从网页传输到浏览器;而HTTPS是以安全为目的的HTTP通道,在HTTP的基础上加了个SSL,协议传输的内容会通过SSL进行加密,保证数据的传输的安全性
  • 用户名和密码:有些url需要带上用户名和密码才可以访问
  • 主机地址:包括域名和ip地址,如https://www.baidu.com中的www.baidu.com就是域名,而https://8.8.8.8中的8.8.8.8就是ip地址
  • 端口:服务器设定的服务端口,如https://192.168.0.0.1:8080中的8080就是端口。有些url没有端口信息,是使用了默认的端口, http协议的默认端口是80,https协议的默认端口是443,所以http://www.baidu.com相当于http://www.baidu.com:80,而https://www.baidu.com相当于https://www.baidu.com:443
  • 路径:网络资源在服务器中的指定地址,如https://github.com/favicon.ico中的路径就是favicon.ico,表示访问github根目录下的favicon.ico
  • 查询参数:用来查询某类资源,如果有多个查询,使用&隔开。例如https://www.baidu.com/s?wd=查询内容&ie=utf-8,wd=查询内容&ie=utf-8就是查询参数

2. 发送请求

模拟浏览器向目标url发送请求(requests第三方库),要确定好请求方式,可以在Request Method中查看

http请求过程(浏览器原理)

在浏览器中的地址栏输入一个url,可以看到网页的返回。实际上,这是浏览器向网站所在的服务器发送了一个请求,网站服务器接收到请求后对其进行处理和解析,然后将对应的响应传给浏览器,浏览器再对其进行解析,将网页呈现出来。

  1. 在浏览器地址栏中输入url
  2. url会被发送给DNS服务器
  3. DNS服务器会根据url域名解析出对应的ip地址
  4. 通过ip地址定位到某台服务器
  5. 服务器会返回给我们数据(html文字样式+css渲染工具+js行为+jpg图片),组成了我们看到的网页
  6. 所以,查找百度的ip地址,ping www.baidu.com后,也可以直接在地址栏输入百度的ip地址进行访问

通过打开谷歌开发者工具的network监听组件,刷新网页后network面板有很多个条目,一个条目就代表一次发送请求和接收响应的过程。

请求方法

  • get请求

  • 请求参数可以在url中看到,参数会显示在地址栏中,不太安全

  • 提交的数据最多只能有1024字节

  • post请求

  • 通过data参数携带表单数据提交,安全性相对较高;(登陆操作通常是post请求,因为登录时需要提交密码这类敏感信息,如果使用get方法会将密码暴露在url中,造成密码泄露)

  • 提交的数据没有限制(上传文件时,由于文件的内容比较大,可以使用post请求)

请求头

服务器会根据请求头里的信息判断请求是否合法,进而做出对应的响应

  • user_agent: 发出请求的用户信息,浏览器型号、版本、操作系统信息

  • referer:请求是从哪个页面跳转过来的

  • cookie: 标识了我们所对应的服务器的会话,我们输入用户名和密码成功登录某个网站后,服务器会用会话保存登录状态信息,之后每次请求这个网站的页面时,都会在请求头加上cookie并将其发送给服务器,服务器通过cookie识别出是我们自己,并查出当前状态是登录状态,所以返回的结果是登录后才能看到的网页内容 (维持当前访问会话)

请求体

  • 请求体一般承载的内容是post请求的表单数据,对于get请求,请求体为空。
  • content-typepost提交数据方式的关系:使用post请求需要使用正确的content-type,否则会导致post请求提交后无法得到正确对的响应
  • 提交表单数据登录后
  • request headers中指定content-typeapplication/x-www-form-rulencoded,这样设置后内容才会以表单数据的形式提交
  • 如果设置为application/json,则是提交json数据
  • 如果设置为multipart/form-data,则是将表单文件上传

请求参数

  • params参数

如果url携带的参数太多,可以使用params参数来传递。添加params参数后,会以?a=1的形式加在请求路径后面

import requests url = "http://www.baidu.com/s" 
payload = { "wd": "爬虫" } 
response = requests.get(url, params=payload) 
print(response.url) 

# https://www.baidu.com/s?wd=爬虫

3. 获取响应

服务端把响应数据给到客户端 (response)

响应头

响应头是响应的一部分,包含服务器的类型、文档类型、日期等信息,浏览器在接收到响应后,会对其进行解析,进而呈现出网页内容。

  • date:响应产生的时间

  • last-modified:指定资源最后修改的时间

  • content-encoding:指定响应内容的编码

  • server:服务器的信息

  • content-type:文档类型,指定返回的数据是什么类型,例如:text/html返回的是html文档,application/x-javascript返回的是javascript文件,image/jpeg返回的是图片

  • set-cookie:设置cookie,用于告诉浏览器需要将此内容放在cookie中,下次请求时将cookie带上

响应状态码

服务器的响应状态,response.status_code,检查是否请求成功,如果是200可以做数据做进一步处理。

  • 1**: 信息,服务器收到请求、需要请求者继续执行操作

  • 2**: 成功,操作被成功接收并处理 (200–请求成功)

  • 3**: 重定向,需要进一步的操作以完成请求 (301–资源被永久跳转到其url)

  • 4**: 客户端错误 (404–请求资源不存在)

  • 5**: 服务器错误 (500–服务器内部发生错误)

响应体

响应的正文数据存储在响应体中

  • 请求网页时,响应体就是网页的html代码
  • 请求一张图片时,响应体就是图片的二进制数据
# response.text -- 字符串数据
with open("文章.txt", "w", encoding="utf-8") as f: 
	f.write(response.text) 

# response.content.decode() -- 字符串数据 
with open("文章.txt", "w", encoding="utf-8") as f: 
	f.write(response.content.decode()) 

# response.content -- 二进制数据 
with open("周杰伦.jpg", "wb")as f: 
	f.write(response.content)

响应文本与编码

  • response.text:返回的是字符串数据(本身是字节类型,但会以一种猜测的编码格式自动帮你解码成字符串)

  • response.content:返回的是二进制数据,需要使用.decode()进行解码,转成字符串类型

  • response.encoding:http头猜测的网页编码格式

网页编码格式错误如何解决?

print(response.text) # 得到的文本可能是乱码 
print(response.encoding) 
# 因为requests猜测的网页编码格式出现错误,导致出现乱码。 ISO-8859-l,实际上是utf-8 

方法一:手动指定一下编码格式

response.encoding = "utf-8" 
print(response.text) # 指定后再次打印就不会出现乱码 

方法二:使用“字符串文件编码检测模块”chardet,将chardet探测到的编码赋值给response.encoding解码

print(chardet.detect(response.content)) 
# 字典 {'encoding': 'utf-8', 'confidence': 0.99, 'language': ''} 
response.encoding = chardet.detect(response.content)["encoding"] 
print(response.text) 

方法三 :.decode()解码

print(response.content.decode())

4. 解析数据

确认响应数据response的数据类型,对响应数据进行解析,提取特定的数据。

  • 如果是html类型,可以使用Xpath、正则、BeautifulSoup(CSS选择器)提取
  • 如果是json类型,可以使用内置模块json、第三方库jsonpath、正则提取。
import json

response_data = '{"name": "John", "age": 30, "city": "New York"}'  # 这里假设响应数据是一个JSON字符串

# 解析JSON数据
data = json.loads(response_data)

# 提取数据
name = data['name']
age = data['age']
city = data['city']

print(name, age, city)  # 输出: John 30 New York

动态网页的抓取主要涉及Ajax和动态Html,简单的网页访问是无法获取完整的数据的,需要对数据加载流程进行分析。

Ajax全称是Asynchronous JavaScript and XML,也就是异步的JavaScriptXML,是JavaScript异步加载技术、XMLDomxhtmlcss等技术的组合。使用Ajax技术不必刷新整个页面,只需对页面的局部进行更新,Ajax只取回一些必需的数据,它使用SOAP、XML或者支持JSON的Web Service接口,我们在客户端利用JavaScript处理来自服务器的响应,这样客户端和服务器之间的数据交互就减少了,访问速度和用户体验都得到了提升。

如何判断要爬取的网站是动态网站还是静态网站呢?

  • 当你使用Requests访问一个网页,返回的Response内容和在浏览器上看的HTML内容不一样时,就是用了动态技术,这就是为什么你无法从响应中抽取出有效的数据。

如果是动态网页如何爬取?

  • 使用自动化测试工具(Selenium、Playwright)模拟浏览器的行为
  • 或者检查网页的网络请求,找到动态加载数据的API请求

5. 保存数据

  • 本地:txt、csv、json、excel

  • 数据库(关系型与非关系型):redis、mongodb、mysql

想了解更多MySQL知识:http://t.csdn.cn/xrAiz

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值