爬虫案例:建设库JS逆向

爬虫流程

1. 确定目标网址和所需内容

https://www.jiansheku.com/search/enterprise/

只是个学习案例,所以目标就有我自己来选择,企业名称,法定代表人,注册资本,成立日期
在这里插入图片描述

2. 对目标网站,进行分析

  • 动态内容分析:

    JS和Ajax请求:确定页面是否使用JavaScript动态加载内容,如果是,需要分析Ajax请求以获取数据的API。
    在这里插入图片描述进行页面切换,抓去Ajax,发现page里面的response携带这我们所需要的数据

    找到动态变化值,一般在headers,或者payload中,动态变化值,可能就是影响批量爬虫的关键
    例中的payload是明文数据,headerssigntimestamp是动态变化值

3 .找到加密的入口

靠经验,运气,猜测,分析代码,观察数据,调试代码,逆向分析,等等。
使用关键字搜索,断点,调用堆栈等方法。

这里我使用关键字搜索
使用正则表达式搜索缩小搜索范围,勾选“Use Regular Expression”或.*并输入正则表达式,如\bSign\b—\b确定搜索边界
像Math.sign这种是js的数学库文件,可以直接排除,就10几个,慢慢排查,使用断点调试
在这里插入图片描述
这里就是目标,注意这里使用了js的逗号表达式,想要查看结果悬浮,或者在控制台中查看,注意你要在断点的作用域内,函数是有生命周期的
在这里插入图片描述

4. 扣js代码

复制js代码,模拟浏览器加密过程

这里我发现一个好用的小技巧,使用单步调试,从断点开始出发查看经过的函数基本都是我们所需的js代码,途中会跳转到其他的js文件(webpack)然后回来就可一看见MD5加密的算法了
在这里插入图片描述

5. 写代码

  1. 请求模拟
  2. 获取js逆向值
  3. py调用js
  4. 数据清洗
  5. 数据存储
  6. 处理反爬机制(ip封禁)

注意事项

  1. 下载packages的时候过慢,pip和node我都会给出镜像源
  2. 我使用的是Linux:pip install PyExecJS2,Windows:pip install PyExecJS,不行就两个都试一遍
  3. google在浏览器开发者工具中不让粘贴,可在控制台输入allow pasting
  4. 本来打算以csv文件保存,但是爬取页数一多,就打不开csv文件,所以就保存为txt
  5. 最好不要使用异步模块,这个爬取的速度不会太慢,爬取的太快服务区可能不会响应
  6. 不要大量爬去,该网站会封IP(使用代理池就可以了)

packages

  • pip
# 模拟浏览器发送请求
pip install requests -i https://mirrors.aliyun.com/pypi/simple/

# 在py中调用js
pip install PyExecJS2 -i https://mirrors.aliyun.com/pypi/simple/

# 方便实时预览进度
pip install requests -i https://mirrors.aliyun.com/pypi/simple/
  • npm
# 使用淘宝源
npm config set registry https://registry.npm.taobao.org

# 我遇到了证书过期(可能是我设置的是外国时区,使用的是国内的源),设置 npm 忽略 SSL 证书错误
npm config set strict-ssl false

npm install crypto-js

python code

import requests
import time
import execjs
import json
from tqdm import tqdm

def fetch_data(page, timer):
    json_data = {
        'eid': '',
        'achievementQueryType': 'and',
        'achievementQueryDto': [],
        'personnelQueryDto': {
            'queryType': 'and',
        },
        'aptitudeQueryDto': {
            'queryType': 'and',
            'nameStr': '',
            'aptitudeQueryType': 'and',
            'businessScopeQueryType': 'or',
            'filePlaceType': '1',
            'aptitudeDtoList': [
                {
                    'codeStr': '',
                    'queryType': 'and',
                    'aptitudeType': 'qualification',
                },
            ],
            'aptitudeSource': 'new',
        },
        'page': {
            'page': page,
            'limit': 20,
            'field': '',
            'order': '',
        },
    }

    get_sign = execjs.compile(open('jiansheku.js').read()).call('get_sign', json_data, timer)

    cookies = {
        'Hm_lvt_03b8714a30a2e110b8a13db120eb6774': '1718020163',
        'Hm_lpvt_03b8714a30a2e110b8a13db120eb6774': '1718020163',
        'HWWAFSESTIME': '1718020163509',
        'HWWAFSESID': '228fb8efd82b43680e',
    }

    headers = {
        'accept': 'application/json, text/plain, */*',
        'accept-language': 'en-US,en;q=0.9',
        'content-type': 'application/json;charset=UTF-8',
        'devicetype': 'PC',
        'origin': 'https://www.jiansheku.com',
        'page': 'search-enterprise',
        'priority': 'u=1, i',
        'referer': 'https://www.jiansheku.com/',
        'sec-ch-ua': '"Google Chrome";v="125", "Chromium";v="125", "Not.A/Brand";v="24"',
        'sec-ch-ua-mobile': '?0',
        'sec-ch-ua-platform': '"Linux"',
        'sec-fetch-dest': 'empty',
        'sec-fetch-mode': 'cors',
        'sec-fetch-site': 'same-site',
        'sign': get_sign,
        'timestamp': str(timer),
        'user-agent': 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/125.0.0.0 Safari/537.36',
    }

    try:
        response = requests.post('https://capi.jiansheku.com/nationzj/enterprice/page', cookies=cookies, headers=headers, json=json_data)
        response.raise_for_status()  # 检查请求是否成功
        print(f"Page {page} fetched successfully")
        print(response.text)  # 打印响应内容以检查数据格式
        return response.json()
    except requests.RequestException as e:
        print(f"Request failed for page {page}: {e}")
        return None

def save_to_txt(all_records, filename='enterprise_data.txt'):
    with open(filename, 'w', encoding='utf-8') as file:
        headers = ['Name', 'Legal Person', 'Registered Capital', 'LiceValidity Date']
        file.write('\t'.join(headers) + '\n')
        for record in all_records:
            line = f"{record['name']}\t{record['legalPerson']}\t{record['registeredCapital']}\t{record['liceValidityDate']}\n"
            file.write(line)
    print(f"数据已保存到 {filename} 文件中")

def main():
    timer = time.time() * 1000
    max_pages = 5  # 设置要遍历的最大页数
    all_records = []

    for page in tqdm(range(1, max_pages + 1)):
        data = fetch_data(page, timer)
        if data and 'data' in data and 'list' in data['data']:
            records = [{
                'name': item['name'],
                'legalPerson': item.get('legalPerson', ''),
                'registeredCapital': item.get('registeredCapital', ''),
                'liceValidityDate': item.get('liceValidityDate', '')
            } for item in data['data']['list']]
            all_records.extend(records)
        else:
            print(f"No data found for page {page}")

    if all_records:
        # 将记录保存到txt文件
        save_to_txt(all_records)
    else:
        print("No records to save.")

if __name__ == "__main__":
    main()

js code

const Cryptojs = require("crypto-js")

ku = function(e, t, time) {
    var n = t + e + time;
    // 这里的MD5是加密算法,加密后的字符串就是签名
    return n = Cryptojs.MD5(n).toString()    // 经过单点调试,发现这里是加密算法构成的位置
}

Lu = function e(t) {
    var n;
    if (Array.isArray(t)) {
        for (var r in n = new Array,
        t) {
            var o = t[r];
            for (var i in o)
                null == o[i] ? delete t[r][i] : Array.isArray(t[r][i]) && e(t[r][i])
        }
        return n = t,
        JSON.stringify(n).replace(/^(\s|")+|(\s|")+$/g, "")
    }
    return n = t && t.constructor === Object ? JSON.stringify(t) : t
}

Tu = function(e) {
    var t = new Array
      , n = 0;
    for (var i in e)
        t[n] = i,
        n++;
    return t.sort()
}

Ou = function(e) {
    var t = Tu(e)
      , n = "";
    for (var i in t) {
        var r = Lu(e[t[i]]);
        null != r && "" != r.toString() && (n += t[i] + "=" + r + "&")
    }
    return n
}

function get_sign(param, time) {
//     param = {
//     'eid': '',
//     'achievementQueryType': 'and',
//     'achievementQueryDto': [],
//     'personnelQueryDto': {
//         'queryType': 'and',
//     },
//     'aptitudeQueryDto': {
//         'queryType': 'and',
//         'nameStr': '',
//         'aptitudeQueryType': 'and',
//         'businessScopeQueryType': 'or',
//         'filePlaceType': '1',
//         'aptitudeDtoList': [
//             {
//                 'codeStr': '',
//                 'queryType': 'and',
//                 'aptitudeType': 'qualification',
//             },
//         ],
//         'aptitudeSource': 'new',
//     },
//     'page': {
//         'page': 3,
//         'limit': 20,
//         'field': '',
//         'order': '',
//     },
// };
//     time = (new Date).getTime();
    t = Ou(param);

return ku("ghaepVf6IhcHmgnk4NCTXLApxQkBcvh1", ku("mwMlWOdyM7OXbjzQPulT1ndRZIAjShDB", ku("ZuSj0gwgsKXP4fTEz55oAG2q2p1SVGKK", t, time), time), time);
}

// console.log(get_sign());

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

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

相关文章

甲板上的战舰|模拟?|每日一题|chatgpt结合更正

文章目录 我的天免费的4o太好用了我的天免费的4o太好用了我的天免费的4o太好用了题目详情思路:关键:chatGPT配合纠正错误思路正确代码: 我的天免费的4o太好用了 我的天免费的4o太好用了 我的天免费的4o太好用了 重要的事情说三遍 题目详情…

HK1-BOX X3刷UBUNTU 24.04,并开启WIFI

端午刚好有点时间,顺便把改完散热的HK1-BOX刷了个最新OC版的UBUNTU 24,这里记录下操作的步骤: 准备材料 HK1-BOX S905X3:注意X4的不行固件没匹配的。建议先改完散热,不然作为7X24小时的机器长时间高温还是很伤硬件的…

什么是SOLIDWORKS科研版

随着科技的不断进步,工程设计和科学研究变得越来越复杂,需要更强大的工具来满足需求。SOLIDWORKS科研版就是在这样的背景下诞生的,它为科研人员和工程师提供了一套全方面、快捷的解决方案,以应对各种科研和工程挑战。 SOLIDWORKS科…

Keil uVision5复制到Word文档后乱码的解决办法

一、问题出现状况 在做嵌入式实验时,我发现在Keil uVision5中正常编写的代码和注释,写入实验报告(word)中其中文注释就会产生乱码,非常不美观,并且使代码变得杂乱。 如下:Keil uVision5中注释…

RK3588 Debian11进行源码编译安装Pyqt5

RK3588 Debian11进行源码编译安装Pyqt5 参考链接 https://blog.csdn.net/qq_38184409/article/details/137047584?ops_request_misc%257B%2522request%255Fid%2522%253A%2522171808774816800222841743%2522%252C%2522scm%2522%253A%252220140713.130102334…%2522%257D&…

Java面试题--JVM大厂篇之深入了解Java虚拟机(JVM):工作机制与优化策略

引言: Java虚拟机(Java Virtual Machine,简称JVM)是Java程序员绕不开的主题。作为Java语言的执行平台,JVM不仅为Java程序提供了平台无关性,还承担了内存管理、线程管理和垃圾回收等复杂任务。了解JVM的工作…

.NET 全局过滤器

过滤器流程图: 过滤器描述: 1、Authorization Filter : 是五种Filter中优先级最高的,通常用于验证Request合不合法、用户身份是否被认证(然后授权等)、复杂的权限角色认证、登录授权等操作。 2、Resource Filter: 会在Authorization之后,Model Binding之…

[Algorithm][动态规划][二维费用的背包问题][一和零][盈利计划]详细讲解

目录 0.原理讲解1.一和零1.题目链接2.算法原理详解3.代码实现 2.盈利计划1.题目链接2.算法原理详解3.代码实现 0.原理讲解 本质仍然是背包问题,但是相较于普通的背包问题,只是限制条件多了一个而已 1.一和零 1.题目链接 一和零 2.算法原理详解 思路&…

Linux操作系统:Redis在虚拟环境下的安装与部署

Redis下载方法 最近部署项目的时候用到了Redis,自己在安装的时候也碰到了一些列问题最终安装成功,记录一下自己的安装历程。前期准备: 服务器Linux版本:Centos8.4 64位(http://isoredirect.centos.org/centos/8/isos/…

esp32s3-gc9a01-lvgl

前言 近期做了一个项目是使用esp32s3 准亿科技的TFT屏幕 该屏幕使用的驱动IC为:GC9A01 通讯方式是:4线SPI , 三线spi和四线SPI区别在于:是否使用D/C信号线 开发LCD屏幕驱动, 可以参考乐鑫官网LCD显示屏指南 SPI 一共有4种工作模式. 根据接线 , 驱动方式的不同. 可分3 , …

Spring boot 使用AbstractRoutingDataSource实现数据源动态切换

目录 一、AbstractRoutingDataSource 二、具体实现 1、pom.xml 2、新建UserMapper 3、在spring boot 启动类上添加扫描mapper注解 4、在配置文件 application.properties 中添加多个(我这里是两个)数据源的配置信息 5、集成动态数据源模块 5.1、新建注解 CurDataSource…

JAVA动态表达式:Antlr4 G4 模板 + 读取字符串表达式结构树

安装antlr4插件 创建一个后缀是g4的文件 grammar Expr;expression :( expression ) # parens| expression and expression # andOp| expression or expression # orOp| VARNAME comparison_op NUMBER # comparison| VARNAME comparison_op STRING # comparison| …

JS基础与高级应用: 性能优化

在现代Web开发中,性能优化已成为前端工程师必须掌握的核心技能之一。本文从URL输入到页面加载完成的全过程出发,深入分析了HTTP协议的演进、域名解析、代码层面性能优化以及编译与渲染的最佳实践。通过节流、防抖、重复请求合并等具体技术手段&#xff0…

人工智能GPT-4o?

对比分析 在讨论GPT-4o时,我们首先需要了解其前身,即GPT-4,以及其之前的版本。GPT系列从GPT-1到GPT-4经历了多次迭代,每一次都带来了显著的进步。 GPT-4 vs GPT-4o: 1. **参数规模:** GPT-4o在参数规模上…

Git仓库中文件的状态

0 Preface/Foreword 1 文件状态 文件包含以下4个状态: untracked,未跟踪,表示该文件在文件夹中,但是没有加入到git 仓库中进行版本管控。可以通过git add命令将该文件增加到git 仓库中。从untracked变为staged。unmodified&…

论文中表格跨页了做续表的正确方法

在上方加表格 粘贴即可 文章来源于论文中表格跨页了做续表的正确方法!论文人快来学习_哔哩哔哩_bilibili 小姐姐用WPS弄的,微软的不理想,我试了试,觉得在上面增加格子再粘贴表头,效果还行

软件工程期末复习题

目录 选择 判断 选择 下列说法中正确的是 ( B )。 A、20 世纪50 年代提出了软件工程的概念摇 B、20 世纪60 年代提出了软件工程的概念 C、20 世纪70 年代出现了客户端/ 服务器技术 D、20 世纪80 年代软件工程学科达到成熟 软件危机的主要原因是 ( D )。 A、软件工具落后…

下载使用nginx发布html自定义页面

在浏览器搜索nginx.org,然后点击download,接着点击 stable and mainline 选择自己所使用系统对应的信息后点击(我用的是CentOS,所以需要点击RHEL and derivatives) vim /etc/yum.repos.d/nginx.repo [nginx-stable] n…

SpringCloud-面试篇(二十五)

(1)Sentinel与Hystix的线程隔离有什么差别? (2)Sentinel的限流与Gateway限流有什么差别 固定窗口计数器算法,可能再其他的时间两个窗口的交界内超过了请求阈值 ,所以就有了滑动窗口算法 滑动窗…

Docker引起的漏洞问题

前言 测试环境上的中间件和java应用都是由docker进行部署的,但是因为docker的镜像访问有时候需要外网,由此引发了问题,在docker文件中 /usr/lib/systemd/system/docker.service 原有的配置为,可以看到进行了加密 ExecStart/usr/bin/dockerd --tlsverify --tlscacert/etc/docker…