网络爬虫相关
一、爬虫的基础内容
1、基本概念和用途
1.1、概念:
- 模拟浏览器、发送请求,获取响应。(只能获取客户端所展示出来的数据)
1.2、特点:知识碎片化,针对不同的网站对应的方法也不同。
- 爬虫:模拟客户端访问,抓取数据。
- 反爬:保护重要数据,阻止恶意网络攻击
- 反反爬:针对反爬的措施。
1.3、作用
- 数据采集
- 软件测试
- 抢票
- 网络安全
- web漏洞扫描
2、爬虫的分类
2.1、根据爬取网站的数量,可以分为
2.1.1、通用爬虫
①特点:爬取网站数量没有上线。
示例:搜索引擎
2.1.2、聚焦爬虫(*)
①特点:爬取网站数量有上限,有明确的目标。
②分类:
功能性爬虫
①特点:不获取数据,只为实现某一功能。
示例:投票 / 抢票 / 短信轰炸等。
数据增量性爬虫
①特点:获取数据用于后续分析
②分类
- url与数据同时变化 -- 整条新数据
- url不变,数据裱花 -- 数据部分更新
3、爬虫的基本流程
3.1、流程
- url(网站资源定位符)
- 对url发送网络请求,获取网络请求的响应
- 解析响应,提取数据
- 保存数据
3.1.1、确认目标:目标url:www.baidu.com
3.1.2、发送请求:发送网络请求,获取到特定的服务端给你响应。
3.1.3、提取数据:从响应中提取特定的数据 jsonpath / xpath / re
3.1.4、保存数据:本地(html、json、txt)、数据库
获取到的响应中,有可能会提取到还需要继续发送请求的url,可以拿着解析到的url继续发送请求
robots协议并不是一个规范,只是约定俗成。
二、http协议以及请求头
1、网络通信
1.1、步骤
- 电脑(浏览器): url -- www.baidu.com 域名
- DNS服务器:IP地址标注服务器,返回响应
- DNS服务器返回IP地址给浏览器
- 浏览器拿到IP地址去访问服务器,返回响应
- 服务器返回给我们的响应数据:html / css / js / jpg......
1.2、实际原理
一个请求只能对应一个数据包(文件)
2、http协议和https协议
2.1、http协议(超文本传输协议)
- 超文本:不仅仅限于文本,还包括图片、音频、视频。
- 传输协议:指使用共用约定的固定格式来传递转换成字符串的超文本内容。
2.1.1、作用
- 规定了服务器和客户端互相通信的规则。
2.1.2、http请求/响应的步骤
- 客户端连接到web服务器
- 发送http请求
- 服务器接受请求返回响应
- 释放连接tcp连接
- 客户端解析html内容
2.1.3、请求头
请求方式:get 和 post
get:向服务器要资源
post:向服务器提交资源
- User-Agent:模拟正常用户
- cookie:登录保持
- referer:当前这一次请求时由哪个请求过来的
抓包得到的响应内容才是判断依据,elements中的源码是渲染之后的源码,这个不能作为判断标准。
2.1.4、字符串编码解码
编码 -- encode()
字符串转换成二进制字符串 str 转换成 bytes
解码 -- decode()
二进制字符串转换成字符串 bytes 转换成 str
三、requests库的介绍
1、requests基本使用
requests模块作用:发送http请求,获取响应数据。
requests模块式第三方模块,需要安装:
1.1、安装命令: -- pip install requests
1.2、基本使用:
import requests
# 目标url
url = 'https://www.baidu.com'
# 向目标url发送get请求
response = requests.get(url)
# 打印响应内容
#将其编码设置为UTF-8
response.encoding = 'utf-8'
print(response.text)
# print(response.content.decode()) 默认UTF-8解码
使用requests库保存图片:
import requests
# 确定url
url = 'https://img0.baidu.com/it/u=3225468693,477076843&fm=253&fmt=auto&app=138&f=JPEG?w=1115&h=800'
# 发送请求,获取响应
res = requests.get(url)
print(res.content)
# 保存响应
with open('1.jpg', 'wb') as f:
f.write(res.content)
1.3、常用的属性或方法
- response.url 响应的url。有时候响应的url和请求的url并不一致。
- response.status_code 响应状态码。
- response.request.headers 响应对应的请求头。
- response.headers 响应头
- response.cookies 响应的cookie(经过了set-cookie动作。返回cookieJar类型)
1.4、其他属性
response.text 和 response.content 的区别:
text: str类型, requests模块自定根据http头部对响应的编码作出有根据的推测。
content: bytes类型, 可以通过decode()解码。
2、用户代理
请求头中user-agent字段必不可少,表示客户端操作系统以及浏览器的信息。
示例
import requests
url = 'https://www.baidu.com/'
# 构建请求头
header = {
'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/133.0.0.0 Safari/537.36'
}
# 带上user-agent发送请求
# headers参数接受字典形式的请求头,请求头字段名为key,值为value
response = requests.get(url, headers=header)
print(response.content.decode())
添加user-agent的目的是为了让服务器认为是浏览器在发送请求,而不是爬虫在发送请求
3、URL传参
user-agent池 --防止反爬
第一种方法:使用user-agent池随机调用
import random
# 随机调用
UAlist = [
'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/133.0.0.0 Safari/537.36',
'Mozilla/5.0 (iPhone; CPU iPhone OS 16_6 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/16.6 Mobile/15E148 Safari/604.1',
'Mozilla/5.0 (Linux; Android 8.0.0; SM-G955U Build/R16NW) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/133.0.0.0 Mobile Safari/537.36',
]
print(random.choice(UAlist))
第二种方法:使用fake_useragent 可能会出现异常
首先下载fake_useragent:pip install fake_useragent
from fake_useragent import UserAgent
print(UserAgent().random)
3.1、浏览器发送请求的原理
- 构建请求
- 查找缓存(在浏览器缓存中寻找有没有需要查找的资源,如果有的话就拦截请求,返回这一资源的副本,并直接结束请求)
- 准备IP地址和端口
- 等待tcp队列
- 建立tcp连接
- 发送http请求
浏览器会向服务器发送请求行,包括了请求方法,请求url,http协议
3.2、编码转译
- 字符串被当做url提交时会被自动进行url编码处理
- 输入 --字符串 明文
- 发送请求的时候 --%xxx%xxx 密文
from urllib.parse import quote, unquote
# quote() #明文转密文
# unquote() #密文转明文
print(quote('参数')) # 输出:%E5%8F%82%E6%95%B0
print(unquote('%E5%8F%82%E6%95%B0')) # 输出:参数
3.3、发送带参数的请求
通过params携带参数字典:
- 构建请求参数字典
- 发送请求的时候带上请求参数字典
import requests
url = 'https://www.baidu.com/s?'
header = {
'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/133.0.0.0 Safari/537.36'
}
# 构建请求参数字典
name = input("请输入关键字:")
kw = {'wd': name}
# 带上请求参数发起请求,获取响应
response = requests.get(url, headers=header, params=kw)
print(response.content.decode())
四、简单案例
1、获取单张图片
示例(网易云):
# 1、导入模块
import requests
# 找到目标url
url = 'https://p1.music.126.net/Y2C3RbZflVZMUuNBkKA-Jg==/109951170607654157.jpg?imageView&quality=89'
# 构建请求头字典
headers = {
'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/134.0.0.0 Safari/537.36'
}
# 发送请求,获取响应
res = requests.get(url, headers=headers)
# res.content是二进制数据
# 保存文件
with open('网易云.jpg', 'wb') as f:
f.write(res.content)
2、获取单首歌曲
示例(酷我):
# 1、导入模块
import requests
# 找到对应目标的url
url = 'https://ga-sycdn.kuwo.cn/2941b0d5664d5d39fbcc5d58db543670/67d45eec/resource/pay3_v2/279292599/'
# 构建请求头字典
headers = {
'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/134.0.0.0 Safari/537.36'
}
# 发送请求,获得响应
res = requests.get(url, headers=headers)
# 保存文件
with open('酷我.mp3', 'wb') as f:
f.write(res.content)
3、获取单个MV
示例(酷我):
# 导入模块
import requests
# 确定目标url
url = 'https://gd-sycdn.kuwo.cn/6bab1f0b832f4a522593a520edc1abee/67d45553/resource/m3/35/83/2343069577.mp4'
# 获取请求头字典
headers = {
'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/134.0.0.0 Safari/537.36'
}
# 发送请求,获取响应
res = requests.get(url, headers=headers)
# 保存文件
with open('mv.mp4', 'wb') as f:
f.write(res.content)
4、获取单页贴吧
示例(百度贴吧):
# 导入模块
import requests
# 确定目标url
url = 'https://tieba.baidu.com/f?ie=utf-8&kw=%E5%B0%8F%E6%98%8E&fr=search'
# 获取请求头字典
headers = {
'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/134.0.0.0 Safari/537.36Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/134.0.0.0 Safari/537.36'
}
# 发送请求,获取响应
res = requests.get(url, headers=headers)
# 保存文件
with open('小明.html', 'wb') as f:
f.write(res.content)
示例(贴吧翻页):
# 导入模块
import requests
# 确定目标url
url = 'https://tieba.baidu.com/f?'
# 获取请求头字典
headers = {
'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/134.0.0.0 Safari/537.36Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/134.0.0.0 Safari/537.36'
}
search = input('请输入搜索内容:')
page = int(input('请输入要保存的页数:'))
for i in range(page):
params = {
'kw': search,
'pn': i*50
}
# 发送请求,获取响应
res = requests.get(url, headers=headers, params=params)
# 保存文件
with open(F'{search}{i+1}.html', 'wb') as f:
f.write(res.content)