php抓取网页json数据(【干货】逆向过程2.1分析参数(篇章中若有讲解))
优采云 发布时间: 2022-01-16 18:15php抓取网页json数据(【干货】逆向过程2.1分析参数(篇章中若有讲解))
文章目录
内容
文章目录
前言
一、分析页面
二、逆过程
2.1 分析参数
2.2sign_code 值
2.3 折扣码
三、 请求数据,处理Json数据,本地保存图片
3.1 导入库
3.2 生成时间戳和参数
3.3 发出请求
四、附上完整代码
总结
前言
之前做的一个站最近整理了一下,写了一个文章记录,也可以给需要的朋友做个参考。(文中解释如有错误,欢迎评论区指正
目标网站: -领先的时尚摄影平台,摄影视频,摄影爱好者分享作品和技巧的首选,个人空间
一、分析页面
首先进入页面,确定我们要爬取的目标
打开页面后发现 网站 是通过惰性方式加载图片的。
PS:延迟加载是指在请求页面时,只加载可见区域的图片,不加载其他部分的图片。只有当这些图片出现在可视区域时,才会动态加载这些图片,从而节省网络带宽,提高初始加载速度。
不过我们暂时先不管它,打开f12抓包,看看这些图片在哪里。小技巧,先打开f12,清除后点击下一页。由于页面是延迟加载的,我们只需要向下滑动即可。
抓包后,下一步进入主题
二、逆过程2.1 分析参数
单纯看头信息和传入参数,直接请求数据肯定不可行,有反爬的方法。
我们来看看表头信息和传入参数(重点关注这个Form Data表单数据
把它复制出来刷新比较一下,总结出比较重要的数据的含义。
"ctime" : 时间戳(你可以使用python自己生成它
"length" : 我们要加载的张数(也可以理解为我们要抓取的张数
"sign_code" : 加密参数(最重要的一个
“works_category”:照片类型的参数(勾选是主页上的照片分类,然后是123...
2.2sign_code 值
这里我们直接使用全局搜索的方式来查找加密位置。 js文件只有一个。我们直接点进去看看吧。
一进来就可以看到sign_code的加密位置,在13479和13490的下一个断点刷新看看是怎么生成的。
分析这几行js代码
var o = JSON.stringify(e) # 只是将o转换为字符串的操作。经过多次测试,o是上面写的prama参数文章
("param":{"start":20,"length":20,"works_category":"1","time_point":1641981023})
n = t("poco_" + o + "_app"); #通过t函数加密一个字符串
n = n.substr(5, 19); # 取一部分加密数据作为sign_code值
定位到这里之后,我们根据经验可以看出这应该是加密的位置。我们可以尝试将这整个函数扣除,然后在本地运行,看看能否生成我们想要的sign_code值。
2.3 折扣码
下面是完整的js代码扣除,最后手动写了一个调用函数
function r(n, t) {
var r = (65535 & n) + (65535 & t)
, e = (n >> 16) + (t >> 16) + (r >> 16);
return e > 32 - t
}
function u(n, t, u, o, c, f) {
return r(e(r(r(t, n), r(o, f)), c), u)
}
function o(n, t, r, e, o, c, f) {
return u(t & r | ~t & e, n, t, o, c, f)
}
function c(n, t, r, e, o, c, f) {
return u(t & e | r & ~e, n, t, o, c, f)
}
function f(n, t, r, e, o, c, f) {
return u(t ^ r ^ e, n, t, o, c, f)
}
function i(n, t, r, e, o, c, f) {
return u(r ^ (t | ~e), n, t, o, c, f)
}
function a(n, t) {
n[t >> 5] |= 128 >> 9 > 5] >>> t % 32 & 255);
return r
}
function g(n) {
var t, r = [];
for (r[(n.length >> 2) - 1] = void 0,
t = 0; t < r.length; t += 1)
r[t] = 0;
for (t = 0; t < 8 * n.length; t += 8)
r[t >> 5] |= (255 & n.charCodeAt(t / 8)) 16 && (u = a(u, 8 * n.length)),
r = 0; 16 > r; r += 1)
o[r] = 909522486 ^ u[r],
c[r] = 1549556828 ^ u[r];
return e = a(o.concat(g(t)), 512 + 8 * t.length),
h(a(c.concat(e), 640))
}
function v(n) {
var t, r, e = "0123456789abcdef", u = "";
for (r = 0; r < n.length; r += 1)
t = n.charCodeAt(r),
u += e.charAt(t >>> 4 & 15) + e.charAt(15 & t);
return u
}
function s(n) {
return unescape(encodeURIComponent(n))
}
function C(n) {
return d(s(n))
}
function A(n) {
return v(C(n))
}
function m(n, t) {
return l(s(n), s(t))
}
function p(n, t) {
return v(m(n, t))
}
function b(n, t, r) {
return t ? r ? m(t, n) : p(t, n) : r ? C(n) : A(n)
};
function getsign(o){
n = b("poco_" + o + "_app");
n = n.substr(5, 19);
return n
}
经过测试,可以在本地成功运行,得到我们想要的加密数据。其实到这里已经差不多完成了90%,接下来就是请求数据并抓包了。
三、请求数据,处理Json数据,本地保存图片3.1 导入库
import requests # 请求数据
import time # 生成时间戳
import execjs # 第三方类库来执行js语句
3.2 生成时间戳和参数
time_point = int(time.time())
o = '{"start":0,"length":20,"works_category":"1","time_point":'+str(time_point)+'}'
with open('D:/poco.js', 'r', encoding='utf-8') as f: # 读取扣下来保存到本地的js代码
js_data = f.read()
js_obj = execjs.compile(js_data)
sign_code = js_obj.call('getsign',o) # 第一个参数是函数名,第二个是传入的参数
# print("sign_code")
这里的长度参数是请求的数据量。我只抓了20张,可以根据自己的需要更换。并且works_category参数也根据自己的需要而改变。
3.3 发出请求
# 把sign_code和时间戳拼接到传入的参数中
data = {
'req': '{"version":"1.1.0","app_name":"poco_photography_web","os_type":"weixin","is_enc":0,"env":"prod","ctime":'+str(int(time.time()*1000))+',"param":{"start":0,"length":20,"works_category":"1","time_point":'+str(time_point)+'},"sign_code":"'+str(sign_code)+'"}',
'host_port': 'https://photo.poco.cn'
}
由于数据是json格式,所以我们要的图片地址在img中的list下data
json数据格式可以这样取,代码如下
response = requests.post(url,headers=headers,data=data).json()['data']['list']
for i in response:
img = i['img']
urls = 'http:' + str(img) # 进行简单拼接成url格式
使用for循环将请求的图片保存到本地
with open(f'D:/POCO图库/img{num}.jpg', 'wb') as f:
print('正在下载第{}张'.format(num))
f.write(content)
你完成了
四、附上完整代码
# _*_ coding:UTF-8 _*_
# @Software : PyCharm
import requests
import time
import execjs
time_point = int(time.time())
o = '{"start":0,"length":20,"works_category":"1","time_point":'+str(time_point)+'}'
with open('D:/poco.js', 'r', encoding='utf-8') as f:
js_data = f.read()
js_obj = execjs.compile(js_data)
sign_code = js_obj.call('getsign',o)
# print(sign_code)
url = 'https://web-api.poco.cn/v1_1/rank/get_homepage_recommend_list'
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.198 Safari/537.36',
'Referer': 'https://photo.poco.cn/?classify_type=1&works_type=medal',
'Origin': 'https://photo.poco.cn'
}
data = {
'req': '{"version":"1.1.0","app_name":"poco_photography_web","os_type":"weixin","is_enc":0,"env":"prod","ctime":'+str(int(time.time()*1000))+',"param":{"start":0,"length":20,"works_category":"1","time_point":'+str(time_point)+'},"sign_code":"'+str(sign_code)+'"}',
'host_port': 'https://photo.poco.cn'
}
response = requests.post(url,headers=headers,data=data).json()['data']['list']
num = 1
for i in response:
img = i['img']
urls = 'http:' + str(img)
content = requests.get(urls).content
with open(f'D:/POCO图库/img{num}.jpg', 'wb') as f:
print('正在下载第{}张'.format(num))
f.write(content)
num += 1
print('完')
总结
吐槽一下最新版的谷歌浏览器(最好用旧版更稳定),天天死机,调试js的时候死机。好在这个网站的加密不是很深。
中途扣除的js代码尝试在谷歌浏览器中运行,发现会报错,说我的方法未定义,应该是bug,然后切换到360极速浏览器,就可以正常运行了。
再次声明,本文文章仅供学习,不做任何商业用途,做一个友好的爬虫。
PS:如果觉得本章对你有帮助,请关注、评论、点赞,谢谢!