爬虫学习
爬虫的简介
爬虫,又称为网络蜘蛛,即爬虫网页中的内容,通俗的来将就是将网页中的数据提取处理,并且保存到本地,来进行后续的操作。
爬虫,遵循所见即所爬原则,也就是说只能爬取到看的见的数据,看不见的数据就无法提取了。
爬虫,要在合法的范围内进行爬取,切记,有关国家政府等机关的网站,碰都不要碰下。
爬虫流程
1.确定url
2.发送请求,获取响应
3.提取响应
4.保存数据,进行后续操作
爬虫爬取的是响应,也就是 Elements
和 Network
中的内容。
如何查看响应内容,在浏览器中,按下F12 键 来打开 开发者工具
。
报文的简介
这里以百度为例,讲解部分重要的报文信息。
bash
Request URL: # 请求url
https://www.baidu.com/
Request Method: # 请求方式
GET
Status Code: # 状态码
200 OK
Remote Address: # 目标服务器的ip地址 (不一定真实)
180.101.50.242:443
Referrer Policy:
strict-origin-when-cross-origin
bash
connection: # 链接类型
keep-alive # 保持状态
content-encoding: # 压缩网站的资源 来加载网页,提升访问速度和省流
gzip
content-security-policy:
frame-ancestors 'self' https://chat.baidu.com http://mirror-chat.baidu.com https://fj-chat.baidu.com https://hba-chat.baidu.com https://hbe-chat.baidu.com https://njjs-chat.baidu.com https://nj-chat.baidu.com https://hna-chat.baidu.com https://hnb-chat.baidu.com http://debug.baidu-int.com;
content-type:
text/html; charset=utf-8 # 网页的类型
date:
Sun, 08 Dec 2024 08:48:06 GMT
isprivate:
1
server:
BWS/1.1
set-cookie: # 设置cookie
H_PS_PSSID=61027_61219_61238_61286_61299_60851; path=/; expires=Mon, 08-Dec-25 08:48:06 GMT; domain=.baidu.com
traceid:
1733647686064072500215700831173387519682
transfer-encoding:
chunked
x-ua-compatible:
IE=Edge,chrome=1
x-xss-protection:
1;mode=block
bash
accept:
text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7
accept-encoding:
gzip, deflate, br, zstd
accept-language:
zh-CN,zh;q=0.9
cache-control:
max-age=0
connection:
keep-alive
cookie: # cookie值
BAIDUID=C155054FF20275AE910502293C199919:FG=1; PSTM=1706779018; BIDUPSID=C5545CC11C26AB48970156B609268488; BDUSS=lwQWtzNkxleWYyN09zRzVKTXpmWERiNGd3ZGJZa0xHMkVERThoalVwakJmWnBtSVFBQUFBJCQAAAAAAAAAAAEAAAAHx--u1LTUtMrH1ea1xLrDv7QAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMHwcmbB8HJmen; BDUSS_BFESS=lwQWtzNkxleWYyN09zRzVKTXpmWERiNGd3ZGJZa0xHMkVERThoalVwakJmWnBtSVFBQUFBJCQAAAAAAAAAAAEAAAAHx--u1LTUtMrH1ea1xLrDv7QAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMHwcmbB8HJmen; BD_UPN=12314753; MCITY=-178%3A; newlogin=1; H_WISE_SIDS_BFESS=61027_61134_61141_61219_61210_61215_61233_61238_61286; H_PS_PSSID=61027_61219_61238_61286_61299_60851; sugstore=1; H_WISE_SIDS=61027_61219_61238_61286_61299_60851; BAIDUID_BFESS=C155054FF20275AE910502293C199919:FG=1; BA_HECTOR=alag0k8g0185aka0al01a5akas6rls1jlagge1u; ZFY=onT3QDmdkVl:A6ZZi602wUgfu47jegP7R:Bh8:BxUbfJ6Q:C; Hm_lvt_aec699bb6442ba076c8981c6dc490771=1732865713,1732963456,1733305567,1733641407; COOKIE_SESSION=8_1_9_9_19_21_0_1_9_9_15_3_746_0_131_2_1733641522_1733641393_1733641391%7C9%23675983_67_1733641391%7C9; BDORZ=B490B5EBF6F3CD402E515D22BCDA1598; ab_sr=1.0.1_N2RmNmY5ZGMwZWNhODI5ZjE5MzIxN2RlNGEwZDUxNGQ4M2Y0Njk2OTdiNTliYjU4M2RkODYxMGYwZjRiMWRhMDkyNmU0ZjFlNzA5YTQ0NDAwMDY3NWUwZmQ2NzE2Y2RkOTMzYTAwMzBlOWM0Zjc2YWI2MTlmNzQxNTA4ZTRhNDM5MTY5MDM3ODMwOTI0Y2NlZTFkNDliZjMzMDg2NzA2MzM4OTRiOTZhODdiZjAwZTZkYTc1ZjNmMjg4YTlmY2Iz; H_PS_645EC=3ae0eS9Vp1YbjDm%2BDSD5RHi%2F9zQXCSJywjzxR4acr3PhdsN4576%2BMU8%2FlSM
host: # 主机
www.baidu.com
sec-ch-ua:
"Google Chrome";v="131", "Chromium";v="131", "Not_A Brand";v="24"
sec-ch-ua-mobile:
?0
sec-ch-ua-platform:
"Windows"
sec-fetch-dest:
document
sec-fetch-mode:
navigate
sec-fetch-site:
none
sec-fetch-user:
?1
upgrade-insecure-requests:
1
user-agent: # 浏览器名称,里面是本机信息和浏览器信息
Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36
网络请求方式
请求方式 | 说明 |
---|---|
GET | 用于从服务器获取信息。GET请求应该只用于数据检索,而不应用于修改服务器上的数据。 请求参数通常通过URL传递 |
POST | 用于向服务器提交数据,比如提交表单或者上传文件。 数据包含在请求体中 |
PUT | 用于更新现有资源或创建新资源(如果该资源不存在的话)。 PUT请求中的数据代表整个被替换的资源。 |
DELETE | 用于请求服务器删除指定的资源 |
HEAD | 类似于GET请求,但不返回消息体,只返回状态行和头信息。这可以用来检查资源是否存在以及获取元数据而无需下载整个内容 |
OPTIONS | 用于描述目标资源所支持的通信选项。可以用来检查服务器的能力,如可用的方法或是否需要认证 |
PATCH | 用于对资源进行部分修改。它只发送需要更改的数据,而不是整个资源,因此可以更高效地更新资源。 |
常用状态码
状态码 | 说明 |
---|---|
200 | 200表示请求在服务器端被正常处理。一般用于 GET 与 POST 请求。在响应报文内,随状态码一起返回的信息会因方法的不同而发生改变。 |
204 | 204表示服务器接收的请求已经成功处理,但是在返回的响应报文中不含实体的主体部分。另外,也不允许返回任何实体的主体。当浏览器在发送请求后接收到204响应,它的显示页面不会发生更新。 |
206 | 206表示客户端进行了范围请求,而服务器成功执行了这部分的GET请求。响应报文内包含由Content-Range指定范围的实体内容。 |
301 | 永久重定向,301状态码表示请求的资源已经分配了新的URI,以后请求该资源应该访问新的URI。也就是说,如果已经把资源对应的 URI保存为书签了,这时应该按 Location 首部字段提示的 URI 重新保存。 |
302 | 临时重定向,302表示请求的资源已经被分配了新的URI,希望客户端本次能使用新的URI访问。和301不同的是,这种资源的URI变更是临时的额,而不是永久的,因此不用去更新书签。 |
303 | 该状态码和 302 有着异曲同工之妙,表示由于请求对应的资源存在着另一个 URI,应使用 GET 方法定向获取请求的资源。 |
304 | 304 状态码表示客户端发送附带条件的请求时,服务器端允许请求访问资源,但未满足条件的情况。例如,客户端请求的资源在客户端本地已有缓存,会在请求头部中加入 "If-Modified-Since"、 "If-None-Match" 等字段,服务端根据这些字段信息判断这些资源信息是否经过修改,如果没有则返回 304 状态码,客户端可以直接使用缓存中的资源. |
400(错误请求) | 400 状态码表示请求报文中存在语法错误。当错误发生时,需修改请求的内容后再次发送请求。另外,浏览器会像 200 OK 一样对待该状态码。 |
401(未经授权) | 401 状态码表示发送的请求需要 有通过 HTTP 认证(BASIC 认证、DIGEST 认证)的认证信息。第一次收到 401 状态码表示需要进行用户认证,第二次再收到 401 状态码说明用户认证失败。 |
403 (拒绝请求) | 403 状态码表明对请求资源的访问被服务器拒绝,当未获得文件系统的访问授权,访问权限出现某些问题(从未授权的发送源 IP 地址试图访问)等列举的情况都可能发生 403 。 |
404 (无法找到) | 404 是我们最常见的状态码之一,它表示服务器上无法找到请求资源。此外,也可能是服务器端在拒绝请求且不想说明原因的时候使用。 |
500(内部服务器错误) | 500 状态码表明服务器端在执行请求时发生了错误。也有可能是 Web 应用存在的 bug 或某些临时的故障。 |
503 (服务不可用) | 503 状态码表明服务器暂时处于超负载或正在进行停机维护,现在无法处理请求。 |
以上常用的状态码记不住,无所谓,只需要记住:
- 以2开头的状态码,说明请求成功
- 以3开头的状态码,说明重定向路径
- 以4开头的状态码,说明请求失败
- 以5开头的状态码,说明请求服务器有问题
Requests模块基础使用
reuqest模块是用来发起网络请求的,并且获取响应,当然对应的,还有其他工具也能达到同样的效果,比如urlib,bs4等。
安装
requests是第三方模块,需要pip安装下
bash
pip install requests -i https://pypi.tuna.tsinghua.edu.cn/simple/
常用方法
get()
:发起get请求
post()
: 发起post请求
text()
: 打印响应内容,可能会出现乱码
content()
: 以二进制的方式打印响应内容
content.deconde()
: 打印响应内容,不会出现乱码
json()
: 自动将json字符串类型的响应内容转换成python对象
发送get请求
python
# 0.导包
import requests
# 1.准备url
url = "https://www.baidu.com/"
# 2.准备头部信息
headers = {
# 指定浏览器的信息
"user-agent":"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36"
}
# 3.发送get请求
response = requests.get(url=url,headers=headers) # get方法里面要传两个基本参数,路由和头部信息
# 4.打印响应内容
print(response.content.decode())
以上代码打印出来的结果,就是 Network
中的内容。
发送带参数的get请求
在确定url之后,添加参数,先不用写,后面再写:
方式一:直接在url后面以格式话字符串的形式
方式二:重新构建变量params
? 前面的是请求地址,后面的是请求参数,类型是键值对类型 wd:python
也就是说,这里的查询参数是python
python
import requests
# 1.准备url
url = "https://cn.bing.com/search?" # 这里以bing为例
# 2.准备头部信息
headers = {
# 指定浏览器的信息
"user-agent":"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36",
}
# 3.构建查询参数 这里使用的是方式二
params = {"q":"python"}
# 4.发送get请求
response = requests.get(url=url,headers=headers,params=params)
# 5.打印响应内容
print(response.url) # 打印请求的url
print(response.content.decode())
发送post请求
首先要构建请求的参数data
python
import requests
# 1.准备url
url = "https://fanyi.baidu.com/mtpe-individual/multimodal?query=%E4%BD%A0%E5%A5%BD&lang=zh2en"
# 2.准备头部信息
headers = {
# 指定浏览器的信息
"user-agent":"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36",
}
# 3.构建post请求参数data 来源于payload
data = {
"corpusIds":[],
"domain":"common",
"from":"zh",
"milliTimestamp": "1733655669726",
"needPhonetic":"false",
"query":"你好",
"reference":"",
'to':'en',
}
# 4.发送get请求
response = requests.post(url=url,headers=headers,data=data)
# 5.打印响应内容
print(response.url)
print(response.content.decode())
以上结果返回405,意思是禁止访问,但是这不重要,重点是演示post请求
json数据及提取
json的使用
json是前后端进行交互的桥梁。
常用方法
方法 | 说明 |
---|---|
dumps | python的字典转换成json数据,json.dumps(字典数据,ensure_ascii=False) |
loads | json字符串转换成python字典,json.loads(json字符串数据) |
dump | python的字典转换成json数据,这会操作文件,json.dump(字典数据,fp=文件对象,ensure_ascii=False) |
load | json字符串转换成python字典,这会操作文件,json.load(文件对象) |
代码案例
python
# dumps方法
import json
d1 = {"name":"zhangsan"} # 这里必须要用双引号
res1 = json.dumps(d1,ensure_ascii=False)
print(res1,type(res1)) # {"name": "zhangsan"} <class 'str'>
以上代码,可以发现,原本字典类型的数据,经过dumps
方法转换后,就变成str类型的数据了,json的数据类型其实是str
python
#loads方法
import json
str1 = '{"name":"zhangsan"}' # 这里最外层要用单引号
loads_str = json.loads(str1)
print(loads_str,type(loads_str)) # {'name': 'zhangsan'} <class 'dict'>
注意:
JSON字符串必须使用双引号(")来包围键和字符串值。如果使用单引号('),则会导致解码错误。
JSON中的布尔值 true 和 false 会被转换成Python中的 True 和 False。
JSON中的 null 会被转换成Python中的 None。
如果JSON字符串格式不正确(例如缺少引号、括号不匹配等),json.loads() 会抛出一个 json.JSONDecodeError 异常。
python
# dump 方法
import json
data_dict = {"name":"zhangsan","age":18}
# 将字典数据转成json类型数据,并写入a.txt文件
with open("a.txt","w") as f:
json.dump(data_dict,fp=f,ensure_ascii=False) # 将data_dict转成json类型数据
python
#load 方法
import json
# 读取刚刚写入的a.txt文件
with open("a.txt","r") as f:
# 将读取到的json数据转成字典
json_data = json.load(fp=f)
print(json_data,type(json_data)) # {'name': 'zhangsan', 'age': 18} <class 'dict'>
jsonpath的使用
jsonpath是第三方库,是用来提取json格式的数据。
jsonpath可以按照 键
对python字典进行批量数据获取。
jsonpath的安装
bash
pip install jsonpath -i https://pypi.tuna.tsinghua.edu.cn/simple/
jsonpath的语法规则(部分)
语法 | 说明 |
---|---|
$ | 根节点 |
@ | 取行节点 |
. 或者 [] | 取子节点 |
... | 就是不管位置,选择所有符合条件的条件 |
* | 匹配所有元素节点 |
[] | 迭代器标识(数组下标) |
[ , ] | 支持迭代器中做多选 |
?() | 支持过滤操作 |
() | 支持表达式计算 |
jsonpath使用方式
jsonpatch(json数据,'jsonpath的语法规则')
python
import jsonpatch
res = jsonpatch(json数据,'jsonpath的语法规则')
print(res)
xpath数据提取
xpath的使用
xpath语法是用来提取DOM节点中数据,也就是Element中的数据。
xpath的语法
语法规则 | 说明 |
---|---|
nodename | 选中该元素 |
/ | 从根节点选取,或者是元素和元素间的过渡 |
// | 从匹配选择的当前节点,选择当前节点文档中的节点,而不考虑它们的位置 |
. | 选择当前节点 |
... | 选择当前节点的父节点 |
@ | 选择属性 |
text() | 选取文本 |
xpath语法练习
bash
# 选择所有 <h2> 下的文本
//h2/text()
# 获取所有的a标签的href
//a/@/href
# 获取html下的head下的title的文本
/html/head/title/text()
# 获取html下的head下的link标签的href
/html/head/link/@href
注意:提取数据时一定要在末尾加上
/text()
lxml模块
lxml模块是用xpath
语法来提取dom节点的数据
lxml模块的安装
bash
pip install lxml -i https://pypi.tuna.tsinghua.edu.cn/simple/
导包
python
from lxml import etree
lxml模块的常用方法
方法名 | 说明 |
---|---|
etree.HTML() | 把内容转换成element 类型的内容 |
etree.tostring() | 把element 数据类型转换为文本类型 |
lxml使用流程
- 从网页中下载html文本数据,通过
etree.html
转成element
数据 - 然后将
element
数据 通过etree.tostring
转换为 html文本数据