JavaScript逆向爬取实战——使用Python实现列表页内容爬取

JavaScript逆向爬取—使用Python实现列表页内容爬取

1. 案例介绍

案例网址:https://spa6.scrape.center/, 如图所示:

Screenshot 2024-04-09 at 19.04.37

点击任意一步电影,观察一下URL的变化,如图所示:

Screenshot 2024-04-09 at 19.07.10

看到详情页URL包含了一个长字符串,看上去像是Base64编码的内容。

看看Ajax的请求,从列表页的第1页到第10页依次点击一下,观察Ajax请求是怎么样的,如图所示:

Screenshot 2024-04-09 at 19.13.56

可以看到,Ajax接口的URL里多了一个token,而且在不同的页码,token是不一样的,它们同样看似是Base64编码的字符串。而且这个接口还有时效性。如果我们把Ajax接口的URL直接复制下来,短期内可以访问,但是过段时间就无法访问了,会直接返回401状态码。

再看一下列表页的返回结果,比如打开第一个请求,看看第一部电影数据的返回结果,如图所示:

Screenshot 2024-04-09 at 19.20.35

第一部电影的URL是https://spa6.scrape.center/detail/ZWYzNCN0ZXVxMGJ0dWEjKC01N3cxcTVvNS0takA5OHh5Z2ltbHlmeHMqLSFpLTAtbWIx,看起来是Base64编码,对它进行解码,结果为ef34#teuq0btua#(-57w1q5o5–j@98xygimlyfxs*-!i-0-mb1,看起来似乎还是毫无规律,这个解码后的结果又是怎么来的呢?返回结果里也并不包含这个字符串,这是怎么构造的呢?其真实数据是通过Ajax加载的,那么Ajax请求又是怎样的呢?如下图所示:

Screenshot 2024-04-09 at 19.36.56

发现Ajax接口除了包含刚才说的URL中携带的字符串,又多了一个token,同样也是类似Base64编码的内容。这个网站有如下特点:

  • 列表页的Ajax接口参数带有加密的token
  • 详情页的URL带有加密id
  • 详情页的Ajax接口参数带有加密id和加密token

那么爬取的逻辑就是,必须把这些加密id和token构造出来才行,而且必须一步步来。首先构造出列表页Ajax接口的token参数,然后获取每部电影的数据信息,接着根据数据信息构造出加密id和加密token。

由于是网页,所以其加密逻辑一定藏在前端代码里,前端为了保护器接口加密逻辑不被轻易分析出来,会采取压缩、混淆等方式来加大分析等难度。

首先看网站的源代码,在网站上点击鼠标右键,此时会弹出快捷菜单,然后点击“查看源代码”选项,结果如下图所示:

Screenshot 2024-04-09 at 20.30.27

内容如下:


<!DOCTYPE html><html lang=en><head><meta charset=utf-8><meta http-equiv=X-UA-Compatible content="IE=edge"><meta name=viewport content="width=device-width,initial-scale=1"><link rel=icon href=/favicon.ico><title>Scrape | Movie</title><link href=/css/chunk-19c920f8.2a6496e0.css rel=prefetch><link href=/css/chunk-2f73b8f3.5b462e16.css rel=prefetch><link href=/js/chunk-19c920f8.c3a1129d.js rel=prefetch><link href=/js/chunk-2f73b8f3.8f2fc3cd.js rel=prefetch><link href=/js/chunk-4dec7ef0.e4c2b130.js rel=prefetch><link href=/css/app.ea9d802a.css rel=preload as=style><link href=/js/app.5ef0d454.js rel=preload as=script><link href=/js/chunk-vendors.77daf991.js rel=preload as=script><link href=/css/app.ea9d802a.css rel=stylesheet></head><body><noscript><strong>We're sorry but portal doesn't work properly without JavaScript enabled. Please enable it to continue.</strong></noscript><div id=app></div><script src=/js/chunk-vendors.77daf991.js></script><script src=/js/app.5ef0d454.js></script></body></html>

这是一个典型的SPA(单页Web应用)页面,其JavaScript文件名带有编码字符、chunk、vendors等关键字,这就是经过webpack打包压缩后的源代码,目前主流的前端开发框架Vue.js、React.js等的输出结果都是类似这样的。

再看一下JavaScript代码是什么样的。在开发者工具中打开Sources选项卡下的Page选项卡,然后打开js文件夹,在这里看到JavaScript的源代码,如图所示:

Screenshot 2024-04-09 at 21.02.04

随便复制一些出来,看看是什么样子的,结果如下:

(window['webpackJsonp'] = window['webpackJsonp'] || [])['push']([['chunk-19c920f8'], {
    '5a19': function(_0x1588d2, _0x49ff45, _0x493500) {},
    'c6bf': function(_0x1ff78d, _0x1a7aa3, _0x6392a5) {},
    'ca9c': function(_0x34ea17, _0x1d01c8, _0x1a974c) {
        'use strict';
        var _0x116bc9 = _0x1a974c('5a19')
          , _0x14ee23 = _0x1a974c['n'](_0x116bc9);
        _0x14ee23['a'];
    },
    'd504': function(_0x4c4705, _0x3c93b9, _0x4c22a6) {
        'use strict';
        _0x4c22a6['r'](_0x3c93b9);
        var _0x4b4f78 = function() {
            var _0x1dc0eb = this
              , _0x559ed0 = _0x1dc0eb['$createElement']
              , _0x28c6bc = _0x1dc0eb['_self']['_c'] || _0x559ed0;
            return _0x28c6bc('div', {
                'attrs': {
                    'id': 'index'
                }
            }, [_0x28c6bc('el-row', {
                'directives': [{
                    'name': 'loading',
                    'rawName': 'v-loading',
                    'value': _0x1dc0eb['loading'],
                    'expression': 'loading'
                }]
              ...
              ...

可以看到一些变量是十六进制字符串,而且代码全部被压缩了。要从这里找出token和id的构造逻辑。

2. 寻找列表页Ajax入口

简单介绍两种寻找入口的方式:

  • 全局搜索标志字符串

    • 全局搜索标志字符串

      重新打开列表页的Ajax接口,看一下请求的Ajax接口,如图所示:

      Screenshot 2024-04-09 at 21.10.37

​ 这里Ajax接口的URL为https://spa6.scrape.center/api/movie/?limit=10&offset=0&token=NzRlZWQwYjRiNDFmZGRiMWZkZj RiYjUyZTkxNTg2OGUxOWUxNDk2YiwxNzEyNjY4MTc4,可以看到带有limit、offset、token三个参数,关键就是找token,我 们就全局搜索是否存在token吧!点击开发者右上角“三个小竖点”选项卡,然后点击Search,如下图所示:

Screenshot 2024-04-10 at 14.42.44

​ 这样就进入全局搜索模式,搜索token,可以看到的确搜索到几个结果,如下图所示:

Screenshot 2024-04-09 at 21.19.24

​ 经过观察,下面的两个结果可能是我们想要的,点击第一个进入看看,此时定位到一个JavaScript文件,如下图所示:

Screenshot 2024-04-09 at 21.43.29

​ 这时可以看到整个代码都是经过压缩的,只有一行,不好看,点击左下角的{}按钮,格式化JavaScript代码,格式化后的结果如 下图所示:

Screenshot 2024-04-09 at 21.51.49

​ 这里我们再次定位到token,观察一下看到有limit、offset、token。然后观察其他的逻辑,基本上能确定这就是构造Ajax请求的 地方,如果不是的话,可以继续搜索其他文件观察分析。现在,就成功找到了混淆的入口,这是一个寻找入口的首选方法,如下 图所示:

Screenshot 2024-04-09 at 22.10.56

  • 设置Ajax断点

​ 我们可以在Sources选项卡右侧XHR/fetch Breakpoints处添加一个断点。首先点击+号,此时就会让我们输入匹配的URL内容。由于Ajax接口的形式是/api/movie/?limit=10…这样的格式,所以截取一段填进去就好了,这里填的就是/api/movie,如图所示:

Screenshot 2024-04-10 at 14.23.38

​ 重新点击格式化按钮{},格式化代码,看看断点在哪里,如下图所示。这里有一个字符send,我们可以初步猜测它相当于发送Ajax请求的一瞬间。

Screenshot 2024-04-10 at 14.26.15

​ 怎样回溯查找相关逻辑的方法,点击右侧的Call Stack,这里记录了JavaScript方法逐层调用的过程,如下图所:

Screenshot 2024-04-10 at 14.32.01 当前指向的是一个名为anonymous(也就是匿名)的调用,在它的下方显示了调用anonymous的方法,名字叫做_0x29474e,然后在下一层就显示了调用_0x2ad882方法的方法,以此类推。继续找下去,注意观察类似token这样的信息,就能找到对应的位置了。最后,找到了onFetchData,这个方法实现了token的构造逻辑,就成功找到了token参数构造位置了。如下图所示:

Screenshot 2024-04-10 at 14.39.21

3. 寻找列表页面的加密逻辑

​ 根据上面的回溯查找,已经找到了token的位置了,可以观察这个token对应的变量,它叫做_0x263439,所以关键就是看看这个变量哪里来的。怎么找呢?添加断点就好了。

取消上面设置的断点,看一下这个变量是哪里生成的,如下图所示:

Screenshot 2024-04-10 at 14.51.32

​ 设置了新断点,刷新网页,发现网页停在新的断点上面,如下图所示:

Screenshot 2024-04-10 at 15.09.23

​ 这时我们就可以观察正在运行的一些变量了,比如把鼠标放在各个变量上,可以看到变量的值和类型;把鼠标放在变量_0x2fa7bd上,会有一个浮窗显示,如下图所示:

Screenshot 2024-04-10 at 15.13.58

​ 另外,还可以在右侧的Watch面板中添加想要查看的变量,如这行代码的内容为:

, _0x263439 =Object(_0x2fa7bd['a'])(this['$store']['state']['url']['index']);

​ 我们比较感兴趣的可能就是_0x51c425,还有this里的$store属性。展开Watch面板,然后点击+号,把想看的变量添加到Watch面板里面,如下图所示:

Screenshot 2024-04-10 at 15.21.22

​ 可以发现,_0x2fa7bd是一个对象,它具有属性a,其值是一个方法。this[‘$store’][‘state’][‘url’][‘index’]的值其实就是/api/movie,即Ajax请求URL的Path。_0x263439就是调用前者的方法传入/api/movie得到的。如下图所示:

Screenshot 2024-04-10 at 15.25.25

​ 下一步就是去寻找这个方法。我们可以把Watch面板的_0x2fa7bd展开,这里会显示的FunctionLocation就是这个函数的代码位置,如下图所示:

Screenshot 2024-04-10 at 15.28.26

​ 点击进入,这时我们就进入一个新的名字为_0x456254的方法里,在这个方法中,应该就有token的生成逻辑了。添加断点,然后点击面板右上角蓝色箭头状的Resume script execution按钮,如下图所示:

Screenshot 2024-04-10 at 15.35.38

接下来,不断进行单步调试,观察这里的执行逻辑和每一步调试的结果都有啥变化,如下图所示:

Screenshot 2024-04-10 at 15.49.25

根据上面的单步调试,在Watch面板下看到每步具体结果,总结出这个token的构造逻辑,如下:

  • 传入的/api/movie会构造一个初始化列表,将变量命名_0x31a891
  • 获取当前的时间戳,命名为_0x5da681,调用push方法将其添加到_0x31a891变量代表的列表中
  • 将_0x31a891变量用,拼接,然后进行SHA1编码,命名为_0xf7c3c7
  • 将_0xf7c3c7(SHA1编码的结果)和_0x5da681(时间戳)用逗号拼接,命名为_0x3c8435
  • 将_0x3c8435进行Base64编码,命名为_0x104b5b,得到最后的token

4. 使用Python实现列表页的爬取

实现这个逻辑,需要借助两个库:一个是hashlib,它提供了sha1方法;另外一个是base64库,它提供了b64encode方法对结果进行Base64编码。实现代码如下:

import hashlib
import time
import base64
from typing import List, Any
import requests

INDEX_URL = 'https://spa6.scrape.center/api/movie?limit={limit}&offset={offset}&token={token}'
LIMIT = 10
OFFSET = 0

def get_token(args: List[Any]):
    timestamp = str(int(time.time()))
    args.append(timestamp)
    sign = hashlib.sha1(','.join(args).encode('utf-8')).hexdigest()
    return base64.b64encode(','.join([sign, timestamp]).encode('utf-8')).decode('utf-8')

args = ['/api/movie']
token = get_token(args=args)
index_url = INDEX_URL.format(limit=LIMIT, offset=OFFSET, token=token)
response = requests.get(index_url)
print('response', response.json())			

根据上面的逻辑加密流程实现出来了,这里先模拟爬取了第一页的内容,最后运行一下,可以得到最终的输出结果了。如下所示:

/usr/bin/python3 /Users/bruce_liu/PycharmProjects/崔庆才--爬虫/11章JavaScript逆向爬虫/python爬取列表页.py
response {'count': 102, 'results': [{'id': 1, 'name': '霸王别姬', 'alias': 'Farewell My Concubine', 'cover': 'https://p0.meituan.net/movie/ce4da3e03e655b5b88ed31b5cd7896cf62472.jpg@464w_644h_1e_1c', 'categories': ['剧情', '爱情'], 'published_at': '1993-07-26', 'minute': 171, 'score': 9.5, 'regions': ['中国内地', '中国香港']}, {'id': 2, 'name': '这个杀手不太冷', 'alias': 'Léon', 'cover': 'https://p1.meituan.net/movie/6bea9af4524dfbd0b668eaa7e187c3df767253.jpg@464w_644h_1e_1c', 'categories': ['剧情', '动作', '犯罪'], 'published_at': '1994-09-14', 'minute': 110, 'score': 9.5, 'regions': ['法国']}, {'id': 3, 'name': '肖申克的救赎', 'alias': 'The Shawshank Redemption', 'cover': 'https://p0.meituan.net/movie/283292171619cdfd5b240c8fd093f1eb255670.jpg@464w_644h_1e_1c', 'categories': ['剧情', '犯罪'], 'published_at': '1994-09-10', 'minute': 142, 'score': 9.5, 'regions': ['美国']}, {'id': 4, 'name': '泰坦尼克号', 'alias': 'Titanic', 
.....
.....

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/533551.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Ant Design Vue 表单验证手机号的正则

代码&#xff1a; pattern: /^1[3456789]\d{9}$/ 1. <a-form-item label"原手机号" v-bind"validateInfos.contactTel"><a-inputstyle"width: 600px"allow-clear:maxlength"20"placeholder"请输入原手机号"v-mo…

吴恩达机器学习ex3 python实现(详细注释)

文章目录 1、多分类1.1 数据集1.2 数据可视化1.3 矢量化 Logistic 回归1.3.1 向量化成本函数1.3.2 矢量化梯度 1.4 一对多分类 2.神经网络 1、多分类 在本练习中&#xff0c;您将使用逻辑回归和神经网络来识别手写数字&#xff08;从 0 到 9&#xff09;。 自动手写数字识别如…

马云支持阿里改革,预见AI时代的到来将带来巨大的变化

&#x1f989; AI新闻 &#x1f680; 马云支持阿里改革&#xff0c;预见AI时代的到来将带来巨大的变化 摘要&#xff1a;马云在阿里内网发表《致改革 致创新》帖子&#xff0c;这是其退休五年来首次深度分享对阿里改革创新及未来的看法。文章中&#xff0c;马云对蔡崇信和吴泳…

微服务-4 Nacos

目录 一、注册中心 二、配置管理 1. 添加配置 2. 配置自动刷新 3. 多环境配置共享​编辑 一、注册中心 服务列表&#xff1a; 服务详情&#xff1a; 二、配置管理 1. 添加配置 (1). 在 nacos 界面中添加配置文件&#xff1a; 配置列表&#xff1a; 配置详情&#xff1a;…

【C++学习】C++11新特性(第二节)—— 右值引用与移动语义超详解

文章目录 文章简介二.右值引用1.什么是左值&#xff0c;什么是右值&#xff1f;什么是左值引用&#xff0c;什么是右值引用&#xff1f;2.左值引用与右值引用比较 三.右值引用使用场景和意义1.左值引用的使用场景&#xff1a;2.左值引用的短板&#xff1a;3.右值引用与移动构造…

Unity之Unity面试题(五)

内容将会持续更新&#xff0c;有错误的地方欢迎指正&#xff0c;谢谢! Unity之Unity面试题&#xff08;五&#xff09; TechX 坚持将创新的科技带给世界&#xff01; 拥有更好的学习体验 —— 不断努力&#xff0c;不断进步&#xff0c;不断探索 TechX —— 心探索、心进取…

LVM逻辑卷

LVM逻辑卷 一.逻辑卷简介 LVM 是 Logical Volume Manager 的简称&#xff0c;译为中文就是逻辑卷管理。它是 Linux 下对硬盘分区的一种管理机制。LVM 适合于管理大存储设备&#xff0c;并允许用户动态调整文件系统的大小。此外&#xff0c;LVM 的快照功能可以帮助我们快速备份…

【AI大模型应用开发】【LangChain系列】 LangChain框架介绍,实现LangChain的Hello World

AI时代&#xff0c;相信大家或多或少都听过 LangChain 的大名。通俗的说&#xff0c;LangChain是一个面向大模型的开发框架&#xff08;SDK&#xff09;。 目前 LangChain 仍在快速迭代中&#xff0c;所以在使用中要时刻关注你所使用的版本和接口变更。 0. 认识LangChain框架 从…

Kafka 消费端消费重试和死信队列

系列文章目录 文章目录 系列文章目录前言前言 前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家。点击跳转到网站,这篇文章男女通用,看懂了就去分享给你的码吧。 Spring-Kafka 提供消费重试的机制。当消息消费失败的时候,Spring-Kafka …

【QT】pro文件里添加又删除LIBS不影响运行的原因

我发现个问题啊&#xff0c;如果运行项目&#xff0c;发现报错&#xff0c;缺少某dll&#xff0c;接着你在pro文件里加上win32:LIBS -lOpengl32&#xff08;举个例子&#xff09;&#xff0c;接着可以运行了&#xff0c;接着把这行删掉&#xff0c;再运行&#xff0c;仍然可以…

中介者模式【行为模式C++】

1.简介 中介者模式是一种行为设计模式&#xff0c; 能让你减少对象之间混乱无序的依赖关系。 该模式会限制对象之间的直接交互&#xff0c; 迫使它们通过一个中介者对象进行合作。 亦称&#xff1a; 调解人、控制器、Intermediary、Controller、Mediator 2.示例 中介者模式在…

计算机组成原理(IO,输入输出)

1、“821.2016T1(1)”&#xff0c;表示821真题&#xff0c;2016年的题&#xff0c;T1是 选择题/填空题/大题 的第一题&#xff0c;其他类似标记也是相通 2、个人小白总结自用&#xff0c;不一定适用于其他人&#xff0c;请自行甄别 3、有任何疑问&#xff0c;欢迎私信探讨&…

uniapp开发h5端使用video播放mp4格式视频黑屏,但有音频播放解决方案

mp4格式视频有一些谷歌播放视频黑屏&#xff0c;搜狗浏览器可以正常播放 可能和视频的编码格式有关&#xff0c;谷歌只支持h.264编码格式的视频播放 将mp4编码格式修改为h.264即可 转换方法&#xff1a; 如果是自己手动上传文件可以手动转换 如果是后端接口调取的地址就需…

【leetcode面试经典150题】36. 旋转图像(C++)

【leetcode面试经典150题】专栏系列将为准备暑期实习生以及秋招的同学们提高在面试时的经典面试算法题的思路和想法。本专栏将以一题多解和精简算法思路为主&#xff0c;题解使用C语言。&#xff08;若有使用其他语言的同学也可了解题解思路&#xff0c;本质上语法内容一致&…

【Ansible自动化运维】Ansible入门基础信息【安装配置、常用命令与模块】

介绍安装配置注意事项yum安装验证安装配置host配置主机清单配置主控端被控端 常用模块命令组成command模块shell模块copy模块script模块 日志信息最后 介绍 Ansible 是一个开源 IT 自动化引擎&#xff0c;可自动执行供应、配置管理、应用程序部署、编排和许多其他 IT 流程。它可…

MySQL分库分表的方式有哪些

目录 一、为什么要分库分表 二、什么是分库分表 三、分库分表的几种方式 1.垂直拆分 2. 水平拆分 四、分库分表带来的问题 五、分库分表技术如何选型 一、为什么要分库分表 如果一个网站业务快速发展&#xff0c;那这个网站流量也会增加&#xff0c;数据的压力也会随之而…

护眼台灯哪个牌子好?护眼台灯十大排名,看看业内人怎么选!

眼镜已成为许多人日常生活中不可或缺的一部分&#xff0c;但戴眼镜并不总是方便的。现在许多家长也越来越关注孩子的视力问题&#xff0c;有些学生的书桌上已经放置上了护眼台灯。这种台灯提供柔和的光线&#xff0c;有助于改善照明环境&#xff0c;保护眼睛健康。然而&#xf…

使用jQuery实现购物界面的动态效果

实现功能&#xff1a;&#xff08;购物车以表格的格式展示&#xff09; 1 全选框和复选框之间的联动关系&#xff1a; 点击全选&#xff0c;所有复选框checked状态为true 点击复选框&#xff0c;全选框状态实时更新 2 点击删除按钮&#xff0c;删除对应的行 3 点击删除所选…

VUE3的有关知识

学习vue3的原因 在vue2当中的组件的实例,都是data一块,computed一块,当我们去找某一变量相关的则十分麻烦,vue3是组合式API,vue2是选项式, vue3的优点: 1)组合式更易维护 2)更快的速度 3)更小的体积 4)更好的响应式proxy 使用vue3相关脚手架创建项目 步骤: 1)node -v node版…

【CVE-2010-2883】进行钓鱼攻击的研究

最近作业中研究APT攻击&#xff0c;了解到2011年前后披露的LURID-APT&#xff0c;其中敌手利用了各种版本的文件查看器的漏洞实现攻击。CVE-2010-2883就是其中被利用的一个adobe reader的漏洞。特此复现&#xff0c;更好的研究和防范APT攻击。 本文仅仅是对相关漏洞利用的学习…