对称加密算法
学习目标
- 了解对称加密算法种类
- 熟悉加密算法工作模式
- 掌握加密算法的实现方式
对称加密(加密解密密钥相同):DES、3DES、AES、RC4
一、常见算法归纳
DES:56位密钥,由于密钥太短,被逐渐弃用。
AES:有128位、192位、256位密钥,现在比较流行。密钥长、可以增加破解的难度和成本。
1.ECB模式
- 全称Electronic Codebook模式,译为电子密码本模式,每个数据块独立进行加/解密
- ECB是最简单的工作模式,原理就是将明文分组,对每一组分别单独加密,加密后的每组密文之间没有联系,在将每一组加密的结果进行拼接。

- 解密流程如下

2.CBC模式
-
全称Cipher Block Chaining模式,译为密文分组链接模式
-
这个模式的核心思想是每一个明文分组在被加密之前要与前一个的密文分组进行异或运算,即每一组的加密结果会参与下一个分组的加密,因此第一个分组加密需要有一个初始化向量(IV)参与。
-
最后将每个密文分组按顺序合并起来就得到加密结果
-
CBC模式是分组加密中使用最多的模式

- 解密方式

3.CFB模式
- 全称Cipher FeedBack模式,译为密文反馈模式
- 这种工作模式吸收了流加密(流加密可以逐个加密数据,因此适用于流式数据,无需等待整个块加密完成)的特点,可以理解成实现了流加密的CBC模式
- 加密时,首先对初始化向量(IV)加密,用加密的结果与第一个明文分组异或,得到第一个密文分组
- 然后将此密文分组进行加密(加密前要进行移位处理),将加密结果与第二个明文分组异或

- 解密过程与加密过程相似,仍然是将前一密文分组加密(注意,这里仍然是加密,不是解密),用加密结果与当前密文分组异或,得到明文

4.OFB模式
- 全称Output Feedback模式,译为输出反馈模式。
- OFB模式与CFB模式类似,区别在于使用上一个分组的密码序列加密生成当前分组的密码序列

- 解密过程

5.CTR模式
-
全称Counter模式,译 为计数器模式。
-
CRT模式与CFB、OFB模式为同一类。但它是通过将逐渐累加的计数器进行加密来生成密码序列
-
也就是说,每一个的密文分组是通过将计数器加密得到的密码序列与明文分组进行异或而得到的

- 解密过程

6.总结
| 名称 | 优点 | 缺点 | 备注 |
|---|---|---|---|
| ECB | 实现简单 运算速度快 支持并行 不存在误差传递 | 不能隐藏明文统计特征 容易被攻击 需要补位 | 不推荐使用 |
| CBC | 隐藏明文统计特征 解密可并行计算 | 加密不支持并行计算 存在误差传递 需要补位 | 推荐使用 |
| CFB | 隐藏明文统计特征 解密可并行计算 不需要补位 | 加密不支持并行计算 存在误差传递 不能抵御重放攻击 | 推荐用CTR模式代替 |
| OFB | 隐藏明文统计特征 不需要补位 不存在误差传递 可事先计算密码序列 | 不支持并行计算 | 推荐用CTR模式代替 |
| CTR | 隐藏明文统计特征 不需要补位 不存在误差传递 可事先计算密码序列 支持并行计算 | 需要设计、管理、分发计数器 | 如果想使用流加密的特点,推荐使用此模式 |
ECB模式和CBC是最常见的加密模式
二、DES算法
1.简介
DES 是一种分组加密算法,它以 64 位为分组对数据加密。64 位一组的明文从算法的一端输入, 64 位的密文从另一端输出。DES是一个对称算法:加密和解密用的是同一个算法(除 密钥编排不同以外)。
密钥的长度位 56 位(密钥通常表示为64位的数,但每个第8位都用奇偶检验,可以忽略)。密钥可以是任意的56位数,且可以在任意的时候改变。
DES算法的入口参数有3个:Key,Data,Mode。其中Key为8字节共64位,是DES算法的工作密钥;Data也为8个字节64位,是要被加密或解密的数据:Mode为DES的工作方式,有两种:加密或解密。
DES算法的工作过程:若Mode为加密,则用Key对数据Data进行加密,生成Data的密码形式(64位)作为DES的输出结果;若Mode为解密,则用Key对密码形式的数据Data解密,还原为Data的明码形式(64位)作为DES的 输出结果。简单地说,算法只不过是加密的一种基本技术,DES基本组建分组是这些技术的一种组合,他基于密钥作用于明文,这是众所周知的轮(round)。
DES有16轮,这意味着要在明文分组上16次实施相同的组合技术。
- mode支持:CBC,CFB,CTR,CTRGladman,ECB,OFB等。
- padding支持:ZeroPadding,NoPadding,AnsiX923,Iso10126,Iso97971,Pkcs7等。
2.JS实现对称加密算法
DES算法的入口参数有3个
- key、DATA、Mode、padding
- key 为7个字节 共56位,是DES算法的工作密钥
- Data 为 8个字节 64位,是要被加密或被解密的数据
- Mode 为 DES 的工作方式
- padding 为填充模式,如果加密后密文长度如果达不到指定整数倍(8个字节,16个字节),填充。
var Crypto = require('crypto-js')
function encrypt1(key, iv, data) {
// 加密
var key = Crypto.enc.Utf8.parse(key)
var iv = Crypto.enc.Utf8.parse(iv)
var enc_data = Crypto.DES.encrypt(data, key, {
iv: iv,
mode: Crypto.mode.CBC,
padding: Crypto.pad.Pkcs7
})
return enc_data.toString()
}
function decrypt1(key,iv,data){
var key = Crypto.enc.Utf8.parse(key)
var iv = Crypto.enc.Utf8.parse(iv)
var dnc_data = Crypto.DES.decrypt(data, key, {
iv: iv,
mode: Crypto.mode.CBC,
padding: Crypto.pad.Pkcs7
})
console.log(dnc_data.toString(Crypto.enc.Utf8))
}
var text="新年快乐"
var desKey="12101429lzz"
var desIV='0123456789abcdef'
encrypt_data=encrypt1(desKey,desIV,text)
decrypt1(desKey,desIV,encrypt_data)
3.python 实现对称加密算法
pip install pyDes
import binascii
from pyDes import des, CBC, PAD_PKCS5
def des_encrypt(key, text, iv):
# 确保 key、text 和 iv 都是字节串,且 key 和 iv 长度为 8
key = key.encode('utf-8')[:8] # 取前 8 字节
iv = iv.encode('utf-8')[:8]
text = text.encode('utf-8') # 文本转为字节串
k = des(key, CBC, iv, pad=None, padmode=PAD_PKCS5)
encrypted = k.encrypt(text, padmode=PAD_PKCS5)
return binascii.b2a_hex(encrypted).decode('utf-8') # 返回 hex 字符串
def des_decrypt(key, encrypted_text, iv):
# 确保 key 和 iv 是字节串,且长度为 8
key = key.encode('utf-8')[:8]
iv = iv.encode('utf-8')[:8]
k = des(key, CBC, iv, pad=None, padmode=PAD_PKCS5)
decrypted = k.decrypt(binascii.a2b_hex(encrypted_text), padmode=PAD_PKCS5)
return decrypted.decode('utf-8') # 返回解密后的字符串
if __name__ == '__main__':
secret_key = '10121429' # 8 字节密钥(必须是 8 字符)
text = '新年快乐'
iv = secret_key # IV 也必须是 8 字节
# 注意参数顺序:key, text, iv
secret_str = des_encrypt(secret_key, text, iv)
print('加密字符串:', secret_str)
decrypt_str = des_decrypt(secret_key, secret_str, iv)
print('解密字符串:', decrypt_str)
4.案例
(1)逆向目标
接口:https://www.kaoshibao.com/api/questions/lists
加密数据:

(2)逆向分析
请求头数据加密定位分析:


(3)代码实现
javascript代码:
var Crypto = require('crypto-js')
function MD5(text) {
return Crypto.MD5(text).toString()
}
function get_headers() {
var headers = {}
var n = (new Date).getTime()
var o = "12b6bb84e093532fb72b4d65fec3f00b"
var r = "/questions/lists"
var c = "400cc904-a5d4-4c4b-8033-f880cd1f10f5"
var h = MD5(o + c + r + n + o)
headers['sign'] = h
headers['timestamp'] = n
return headers
}
function c(e) {
var t='h553YNYhPXPuWRgGasyDck=='
var n = Crypto.enc.Utf8.parse(t);
return Crypto.TripleDES.decrypt({
ciphertext: Crypto.enc.Base64.parse(e)
}, n, {
mode: Crypto.mode.ECB,
padding: Crypto.pad.Pkcs7
}).toString(Crypto.enc.Utf8)
}
python代码:
import time
import requests
import json
import execjs
import csv
import os
class KaoShiBao():
def __init__(self):
self.headers = {
"accept": "application/json, text/plain, */*",
"accept-language": "zh-CN,zh;q=0.9",
"client-identifier": "400cc904-a5d4-4c4b-8033-f880cd1f10f5",
"content-type": "application/json;charset=UTF-8",
"origin": "https://www.kaoshibao.com",
"platform": "web",
"priority": "u=1, i",
"referer": "https://www.kaoshibao.com/online/paper/detail/?paperid=245772",
"request-id": "cccc3713-f8ad-4a66-aa5d-26f0e4bc8b0f",
"sec-ch-ua": "\"Google Chrome\";v=\"137\", \"Chromium\";v=\"137\", \"Not/A)Brand\";v=\"24\"",
"sec-ch-ua-mobile": "?1",
"sec-ch-ua-platform": "\"Android\"",
"sec-fetch-dest": "empty",
"sec-fetch-mode": "cors",
"sec-fetch-site": "same-origin",
"sign": "6b841b0236c0cc15000e3d1346444cd1",
"timestamp": "1755498876243",
"user-agent": "Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/137.0.0.0 Mobile Safari/537.36"
}
self.cookies = {
"UM_distinctid": "198a68e1b04a35-0452b9934b4c738-26011e51-1fa400-198a68e1b05fc2",
"uu": "400cc904-a5d4-4c4b-8033-f880cd1f10f5",
"Hm_lvt_975400bd703f587eef8de1efe396089d": "1755140988,1755487136,1755497129",
"HMACCOUNT": "66294A5300752703",
"source": "",
"invitation": "",
"TDC_itoken": "935566383%3A1755500606",
"token": "79brY3Vf945y1ttOXonKu9x0lzR3aIxPolRA6d%2FjfXwLJkG5Jr8Lbcum1NpiDL91",
"openid": "",
"CNZZDATA1278923901": "871074466-1755140988-https%253A%252F%252Fmp.csdn.net%252F%7C1755500658",
"Hm_lpvt_975400bd703f587eef8de1efe396089d": "1755500658"
}
self.url = "https://www.kaoshibao.com/api/questions/lists"
self.filename = 'kaoshibao.csv'
def get_info(self, page):
data = {
"paperid": "245772",
"type": "all",
"size": 10,
"page": page
}
# 获取请求头的加密的参数
with open('考试宝.js', 'r') as f:
js_code = f.read()
js = execjs.compile(js_code)
header_data = js.call('get_headers')
self.headers["timestamp"] = str(header_data["timestamp"])
self.headers['sign'] = header_data["sign"]
data = json.dumps(data, separators=(',', ':'))
response = requests.post(self.url, headers=self.headers, cookies=self.cookies, data=data)
print(response.json())
return response.json()['data']['rows']
def parse_data(self, data):
item = dict()
for i in data:
item['id'] = i['id']
item['question'] = i['question']
self.save(item)
print(f'{item["id"]}保存成功')
def save(self, item):
header = ['id', 'question']
with open('kaoshibao.csv', 'a', encoding='utf-8', newline='') as f:
f_csv = csv.DictWriter(f, fieldnames=header)
if not os.path.exists(self.filename):
f_csv.writeheader()
f_csv.writerow(item)
def run(self):
for i in range(1, 9):
print(f'正在爬取第{i}页面')
data = self.get_info(i)
self.parse_data(data)
time.sleep(3)
if __name__ == '__main__':
k = KaoShiBao()
k.run()
三、AES算法
1.简介
全称高级加密标准(英文名称:Advanced Encryption Standard),在密码学中又称 Rijndael加密法,由美国国家标准与技术研究院(NIST)于2001年发布,并在2002年成为有效的标准,是美国联邦政府采用的一种区块加密标准。这个标准用来替代原先的DES,已经被多方分析且广为全世界所使用,它本身只有一个密钥,即用来实现加密,也用于解密。
- mode 支持:CBC,CFB,CTR,CTRGladman,ECB,OFB等。
- padding支持:ZeroPadding,NoPadding,AnsiX923,Iso10126,Iso97971,Pkcs7等。
参数定义:
- key length (密钥位数,密码长度)AES128,AES192,AES256(128位、192位或256位)
- key(密钥,密码)key指的就是密码了,AES128就是128位的,如果位数不够,某些库可能会自动填充到128。
- IV(向量)IV称为初始向量,不同的IV加密后的字符串是不同的,加密和解密需要相同的IV。
- mode(加密模式)AES分为几种模式,比如ECB,CBC,CFB等等,这些模式除了ECB由于没有使用IV而不太安全,其他模式差别并没有太明显。
- padding(填充方式)对于加密解密两端需要使用同一的PADDING模式,大部分PADDING模式为PKCS5,PKCS7,NOPADDING.
加密原理:
AES加密算法采用分组密码体制,每个分组数据的长度为128位16个字节,密钥长度可以是128位16个字节、192位或256位,一共有四种加密模式,我们通常采用需要初始向量IV的CBC模式,初始向量的长度也是128位16个字节。
2.JavaScript实现加密
var Crypto = require('crypto-js')
function encrypt1(key, iv, data) {
// 加密
var key = Crypto.enc.Utf8.parse(key)
var iv = Crypto.enc.Utf8.parse(iv)
var enc_data = Crypto.AES.encrypt(data, key, {
iv: iv,
mode: Crypto.mode.CBC,
padding: Crypto.pad.Pkcs7
})
return enc_data.toString()
}
function decrypt1(key,iv,data){
var key = Crypto.enc.Utf8.parse(key)
var iv = Crypto.enc.Utf8.parse(iv)
var dnc_data = Crypto.AES.decrypt(data, key, {
iv: iv,
mode: Crypto.mode.CBC,
padding: Crypto.pad.Pkcs7
})
console.log(dnc_data.toString(Crypto.enc.Utf8))
}
var text = "pxy 新年快乐呀!" // 待加密对象
var aesKey = "6f726c64f2c2057c" // 密钥,16 倍数
var aesIv = "0123456789ABCDEF" // 偏移量,16 倍数
encrypt_data=encrypt1(aesKey,aesIv,text)
decrypt1(aesKey,aesIv,encrypt_data)
3.案例一
(1)逆向目标
接口:https://jzsc.mohurd.gov.cn/APi/webApi/dataservice/query/comp/list?pg=1&pgsz=15&total=450
加密参数: 响应数据为加密数据
(2)逆向分析
加密数据定位:
- 关键字 decrpyt 定位

- hook定位
var my_parse = JSON.parse;
JSON.parse = function (params) {
//这里可以添加其他逻辑比如 debugger
debugger;
console.log("json_parse params:",params);
return my_parse(params);
};
运行hook代码,得到如下的结果(:
然后往前一个栈看,得到结果如下:

- xhr定位(同样可以找到发送ajax的回调位置,不好找的话可以直接在执行下一步,因为它一定会进入到回调的位置进行解密)


(3)代码实现
python代码:
"""
网址:https://jzsc.mohurd.gov.cn/data/company
接口:https://jzsc.mohurd.gov.cn/APi/webApi/dataservice/query/comp/list?pg=1&pgsz=15&total=450
加密数据:响应数据为加密数据
"""
import requests
import execjs
import pymysql
class jzsc():
def __init__(self):
self.db = pymysql.connect(host='localhost',
user='root',
password='123456',
database='py_spider'
) # 数据库名字
# 使用cursor()方法获取操作游标
self.cursor = self.db.cursor()
self.headers = {
"Referer": "https://jzsc.mohurd.gov.cn/data/company",
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/138.0.0.0 Safari/537.36",
"v": "231012"
}
self.cookies = {
"Hm_lvt_b1b4b9ea61b6f1627192160766a9c55c": "1752505831",
"Hm_lpvt_b1b4b9ea61b6f1627192160766a9c55c": "1752505831",
"HMACCOUNT": "C844EA1E4B3823E0"
}
self.url = "https://jzsc.mohurd.gov.cn/APi/webApi/dataservice/query/comp/list"
"""获取响应数据"""
def get_info(self,params):
response = requests.get(self.url, headers=self.headers, cookies=self.cookies, params=params)
with open('案例1.js',encoding='utf-8')as f:
js_code=f.read()
js=execjs.compile(js_code)
data=js.call('b',response.text)
return data
"""解析数据"""
def parse_data(self,data):
for i in data['data']['list']:
code=i['QY_ORG_CODE']
Legal_Person=i['QY_FR_NAME'] # 法人
company_name=i['QY_NAME'] # 公司
address=i['QY_REGION_NAME'] # 企业注册地址
self.save(code,Legal_Person,company_name,address)
"""创建数据表"""
def create_table(self):
sql="""
create table if not exists jzsc(
id int primary key auto_increment,
code varchar(100) ,
Legal_Person varchar(50),
company_name varchar(100),
address varchar(150)
)
"""
try:
self.cursor.execute(sql)
print('创建成功')
except Exception as e:
print('表创建成功',e)
"""插入数据"""
def save(self,code,Legal_Person,company_name,address):
sql="""
insert into jzsc(code,Legal_Person,company_name,address) values(%s,%s,%s,%s)
"""
try:
self.cursor.execute(sql,(code,Legal_Person,company_name,address))
self.db.commit()
print('插入成功',code)
except Exception as e:
print(f'插入失败{e}')
self.db.rollback()
def main(self):
for i in range(1,15):
params = {
"pg": "1",
"pgsz": "15",
"total": "450"
}
self.create_table()
data=self.get_info(params)
self.parse_data(data)
if __name__ == '__main__':
j=jzsc()
j.main()
javascript代码:

密钥在这个代码的下面:

var CryptoJS = require('crypto-js')
m = CryptoJS.enc.Utf8.parse("0123456789ABCDEF")
f = CryptoJS.enc.Utf8.parse("Dt8j9wGw%6HbxfFn")
function b(t) {
var e = CryptoJS.enc.Hex.parse(t)
, n = CryptoJS.enc.Base64.stringify(e)
, a = CryptoJS.AES.decrypt(n, f, {
iv: m,
mode: CryptoJS.mode.CBC,
padding: CryptoJS.pad.Pkcs7
})
, r = a.toString(CryptoJS.enc.Utf8);
return r.toString()
}
4.案例二
(1)逆向目标
接口: https://app.swguancha.com/client/v1/article/client/page
加密参数: 响应数据加密
(2)逆向分析
用xhr断点定位:


(3)代码实现
python代码:
"""
网址:https://www.swguancha.com/home/business-observe
接口:https://app.swguancha.com/client/v1/article/client/page
加密数据:响应的数据
"""
import requests
import json
import execjs
import pymysql
class swguancha():
def __init__(self):
self.db = pymysql.connect(host='localhost',
user='root',
password='123456',
database='py_spider'
) # 数据库名字
# 使用cursor()方法获取操作游标
self.cursor = self.db.cursor()
self.headers = {
"Content-Type": "application/json;charset=UTF-8",
"Origin": "https://www.swguancha.com",
"Referer": "https://www.swguancha.com/",
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/138.0.0.0 Safari/537.36",
}
self.url = "https://app.swguancha.com/client/v1/article/client/page"
"""获取响应数据"""
def get_info(self,data):
data = json.dumps(data, separators=(',', ':'))
response = requests.post(self.url, headers=self.headers, data=data)
with open('案例2.js',encoding='utf-8')as f:
js_code=f.read()
js=execjs.compile(js_code)
response_data=js.call('get_data',response.text)
return response_data
"""解析数据"""
def parse_data(self,data):
for i in data['data']['data']:
title=i['title']
detail_url=f'https://www.swguancha.com/home/news-content?id={i["id"]}'
contentAbstract=i['contentAbstract']
viewCnt=i['viewCnt']
createTime=i['createTime']
self.save(title,detail_url,contentAbstract,viewCnt,createTime)
"""创建数据表"""
def create_table(self):
sql = """
create table if not exists swguancha(
id int primary key auto_increment,
title varchar(100) ,
detail_url varchar(100),
contentAbstract text,
viewCnt int,
createTime varchar(50)
)
"""
try:
self.cursor.execute(sql)
print('创建成功')
except Exception as e:
print('表创建成功', e)
"""插入数据"""
def save(self, title,detail_url,contentAbstract,viewCnt,createTime):
sql = """
insert into swguancha(title,detail_url,contentAbstract,viewCnt,createTime) values(%s,%s,%s,%s,%s)
"""
try:
self.cursor.execute(sql, (title,detail_url,contentAbstract,viewCnt,createTime))
self.db.commit()
print('插入成功', title)
except Exception as e:
print(f'插入失败{e}')
self.db.rollback()
def main(self):
for i in range(1,5):
data = {
"queryType": 3,
"current": i,
"size": 20
}
res_data=self.get_info(data)
self.parse_data(res_data)
if __name__ == '__main__':
s=swguancha()
s.create_table()
s.main()
javascript代码:
var Crypto=require('crypto-js')
function get_data(data){
var l="QV1f3nHn2qm7i3xrj3Y9K9imDdGTjTu9"
var n = Crypto.enc.Utf8.parse(l)
, r = Crypto.AES.decrypt(data, n, {
mode: Crypto.mode.ECB,
padding: Crypto.pad.Pkcs7
})
, i = r.toString(Crypto.enc.Utf8)
return JSON.parse(i)
}
四、魔改算法
魔改算法 通常指的是对现有算法进行修改或改进,以满足特定需求、优化性能或解决特定问题的过程。
1.逆向目标
网址:https://www.ccprec.com/projectSecPage/#/cqzr
接口:https://www.ccprec.com/honsanCloudAct
加密参数:
加密数据:

2.逆向分析
xhr定位断点:先找参数加密的位置


可以看出this.aes.encode(a)为参数加密的核心代码 ,我们发现后面我们扣的地方都有this,因此这个案例我们应该要使用扣类的方法进行扣代码
找this.aes这个类的方法:
this数据定位
先创建的对象 再给对象赋值属性,用搜索进行搜索下面的关键字
this.aes = xxx
aes:
aes =
例如:


3.代码实现
python代码:
"""
网址:https://www.ccprec.com/projectSecPage/#/cqzr
接口:https://www.ccprec.com/honsanCloudAct
加密数据:载荷 和 响应数据
"""
import requests
import execjs
import pymongo
import hashlib
import redis
class ccprec():
def __init__(self):
self.headers = {
"Accept": "application/json, text/plain, */*",
"Accept-Language": "zh-CN,zh;q=0.9",
"Cache-Control": "no-cache",
"Connection": "keep-alive",
"Content-Type": "text/xml;charset=UTF-8",
"Origin": "https://www.ccprec.com",
"Pragma": "no-cache",
"Referer": "https://www.ccprec.com/projectSecPage/",
"Sec-Fetch-Dest": "empty",
"Sec-Fetch-Mode": "cors",
"Sec-Fetch-Site": "same-origin",
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/139.0.0.0 Safari/537.36",
"sec-ch-ua": "\"Not;A=Brand\";v=\"99\", \"Google Chrome\";v=\"139\", \"Chromium\";v=\"139\"",
"sec-ch-ua-mobile": "?0",
"sec-ch-ua-platform": "\"Windows\""
}
self.url = "https://www.ccprec.com/honsanCloudAct"
self.redis_client=redis.Redis()
self.mongo_client=pymongo.MongoClient()
self.collection=self.mongo_client['py_spider']['ccprec']
def get_info(self,page):
with open('ccprec(魔改算法).js','r',encoding='utf-8')as f:
js_code=f.read()
js=execjs.compile(js_code)
data=js.call('get_h',page)
response = requests.post(self.url, headers=self.headers, data=data)
res_json=js.call('get_data',response.text)
return res_json
def parse_data(self,data):
item=dict()
for i in (data['results'][0]['args'][0]['list']):
item['id'] = i['id']
item['url'] = f'https://www.ccprec.com/newSinglePage/#/?id={item["id"]}&type=cqweb_nonphy_cqzr'
item['create_date'] = i['create_date']
item['publish_edtime'] =i['create_date']
item['object_name'] = i['object_name']
self.save(item)
@staticmethod
def get_md5(value):
"""去重"""
# md5只接收字节数据
# 计算哈希值,哈希值是唯一的,哈希值长度为32位
md5_hash=hashlib.md5(str(value).encode('utf-8')).hexdigest()
return md5_hash
def save(self,item):
value=self.get_md5(item)
# 当前返回的是redis是否成功保存md5数据,保存成功result=1,保存失败:result=0
result=self.redis_client.sadd('ccprec:filter',value)
if result:
# 确保插入的数据没有_id字段
item.pop('_id',None)
self.collection.insert_one(item)
print(f'{item}--保存成功')
else:
print(f'{item}--数据重复')
def run(self):
for page in range(1,7):
print(f'正在爬取第{page}页面')
data=self.get_info(page)
self.parse_data(data)
self.mongo_client.close()
self.redis_client.close()
if __name__ == '__main__':
c=ccprec()
c.run()
javascript代码:
var g = function () {
function e() {
this.codeStr = "",
this.pubPass = "BX1o65CoobwcDP33iQW6ld1OyIPsNzF1",
this.pubPassNum = [],
this.publicKey = "",
this.setPass(this.pubPass)
}
return e.prototype.encode = function (e) {
var t = "";
try {
t = JSON.stringify(e)
} catch (n) {
return console.error(n + "这不是一个正确的json对象"),
""
}
return this.encryptCode(t)
}
,
e.prototype.decode = function (e) {
var t;
try {
t = JSON.parse(this.decryptCode(e))
} catch (n) {
return void console.error(n + "json对象转出失败")
}
return t
}
,
e.prototype.encryptCode = function (e) {
for (var t = encodeURI(e), n = [], i = 0, r = "", o = this.random(16, 32), a = this.randomStr(o), s = this.stringChangeASCIINumberArrs(a), l = 0, c = 0, u = 0, h = 0; h < t.length; h++)
i = t.charCodeAt(h),
l == this.pubPassNum.length && (l = 0),
i += this.pubPassNum[l],
l++,
c == s.length && (c = 0),
i += s[c],
c++,
u += i,
u > 65535 && (u -= 65535),
r = i.toString(36),
r = ("00" + r).substr(-2, 2),
1 == r.length && (r = "0" + r),
n.push(r);
var d = "";
return d = u.toString(36),
d = ("0000" + r).substr(-4, 4),
n.unshift(a),
n.unshift(o.toString(36)),
n.unshift(d),
n.join("")
}
,
e.prototype.decryptCode = function (e) {
var t = ""
, n = 0
, i = ""
, r = []
, o = []
, a = 0
, s = 0;
t = e.substr(4, 1),
n = parseInt(t, 36),
i = e.substr(5, n),
r = this.stringChangeASCIINumberArrs(i),
t = e.substr(5 + n, e.length - 5 - n);
for (var l = "", c = 0, u = 0, h = 0; h < t.length / 2; h++)
l = t.substr(u, 2),
u += 2,
c = parseInt(l, 36),
s == r.length && (s = 0),
c -= r[s],
s++,
a == this.pubPass.length && (a = 0),
c -= this.pubPassNum[a],
a++,
l = String.fromCharCode(c),
o.push(l);
return t = o.join(""),
t = decodeURI(t),
t
}
,
e.prototype.setPass = function (e) {
this.pubPassNum = this.stringChangeASCIINumberArrs(e)
}
,
e.prototype.stringChangeASCIINumberArrs = function (e) {
for (var t = [], n = 0; n < e.length; n++)
t.push(e.charCodeAt(n));
return t
}
,
e.prototype.random = function (e, t) {
return void 0 === e && (e = 0),
void 0 === t && (t = 1e4),
Math.floor(Math.random() * (t - e) + e)
}
,
e.prototype.randomStr = function (e) {
for (var t = [], n = 0; n < e; n++)
t.push(this.random(0, 35).toString(36));
return t.join("")
}
,
e
}()
function get_h(page) {
var o = {
"id": "rtxdhspv6w0msei5",
"projectKey": "honsan_cloud_ccprec",
"clientKey": "rtxdgdfgrow59sy6",
"token": null,
"clientDailyData": {},
"acts": [
{
"id": "rtxdhspuqoghlc3p",
"fullPath": "/ccprec.com.cn.web/client/info/cqweb_nonphy_cqzr",
"args": [
page,
20,
null
]
}
]
}
this.aes = new g
var a = JSON.stringify(o)
var s = this.aes.encode(a)
return s
}
function get_data(data){
aes=new g
result=JSON.parse(aes.decryptCode(data))
return result
}
更多推荐
所有评论(0)