前言
本博客仅做学习笔记,如有侵权,联系后即刻更改
科普:
requests进阶
headers:HTTP协议中的请求头.
⼀般存放⼀些和请求内容⽆关的数据. 有时也会存放⼀些安全验证信息.⽐如常⻅的User-Agent, token, cookie等
- 通过requests发送的请求, 我们可以把请求头信息放在headers中. 也可以单独进⾏存放, 最终由requests⾃动帮我们拼接成完整的http请求头.
处理cookie. 模拟登录
抓取⾃⼰收藏到书架上的⼩说信息
- 通过session会话获得
# 登录 -> 得到cookie
# 带着cookie 去请求到书架url -> 书架上的内容
# 必须得把上面的两个操作连起来
# 我们可以使用session进行请求 -> session你可以认为是一连串的请求. 在这个过程中的cookie不会丢失
import requests
# # 会话
# session = requests.session()
# data = {
# 相关验证信息
# }
#
# # 1. 登录
# url = "https://passport.17k.com/ck/user/login"
# session.post(url, data=data)
# # print(resp.text)
# # print(resp.cookies) # 看cookie
#
# # 2. 拿书架上的数据
# # 刚才的那个session中是有cookie的
# resp = session.get('https://user.17k.com/ck/author/shelf?page=1&appKey=2406394919')
#
# print(resp.json())
- 直接从请求网页上拿,同之前的useragent一样
import requests
resp = requests.get("https://user.17k.com/ck/author/shelf?page=1&appKey=2406394919", headers={
"Cookie":"网页中的cookie"
})
print(resp.json())
防盗链
防盗链: 溯源, 当前本次请求的上一级是谁
- 请求头里的 "Referer"字段
抓取梨视频视频数据
# 1. 拿到contId
# 2. 拿到videoStatus返回的json. -> srcURL
# 3. srcURL里面的内容进行修整
# 4. 下载视频
import requests
# 拉取视频的网址
url = "https://www.pearvideo.com/video_1721605"
contId = url.split("_")[1]
videoStatusUrl = f"https://www.pearvideo.com/videoStatus.jsp?contId={contId}"
headers = {
"User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.192 Safari/537.36",
# 防盗链: 溯源, 当前本次请求的上一级是谁
"Referer": url
}
resp = requests.get(videoStatusUrl, headers=headers)
dic = resp.json()
srcUrl = dic['videoInfo']['videos']['srcUrl']
systemTime = dic['systemTime']
srcUrl = srcUrl.replace(systemTime, f"cont-{contId}")
# 下载视频
with open("a.mp4", mode="wb") as f:
f.write(requests.get(srcUrl).content)
代理
当我们反复抓取⼀个⽹站时
- 由于请求过于频繁, 服务器很可能会将你的IP进⾏封锁来反爬. 应对⽅案就是通过⽹络代理的形式进⾏伪装
- 可以通过代理服务器访问,避免封锁
代理IP⼀般属于⼀个灰⾊产业,不可随意尝试
# 原理. 通过第三方的一个机器去发送请求
import requests
# 218.60.8.83:3129
proxies = {
"https": "https://218.60.8.83:3129"
}
resp = requests.get("https://www.baidu.com", proxies=proxies)
resp.encoding = 'utf-8'
print(resp.text)
爬网易云热评
# 1. 找到未加密的参数 # window.arsea(参数, xxxx,xxx,xxx)
# 2. 想办法把参数进行加密(必须参考网易的逻辑), params => encText, encSecKey => encSecKey
# 3. 请求到网易. 拿到评论信息
# 需要安装pycrypto: pip install pycrypto
from Crypto.Cipher import AES
from base64 import b64encode
import requests
import json
url = "https://music.163.com/weapi/comment/resource/comments/get?csrf_token="
# 请求方式是POST
data = {
"csrf_token": "",
"cursor": "-1",
"offset": "0",
"orderType": "1",
"pageNo": "1",
"pageSize": "20",
"rid": "R_SO_4_1325905146",
"threadId": "R_SO_4_1325905146"
}
# 服务于d的
f = "00e0b509f6259df8642dbc35662901477df22677ec152b5ff68ace615bb7b725152b3ab17a876aea8a5aa76d2e417629ec4ee341f56135fccf695280104e0312ecbda92557c93870114af6c9d05c4f7f0c3685b7a46bee255932575cce10b424d813cfe4875d3e82047b97ddef52741d546b8e289dc6935b3ece0462db0a22b8e7"
g = "0CoJUm6Qyw8W8jud"
e = "010001"
i = "d5bpgMn9byrHNtAh" # 手动固定的. -> 人家函数中是随机的
def get_encSecKey(): # 由于i是固定的. 那么encSecText就是固定的. c()函数的结果就是固定的
return "1b5c4ad466aabcfb713940efed0c99a1030bce2456462c73d8383c60e751b069c24f82e60386186d4413e9d7f7a9c7cf89fb06e40e52f28b84b8786b476738a12b81ac60a3ff70e00b085c886a6600c012b61dbf418af84eb0be5b735988addafbd7221903c44d027b2696f1cd50c49917e515398bcc6080233c71142d226ebb"
# 把参数进行加密
def get_params(data): # 默认这里接收到的是字符串
first = enc_params(data, g)
second = enc_params(first, i)
return second # 返回的就是params
# 转化成16的倍数, 位下方的加密算法服务
def to_16(data):
pad = 16 - len(data) % 16
data += chr(pad) * pad
return data
# 加密过程
def enc_params(data, key):
iv = "0102030405060708"
data = to_16(data)
aes = AES.new(key=key.encode("utf-8"), IV=iv.encode('utf-8'), mode=AES.MODE_CBC) # 创建加密器
bs = aes.encrypt(data.encode("utf-8")) # 加密, 加密的内容的长度必须是16的倍数
return str(b64encode(bs), "utf-8") # 转化成字符串返回,
# 处理加密过程
"""
function a(a = 16) { # 随机的16位字符串
var d, e, b = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789", c = "";
for (d = 0; a > d; d += 1) # 循环16次
e = Math.random() * b.length, # 随机数 1.2345
e = Math.floor(e), # 取整 1
c += b.charAt(e); # 去字符串中的xxx位置 b
return c
}
function b(a, b) { # a是要加密的内容,
var c = CryptoJS.enc.Utf8.parse(b) # # b是秘钥
, d = CryptoJS.enc.Utf8.parse("0102030405060708")
, e = CryptoJS.enc.Utf8.parse(a) # e是数据
, f = CryptoJS.AES.encrypt(e, c, { # c 加密的秘钥
iv: d, # 偏移量
mode: CryptoJS.mode.CBC # 模式: cbc
});
return f.toString()
}
function c(a, b, c) { # c里面不产生随机数
var d, e;
return setMaxDigits(131),
d = new RSAKeyPair(b,"",c),
e = encryptedString(d, a)
}
function d(d, e, f, g) { d: 数据, e: 010001, f: 很长, g: 0CoJUm6Qyw8W8jud
var h = {} # 空对象
, i = a(16); # i就是一个16位的随机值, 把i设置成定值
h.encText = b(d, g) # g秘钥
h.encText = b(h.encText, i) # 返回的就是params i也是秘钥
h.encSecKey = c(i, e, f) # 得到的就是encSecKey, e和f是定死的 ,如果此时我把i固定, 得到的key一定是固定的
return h
}
两次加密:
数据+g => b => 第一次加密+i => b = params
"""
# 发送请求. 得到评论结果
resp = requests.post(url, data={
"params": get_params(json.dumps(data)),
"encSecKey": get_encSecKey()
})
print(resp.text)
总结
小小励志
有些事你现在不做,一辈子都不会做了。
如果你想做一件事,全世界都会为你让路。
《搭车去柏林》