01.浏览器
# 一个网页的加载全过程
1. 服务器端渲染
html的内容和数据在服务器进行融合.
在浏览器端看到的页面源代码中. 有你需要的数据
2. 客户端(浏览器)渲染
html的内容和数据进行融合是发生在你的浏览器上的.
这个过程一般通过脚本来完成(javascript)
我们通过浏览器可以看到上述加载过程
# 数据在浏览器的位置:
network ---> All 或 Fetch/XHR 或 JS # 99%只会在这三个里
02.requests
# requests模块
是python的一个非常完善的一个第三方模块,专门用来模拟浏览器进行网络请求的发送
# 本质就是 模拟成浏览器的样子
# url:
协议 域名 端口(80) 资源文件路径 参数
http://www.baidu.com/s?name=alex&age=185
https://www.baidu.com/s?name=alex&age=185
# 发送get请求
# 参数类型:query string parameteres
# 方式: params 和 url传参. 二选一即可
requests.get("https://www.baidu.com/s?ie=UTF-8&wd=周杰伦")
resp = requests.get("https://www.baidu.com/s",
params={
"ie": "UTF-8",
"wd": "周杰伦"
}) # params 是专门给get请求增加参数的
# 发送post请求
# 参数类型:formdata 或 urlcode
requests.post(url, data={"直接给字典就可以了"})
# 参数类型:request payload, 能直观的看到是json类型的数据
requests.post(url, json={"直接给字典就可以了"})
requests.post(url, data=json.dumps({直接给字典就可以了}), headers={
"Content-Type": "application/json; charset=UTF-8"
})
### get/pos对比
get/post, 是http的请求方式 # 我们只需要根据抓包里面的状况去选择使用
get和post的传参方式是不一样的
get的参数,最终都会被添加到url身上 ###
# 状态码 (HTTP协议的状态码)
200 系列 一般指的是你当前本次和服务器进行通信没有问题
300 系列 一般指的是重定向. 注意在响应头上能看到location字样
写爬虫的时候. 基本上不用管302 因为requests可以自动帮你完成这个重定向的动作
403 系列 一般都是被风控拦截了
404 系列 资源文件路径走丢了
你的url不存在.再服务器上人家没办法给你想要的内容
500 系列 服务器内部出现了错误
若浏览器有错,那就是本身服务有问题
若浏览器上啥事儿没有. 你的程序一跑,就500. 基本上就是你给的参数有问题. 让服务器无法正常工作
# 解决:重试 + 异常捕获
for i in range(10):
try:
发请求
break
except Exception as e:
print("出错了")
请求头
# 请求头参数
User-Agent # 用户用什么设备发送的请求, 直接复制粘贴就好
Cookie # 服务器 记录在浏览器上 的一个字符串, 写入浏览器上的一个文件中
# 作用: 和服务器之间保持住会话. session:同理,记录在服务器端的
# 解决:
1.可以直接从浏览器抓包中复制. (某些网站可以)
2.requests.session()来保持会话
注意:requests.session(). 可以帮你处理set-cookie的内容.
它不能帮你处理javascript处理的cookie的内容.
如果网站是用js来维护cookie的, name你需要自己来写代码处理这坨逻辑
Referer # 用来检测上一个url是什么. 一般直接复制粘贴即可 eg: 图片防盗链
网页自己添加的一些参数 # 最蛋疼的 JS逆向的地方
### 请求头参数 依次尝试的优先级
headers = {
'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/121.0.0.0 Safari/537.36',
'Referer':'https://fanyi.baidu.com/',
'Cookie':'xxx',
'Content-Type':'application/x-www-form-urlencoded; charset=UTF-8',
'X-Requested-With':'XMLHttpRequest',
# 再寻找特殊的请求参数
'Acs-Token':'xxx', # 百度翻译封控比较奇怪,该参数时检测,时不检测
}
### session的使用
session = requests.session()
session.headers = {
}
session.cookie = {
}
session.get()
session.post()
响应头
# 响应头参数
Location # 302重定向地址 我们不管
Set-Cookie # session自动维护 我们也不管
网页自己添加的一些参数 # 一般情况下是不用管的. 万中无一的那种网站会使用到
04.数据解析
# html
re # 常见使用场景:在html中获取到js的一部分代码(字符串)
xpath # 常见使用场景:解析常规的html结构
from lxml import etree
tree = etree.HTML(response.text)
res = tree.xpath("xxxxx/xxx/xxx")
# etree的xpath,默认返回的是列表. 要判断空的情况
if res:
res[0]
else:
xxx
bs4 # 常见使用场景:解析 xml类型和 svg(使用XML格式,定义图像)
.find()
.findall()
# json
response.json()
json.loads(response.text)
# 注意:
如果遇到反爬. 很可能拿到的东西 和 抓包工具获取的 不一致
切记, 先打印response.text. 确定好 返回的内容是json格式. 才开始转化
# jsonp 一般是 network 中 JS 请求类型 返回的数据类型
# 这个"jsonpxxxxxx",也在该url的 请求参数中看得到
callback: jsonpxxxxxx
# eg:
jsonpxxxxxx({json}) => {json}
# 解决:想办法去掉左右两端的xxxxxx( ) => 得到的就是json
"jsonpxxxxxx({json})".replace("xxxxxx(", "")[:-1]
05.多任务异步爬虫
# 一般情况下:
最多是 多进程 + 多线程 就够了, 协程不仅麻烦,而且基本正规的网站 都有频率等限制,用不到协程这么高性能
# 进程是资源单位. 进程与进程之间是隔离的
p1 = Process()
p2 = Process()
Queue / redis # 进程通信:队列 和 redis
# 线程是执行单位,多个线程共享 同一个进程的资源
# 协程是人为干预,主进程下 主线程的任务执行情况,将耗时任务 挂起,并切换到其他任务 (最麻烦的)
06.数据存储
# MySQL、Mongodb、Redis、CSV
### 1 mysql
# 用Navicat创建表格即可
增加数据
insert into 表(字段1, 字段2, 字段3.....) values (值1, 值2, 值3.....)
修改数据
update 表 set 字段=值, 字段=值 where条件
删除数据
delete from 表 where 条件
查询数据
select * from 表 where 条件
# python如何操纵数据库
pymysql
# 注意:
1.以字典形式返回数据
cursor = conn.cursor(cursor=pymysql.cursors.DictCursor)
2.避免sql注入问题 %s占位 模块自动拼接
sql = "insert into class(cname, cmoney, cbanzhuren) values (%s, %s, %s)"
cursor.execute(sql, (name, money, banzhuren))
### 2 redis
# redis存储数据的规则:
key -> 数据(单一字符串, 列表, 字典, 集合、有序集合)
### 3 存csv 客户一般用于 pandas进行数据分析
本质就是个文本文件,特点是:文件内的数据 默认 以'逗号,' 分隔,呈现一个表格形式
可以直接用excel打开,逗号会自动分隔到不同的单元格中
# 若数据文本本身包含 逗号,解决
# 解决1:将整个文本 用引号包裹,eg:'"樵,夫"'
f = open("data.csv", mode="w", encoding="utf-8")
f.write('樵,夫')
f.write(",")
f.write("18")
f.write(",")
f.write("5000")
f.write("\n")
# pandas 读取
import pandas
r = pandas.read_csv('data.csv', header=None)
print(r)
# 解决2:可自定义分割符,eg: '|' 通常不修改分割符
f = open("data.csv", mode="w", encoding="utf-8")
f.write('樵,夫')
f.write("|")
f.write("18")
f.write("|")
f.write("5000")
f.write("\n")
# pandas 读取
import pandas
r = pandas.read_csv("data.csv", sep="|", header=None)
r.to_excel("data.xls", header=False, index=False) # 另存为xls格式
07.面向对象(基础)
# 核心是编程思想的转变
# 目前. 我们写的代码是什么思想. 面向过程
1.获取页面源代码
2.去解析页面源代码
3.去存储数据
# 面向对象: 你要操纵对象. 让对象给你干活
结局都是能喝到可乐.
让对象去操作 # 需要自己去创造对象
1.你得有对象
2.你的对象得会去干活
# 怎么去造对象?
在编程的世界里. 想要造对象,需要先写类(泥人, 图纸, 你想想的那个样子)
# 1.先写类
class 类名:
def __init__(self, xxxx):
self.xxxx = xxxx
def 方法名(self):
pass
# 2.造对象
对象 = 类名(参数)
对象.方法名()
self: 当前正在执行这个功能的对象