当前位置: 首页 > news >正文

爬虫案例:建设库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 falsenpm install crypto-js

python code

import requests
import time
import execjs
import json
from tqdm import tqdmdef 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 Nonedef 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() * 1000max_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());

相关文章:

爬虫案例:建设库JS逆向

爬虫流程 1. 确定目标网址和所需内容 https://www.jiansheku.com/search/enterprise/ 只是个学习案例,所以目标就有我自己来选择,企业名称,法定代表人,注册资本,成立日期 2. 对目标网站,进行分析 动态…...

基于springboot的酒店管理系统源码数据库

时代的发展带来了巨大的生活改变,很多事务从传统手工管理转变为自动管理。自动管理是利用科技的发展开发的新型管理系统,这类管理系统可以帮助人完成基本的繁琐的反复工作。酒店是出门的必需品,无论出差还是旅游都需要酒店的服务。由于在旺季…...

Web前端开发 - 5 - JavaScript基础

JavaScript 一、JavaScript基础1. JavaScript入门2. 语句3. 数据类型4. 函数5. 对象6. 数组 一、JavaScript基础 1. JavaScript入门 <script> </script> <script type"text/javascript" src"xxx.js"> </script>//单行注释 /* 多…...

程序员之路:塑造卓越职业素养的探索与实践

序章 在这个数字时代&#xff0c;程序员作为技术进步的推动者&#xff0c;不仅需要掌握扎实的技术技能&#xff0c;更需具备高尚的职业素养&#xff0c;以应对日益复杂的行业挑战。职业素养&#xff0c;犹如编程中的“算法”&#xff0c;虽无形却决定着个人发展的效率与质量。本…...

C# Winform 在低DPI创建窗体后,在高DPI运行时,窗体会自动拉伸,导致窗体显示不全

C# Winform 在低DPI创建窗体后&#xff0c;在高DPI运行时&#xff0c;窗体会自动拉伸&#xff0c;导致窗体显示不全&#xff0c; 比如在分辨率为100% 的电脑创建C#项目&#xff0c;当运动到分辨率为125%的电脑运行时&#xff0c;后者运行的窗体会自动拉伸&#xff0c;窗体显示…...

JWT攻击手册(非常详细)零基础入门到精通,收藏这一篇就够了

JSON Web Token&#xff08;JWT&#xff09;对于渗透测试人员而言可能是一种非常吸引人的攻击途径&#xff0c;因为它们不仅是让你获得无限访问权限的关键&#xff0c;而且还被视为隐藏了通往以下特权的途径&#xff1a;特权升级&#xff0c;信息泄露&#xff0c;SQLi&#xff…...

5.所有权

标题 一、概念二、规则三、示例3.1 变量作用域3.2 所有权的移交&#xff08;深拷贝与浅拷贝&#xff09;3.3 函数与所有权3.4 返回值与作用域3.5 引用的使用 四、切片(&str) 一、概念 所有权是Rust的核心特性。所有程序在运行时都必须管理它们使用计算机内存的方式。Rust的…...

RabbitMQ-工作模式(Publish模式Routing模式)

文章目录 发布/订阅&#xff08;Publish/Subscribe&#xff09;交换机临时队列绑定总体代码示例 路由&#xff08;Routing&#xff09;绑定直连交换机多重绑定发送日志订阅总体代码示例 更多相关内容可查看 发布/订阅&#xff08;Publish/Subscribe&#xff09; 构建一个简单的…...

【机器学习算法】期望最大化(EM)算法概述

期望最大化&#xff08;EM&#xff09;算法是一种迭代算法&#xff0c;用于在有未观测变量的情况下&#xff0c;求解概率模型参数的最大似然估计或最大后验估计。以下是对EM算法的原理与应用进行详细地剖析&#xff1a; EM算法原理 E步 - 期望计算&#xff1a;根据当前估计的模…...

【深度学习】数竹签演示软件系统

往期文章列表&#xff1a; 【YOLO深度学习系列】图像分类、物体检测、实例分割、物体追踪、姿态估计、定向边框检测演示系统【含源码】 【深度学习】物体检测/实例分割/物体追踪/姿态估计/定向边框/图像分类检测演示系统【含源码】 【深度学习】YOLOV8数据标注及模型训练方法整…...

Halcon 多相机统一坐标系

小杨说事-基于Halcon的多相机坐标系统一原理个人理解_多相机标定统一坐标系-CSDN博客 一、概述 最近在搞多相机标定等的相关问题&#xff0c;对于很大的场景&#xff0c;单个相机的视野是不够的&#xff0c;就必须要统一到一个坐标系下&#xff0c;因此我也用了4个相机&#…...

Apache Kylin:大数据分析从入门到精通

一、Kylin简介 Apache Kylin是一个分布式数据分析引擎,专为处理海量数据设计,能够在极短时间内对超大规模数据集进行OLAP(Online Analytical Processing)分析。Kylin通过预计算和高效的查询机制,为用户提供秒级的查询响应时间,支持与Hadoop、Hive、HBase等大数据平台无缝…...

SQL Server 2016导入.bak文件到数据库里面步骤

1、打开SSMS管理器 选择数据库 右键 然后点击还原数据库。 2、选择设备 然后点击三个点 找到本地bak文件&#xff0c;然后点击确定 3、点击确定&#xff0c;会自动弹出来一个成功的提示。...

WPF Frame 简单页面切换示例

原理比较简单&#xff0c;但是有个坑&#xff0c;为了使界面能够正确更新&#xff0c;记得使用 INotifyPropertyChanged 接口来实现属性更改通知。 <Window x:Class"PageTest.MainWindow"xmlns"http://schemas.microsoft.com/winfx/2006/xaml/presentation&…...

kafka-生产者监听器(SpringBoot整合Kafka)

文章目录 1、生产者监听器1.1、创建生产者监听器1.2、创建生产者拦截器1.3、发送消息测试1.4、使用Java代码创建主题分区副本1.5、application.yml配置----v1版1.6、屏蔽 kafka debug 日志 logback.xml1.7、引入spring-kafka依赖1.8、控制台日志 1、生产者监听器 1.1、创建生产…...

3D感知视觉表示与模型分析:深入探究视觉基础模型的三维意识

在深度学习与大规模预训练的推动下&#xff0c;视觉基础模型展现出了令人印象深刻的泛化能力。这些模型不仅能够对任意图像进行分类、分割和生成&#xff0c;而且它们的中间表示对于其他视觉任务&#xff0c;如检测和分割&#xff0c;同样具有强大的零样本能力。然而&#xff0…...

VS2019+QT5.15调用动态库dll带有命名空间

VS2019QT5.15调用动态库dll带有命名空间 vs创建动态库 参考&#xff1a; QT调用vs2019生成的c动态库-CSDN博客 demo的dll头文件&#xff1a; // 下列 ifdef 块是创建使从 DLL 导出更简单的 // 宏的标准方法。此 DLL 中的所有文件都是用命令行上定义的 DLL3_EXPORTS // 符号…...

助力草莓智能自动化采摘,基于YOLOv5全系列【n/s/m/l/x】参数模型开发构建果园种植采摘场景下草莓成熟度智能检测识别系统

随着科技的飞速发展&#xff0c;人工智能&#xff08;AI&#xff09;技术已经渗透到我们生活的方方面面&#xff0c;从智能家居到自动驾驶&#xff0c;再到医疗健康&#xff0c;其影响力无处不在。然而&#xff0c;当我们把目光转向中国的农业领域时&#xff0c;一个令人惊讶的…...

C++中的生成器模式

目录 生成器模式&#xff08;Builder Pattern&#xff09; 实际应用 构建一辆汽车 构建一台计算机 构建一个房子 总结 生成器模式&#xff08;Builder Pattern&#xff09; 生成器模式是一种创建型设计模式&#xff0c;它允许你分步骤创建复杂对象。与其他创建型模式不同…...

基于python的PDF文件解析器汇总

基于python的PDF文件解析器汇总 大多数已发表的科学文献目前以 PDF 格式存在&#xff0c;这是一种轻量级、普遍的文件格式&#xff0c;能够保持一致的文本布局和格式。对于人类读者而言&#xff0c; PDF格式的文件内容展示整洁且一致的布局有助于阅读&#xff0c;可以很容易地…...

ES6从入门到精通:前言

ES6简介 ES6&#xff08;ECMAScript 2015&#xff09;是JavaScript语言的重大更新&#xff0c;引入了许多新特性&#xff0c;包括语法糖、新数据类型、模块化支持等&#xff0c;显著提升了开发效率和代码可维护性。 核心知识点概览 变量声明 let 和 const 取代 var&#xf…...

2025年能源电力系统与流体力学国际会议 (EPSFD 2025)

2025年能源电力系统与流体力学国际会议&#xff08;EPSFD 2025&#xff09;将于本年度在美丽的杭州盛大召开。作为全球能源、电力系统以及流体力学领域的顶级盛会&#xff0c;EPSFD 2025旨在为来自世界各地的科学家、工程师和研究人员提供一个展示最新研究成果、分享实践经验及…...

如何在看板中体现优先级变化

在看板中有效体现优先级变化的关键措施包括&#xff1a;采用颜色或标签标识优先级、设置任务排序规则、使用独立的优先级列或泳道、结合自动化规则同步优先级变化、建立定期的优先级审查流程。其中&#xff0c;设置任务排序规则尤其重要&#xff0c;因为它让看板视觉上直观地体…...

Qt Http Server模块功能及架构

Qt Http Server 是 Qt 6.0 中引入的一个新模块&#xff0c;它提供了一个轻量级的 HTTP 服务器实现&#xff0c;主要用于构建基于 HTTP 的应用程序和服务。 功能介绍&#xff1a; 主要功能 HTTP服务器功能&#xff1a; 支持 HTTP/1.1 协议 简单的请求/响应处理模型 支持 GET…...

ArcGIS Pro制作水平横向图例+多级标注

今天介绍下载ArcGIS Pro中如何设置水平横向图例。 之前我们介绍了ArcGIS的横向图例制作&#xff1a;ArcGIS横向、多列图例、顺序重排、符号居中、批量更改图例符号等等&#xff08;ArcGIS出图图例8大技巧&#xff09;&#xff0c;那这次我们看看ArcGIS Pro如何更加快捷的操作。…...

LangChain知识库管理后端接口:数据库操作详解—— 构建本地知识库系统的基础《二》

这段 Python 代码是一个完整的 知识库数据库操作模块&#xff0c;用于对本地知识库系统中的知识库进行增删改查&#xff08;CRUD&#xff09;操作。它基于 SQLAlchemy ORM 框架 和一个自定义的装饰器 with_session 实现数据库会话管理。 &#x1f4d8; 一、整体功能概述 该模块…...

代码规范和架构【立芯理论一】(2025.06.08)

1、代码规范的目标 代码简洁精炼、美观&#xff0c;可持续性好高效率高复用&#xff0c;可移植性好高内聚&#xff0c;低耦合没有冗余规范性&#xff0c;代码有规可循&#xff0c;可以看出自己当时的思考过程特殊排版&#xff0c;特殊语法&#xff0c;特殊指令&#xff0c;必须…...

java高级——高阶函数、如何定义一个函数式接口类似stream流的filter

java高级——高阶函数、stream流 前情提要文章介绍一、函数伊始1.1 合格的函数1.2 有形的函数2. 函数对象2.1 函数对象——行为参数化2.2 函数对象——延迟执行 二、 函数编程语法1. 函数对象表现形式1.1 Lambda表达式1.2 方法引用&#xff08;Math::max&#xff09; 2 函数接口…...

WEB3全栈开发——面试专业技能点P4数据库

一、mysql2 原生驱动及其连接机制 概念介绍 mysql2 是 Node.js 环境中广泛使用的 MySQL 客户端库&#xff0c;基于 mysql 库改进而来&#xff0c;具有更好的性能、Promise 支持、流式查询、二进制数据处理能力等。 主要特点&#xff1a; 支持 Promise / async-await&#xf…...

ArcPy扩展模块的使用(3)

管理工程项目 arcpy.mp模块允许用户管理布局、地图、报表、文件夹连接、视图等工程项目。例如&#xff0c;可以更新、修复或替换图层数据源&#xff0c;修改图层的符号系统&#xff0c;甚至自动在线执行共享要托管在组织中的工程项。 以下代码展示了如何更新图层的数据源&…...