php抓取网页json数据(【干货】逆向过程2.1分析参数(篇章中若有讲解))

优采云 发布时间: 2022-01-16 18:15

  php抓取网页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:如果觉得本章对你有帮助,请关注、评论、点赞,谢谢!

0 个评论

要回复文章请先登录注册


官方客服QQ群

微信人工客服

QQ人工客服


线