├── .gitignore
├── .idea
├── .gitignore
├── dbnavigator.xml
├── inspectionProfiles
│ ├── Project_Default.xml
│ └── profiles_settings.xml
├── misc.xml
├── modules.xml
├── reverse_practice.iml
└── vcs.xml
├── 8btc
├── __init__.py
├── demo.js
├── demo.py
└── docs
│ ├── 1.png
│ ├── 2.png
│ ├── 4.png
│ └── readme.md
├── aliwx
├── __init__.py
└── demo.py
├── appmiu
├── __init__.py
└── demo.js
├── bbs_csdn
├── __init__.py
├── demo.js
└── demo.py
├── bmfw
├── __init__.py
├── demo.js
└── demo.py
├── cas_gench
├── __init__.py
├── demo.js
└── demo.py
├── chacewang
├── __init__.py
├── demo.js
└── demo.py
├── changelog.md
├── chrome.md
├── chromedriver.md
├── cnpub
├── __init__.py
├── demo.js
└── demo.py
├── cpws
├── __init__.py
├── demo.js
├── login.js
└── login.py
├── ctbpsp
├── __init__.py
├── demo.js
└── demo.py
├── ctyun
├── __init__.py
└── demo.js
├── dewu
├── __init__.py
├── demo.js
└── demo.py
├── didiwaimai
├── __init__.py
├── demo.js
└── demo.py
├── dmfw_mca
├── __init__.py
├── demo.js
└── demo.py
├── driver_path
└── chromedriver
├── ehsy
├── __init__.py
├── demo.js
└── demo.py
├── endata
├── __init__.py
├── demo.js
└── demo.py
├── fenbi
├── __init__.py
├── demo.js
└── demo.py
├── ggzyfw_fujian
├── __init__.py
├── demo.js
└── demo.py
├── hh1024
├── __init__.py
├── demo.js
└── demo.py
├── hjs
├── __init__.py
└── demo.py
├── hsddcx
├── __init__.py
├── demo.js
└── demo.py
├── images
├── chrome_version.png
├── chromedriver_version.png
├── fix_origin_chrome.png
├── origin_chrome.png
├── response_type.png
├── setting.png
└── setting_button.png
├── iyunzhi
├── __init__.py
├── demo.js
└── demo.py
├── jzsc
├── __init__.py
├── demo.js
└── demo.py
├── kanzhun
├── __init__.py
├── demo.js
└── demo.py
├── landchina
├── __init__.py
├── demo.js
└── demo.py
├── liepin
├── __init__.py
└── demo.js
├── liuyan
├── __init__.py
└── demo.py
├── maomaozu
├── __init__.py
├── demo.js
└── demo.py
├── music163
├── __init__.py
└── demo.js
├── music_kuwo
├── __init__.py
└── demo.js
├── my_37
├── __init__.py
└── demo.js
├── mytokencap
├── __init__.py
├── demo.js
└── demo.py
├── newrank
├── __init__.py
├── demo.js
└── demo.py
├── oauth
├── __init__.py
└── demo.js
├── oklink
├── __init__.py
├── demo.js
└── demo.py
├── package.json
├── passport_fang
├── __init__.py
├── demo.js
└── demo.py
├── pycharm激活方案汇总
├── README.MD
├── 激活方案一
│ └── 无限30天试用(靠谱)
│ │ ├── ide-eval-resetter-2.1.13.zip
│ │ └── 操作步骤.docx
├── 激活方案三
│ └── 正版激活(支持所有版本)(永久更新)
│ │ └── 支持所有版本-正版激活.txt
├── 激活方案二
│ └── 永久破解(亲测2020 3.3以下版本通用)
│ │ ├── BetterIntelliJ.zip
│ │ ├── reset_script
│ │ ├── reset_jetbrains_eval_mac_linux.sh
│ │ └── reset_jetbrains_eval_windows.vbs
│ │ ├── 操作说明.txt
│ │ └── 激活补丁key-.txt
└── 激活方案四
│ └── README.MD
├── python2encrypt
├── __init__.py
├── base64_encrypt.py
├── md5_encrypt.py
├── rsa_encrypt.py
└── sha_encrypt.py
├── qimingpian
├── __init__.py
├── demo.js
└── demo.py
├── readme.MD
├── remark.md
├── requirements.txt
├── souhu
├── __init__.py
└── demo.js
├── stream_capital
├── __init__.py
├── demo.js
└── demo.py
├── tonghuashun
├── __init__.py
├── demo.js
└── demo.py
├── tousu_sign
├── __init__.py
├── demo.js
└── demo.py
├── utils.py
├── waitpay
├── __init__.py
├── demo.js
└── demo.py
├── webapi
├── __init__.py
├── demo.js
└── demo.py
├── weibotop
├── __init__.py
├── demo.js
└── demo.py
├── xhpfmapi
├── __init__.py
├── demo.js
└── demo.py
├── xiniu
├── __init__.py
├── demo.js
└── demo.py
├── xmly_login
├── __init__.py
├── demo.py
├── get_pwd.js
└── get_signature.js
├── ybdzpz
├── __init__.py
├── demo.js
└── demo.py
├── yiche
├── __init__.py
└── demo.py
├── ypwk
├── __init__.py
└── demo.js
├── yuanrenxue
├── __init__.py
├── readme.md
├── scrape_login1
│ ├── __init__.py
│ └── demo.py
├── scrape_spa2
│ ├── __init__.py
│ ├── demo.js
│ └── demo.py
├── scrape_spa6
│ ├── __init__.py
│ ├── demo.js
│ └── demo.py
├── topic13
│ ├── __init__.py
│ └── demo.py
├── topic14
│ ├── __init__.py
│ ├── demo.js
│ └── demo.py
├── topic25
│ ├── __init__.py
│ └── demo.py
├── topic55
│ ├── __init__.py
│ ├── demo.js
│ └── demo.py
├── topic56
│ ├── __init__.py
│ ├── demo.js
│ └── demo.py
├── topic57
│ ├── __init__.py
│ ├── demo.js
│ └── demo.py
├── topic58
│ ├── __init__.py
│ └── demo.py
├── topic60
│ ├── __init__.py
│ ├── demo.js
│ └── demo.py
├── wangluozhe2
│ ├── __init__.py
│ ├── demo.js
│ └── demo.py
├── wangluozhe3
│ ├── __init__.py
│ ├── demo.js
│ └── demo.py
└── wangluozhe4
│ ├── __init__.py
│ ├── demo.js
│ └── demo.py
├── zbcg_sznsyy
├── __init__.py
├── demo.js
└── demo.py
└── zyfuw
├── __init__.py
├── demo.js
└── demo.py
/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules
2 | package-lock.json
3 | .idea
4 | __pycache__
5 | .xml
6 | .iml
--------------------------------------------------------------------------------
/.idea/.gitignore:
--------------------------------------------------------------------------------
1 | # Default ignored files
2 | /shelf/
3 | /workspace.xml
4 | # Datasource local storage ignored files
5 | /dataSources/
6 | /dataSources.local.xml
7 | # Editor-based HTTP Client requests
8 | /httpRequests/
9 |
--------------------------------------------------------------------------------
/.idea/inspectionProfiles/Project_Default.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
13 |
14 |
15 |
--------------------------------------------------------------------------------
/.idea/inspectionProfiles/profiles_settings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/.idea/misc.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/.idea/modules.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/.idea/reverse_practice.iml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/.idea/vcs.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/8btc/__init__.py:
--------------------------------------------------------------------------------
1 | # _*_ coding: utf-8 _*_
2 | # @Date: 11:45 上午
3 | # @File: __init__.py.py
4 | # @Author: liyf
5 |
--------------------------------------------------------------------------------
/8btc/demo.js:
--------------------------------------------------------------------------------
1 | var CryptoJS = require('crypto-js');
2 |
3 | function get_device_id(e, t) {
4 | for (var n = "", a = t ? Math.round(Math.random() * (t - e)) + e : e, i = ["0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z", "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z"], r = 0; r < a; r++) {
5 | n += i[Math.round(Math.random() * (i.length - 1))]
6 | }
7 | return n
8 | }
9 |
10 | function get_sign(c) {
11 | var e = JSON.stringify(c),
12 | t = 'WTAHAPPYACTIVITY';
13 | var n = {
14 | mode: CryptoJS.mode.ECB,
15 | padding: CryptoJS.pad.Pkcs7
16 | }
17 | , a = CryptoJS.enc.Utf8.parse(t);
18 | return CryptoJS.AES.encrypt(e, a, n).toString().replace(/\//g, "_").replace(/\+/g, "-")
19 | }
20 |
21 |
22 | var device_id = get_device_id(20, 20);
23 | console.log(device_id)
24 |
25 | var sign_params = {"appId": "1", "timestamp": 1695189097, "serverCode": "0"},
26 | sign = get_sign(sign_params);
27 | console.log(sign)
28 |
--------------------------------------------------------------------------------
/8btc/demo.py:
--------------------------------------------------------------------------------
1 | # _*_ coding: utf-8 _*_
2 | # @Date: 11:45 上午
3 | # @File: demo.py
4 | # @Author: liyf
5 |
6 | import time
7 | import requests
8 |
9 | from utils import *
10 |
11 |
12 | def conversion_time_str(postDate):
13 | """
14 | 时间戳转标准时间格式
15 | :param postDate: 时间戳
16 | :return: 标准时间格式
17 | """
18 | timeArray = time.localtime(postDate)
19 | res_time = time.strftime("%Y-%m-%d %H:%M:%S", timeArray)
20 | return res_time
21 |
22 |
23 | def get_device_id_and_sign(sign_params):
24 | ctx = Utils(js_file_name='demo.js').read_js_file()
25 | device_id = ctx.call('get_device_id', 20, 20)
26 | sign = ctx.call('get_sign', sign_params)
27 | return device_id, sign
28 |
29 |
30 | def get_results(json_data):
31 | sign_params = {"appId": "1", "timestamp": str(int(time.time())), "serverCode": "0"}
32 | device_id, sign = get_device_id_and_sign(sign_params)
33 | logger.info({'device_id': device_id, 'sign': sign})
34 | headers = {
35 | 'authority': 'gate.8btc.cn:8443',
36 | 'accept': '*/*',
37 | 'accept-language': 'zh-CN,zh;q=0.9',
38 | 'app-code': '8btc',
39 | 'authorization': '{"secretKeyVersion":1,"sign":"%s"}' % sign,
40 | 'device_id': device_id,
41 | 'origin': 'https://www.8btc.com',
42 | 'referer': 'https://www.8btc.com/',
43 | 'user-agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/104.0.0.0 Safari/537.36',
44 | }
45 | response = requests.post('https://gate.8btc.cn:8443/one-graph-auth/graphql', headers=headers, json=json_data)
46 | return response.json()
47 |
48 |
49 | def parse(json_data):
50 | results = get_results(json_data)
51 | data_list = results['data']['articleGraph']['list']['edges']
52 | for data in data_list:
53 | node = data['node']
54 | title = node['post']['title']
55 | post_date = node['post']['postDate']
56 | release_time = conversion_time_str(post_date)
57 | source = node['extra']['source']['name']
58 | link = node['extra']['source']['link']
59 | links = '无' if not link else link
60 | source = '无' if not source else source
61 | up = node['sense']['up']
62 | down = node['sense']['down']
63 | desc = node['post']['desc']
64 | print(
65 | f'标题: {title}\n发布时间: {release_time}\n来源: {source}\n利好: {up}\n利空: {down}\n原文链接: {links}\n内容: {desc.strip()}')
66 | print('===' * 30)
67 |
68 | page_info = results['data']['articleGraph']['list']['pageInfo']
69 | has_next_page = page_info['hasNextPage']
70 | if not has_next_page:
71 | logger.info('已经是最后一页了~~~')
72 | return
73 | next_page_params = page_info['endCursor']
74 | json_data['variables']['after'] = next_page_params
75 | parse(json_data)
76 |
77 |
78 | if __name__ == '__main__':
79 | json_data = {
80 | 'operationName': 'listFlash',
81 | 'variables': {
82 | 'flashCategory': 'GENERAL',
83 | 'first': 20,
84 | },
85 | 'query': 'query listFlash($first: Int, $after: String, $showOn7x24h: Boolean, $flashCategory: FlashCategory = GENERAL, $tag: Int, $startTime: Date, $endTime: Date) { articleGraph { list: listFlash(page: {first: $first, after: $after, pattern: CURSOR}, param: {flashCategory: $flashCategory, showOn7x24h: $showOn7x24h, tagId: $tag, startTime: $startTime, endTime: $endTime}) { edges { node { id post { title desc content postDate thumbnail __typename } extra { authorInfo { base { displayName __typename } __typename } source { link name __typename } __typename } ... on Flash { highlight push sense { down up select __typename } __typename } __typename } __typename } pageInfo { hasNextPage totalCount startCursor endCursor __typename } __typename } __typename }}',
86 | }
87 | parse(json_data)
88 |
--------------------------------------------------------------------------------
/8btc/docs/1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/liyf-code/reverse_practice/e7e984ab8926770c4c193f4e717bcc02cfe1cf44/8btc/docs/1.png
--------------------------------------------------------------------------------
/8btc/docs/2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/liyf-code/reverse_practice/e7e984ab8926770c4c193f4e717bcc02cfe1cf44/8btc/docs/2.png
--------------------------------------------------------------------------------
/8btc/docs/4.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/liyf-code/reverse_practice/e7e984ab8926770c4c193f4e717bcc02cfe1cf44/8btc/docs/4.png
--------------------------------------------------------------------------------
/8btc/docs/readme.md:
--------------------------------------------------------------------------------
1 | ## 巴比特站点爬虫文档
2 | - 网站 [https://www.8btc.com/flash](https://www.8btc.com/flash)
3 | - 爬取的是 `快讯` 模块
4 |
5 | ## 反扒
6 | - 下拉刷新更多,抓包,如下
7 | - 经过多次测试,请求头中的 `authorization` 参数,每次请求都会变化,为必要参数。
8 |
9 | ## `authorization` 的破解
10 |
11 | - 全局搜索该关键字即可定位到关键代码
12 | - 下拉,点击 `查看更多`,发现断点生效
13 | ### device_id
14 | - `device_id` 由 `Object(i.u)(20, 20)` 生成
15 | - 控制台输入 `i.u`,并点击进去,发现如下代码:
16 | ```javascript
17 | function w(e, t) {
18 | for (var n = "", a = t ? Math.round(Math.random() * (t - e)) + e : e, i = ["0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z", "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z"], r = 0; r < a; r++) {
19 | n += i[Math.round(Math.random() * (i.length - 1))]
20 | }
21 | return n
22 | }
23 | ```
24 | - 该代码就可以直接生成 `device_id` 参数,且不需要额外的补环境
25 | - 其中参数 e 和 t 都是定值 20
26 |
27 | ### sign
28 | - `sign` 由 `Object(i.d)(c, "WTAHAPPYACTIVITY")` 生成。其中 `i.d` 是函数 `E`,且接收两个参数:`c` 和 `WTAHAPPYACTIVITY`
29 | - 其中 c 为 `'{"appId":"1","timestamp":"1662101940","serverCode":"0"}'`
30 | - i.d 函数,点击进去之后,发现如下代码
31 | ```javascript
32 | function E(e, t) {
33 | var n = {
34 | mode: o.a.mode.ECB,
35 | padding: o.a.pad.Pkcs7
36 | }
37 | , a = o.a.enc.Utf8.parse(t);
38 | return o.a.AES.encrypt(e, a, n).toString().replace(/\//g, "_").replace(/\+/g, "-")
39 | }
40 | ```
41 | - AES-ECB 模式,Pkcs7 填充方式
--------------------------------------------------------------------------------
/aliwx/__init__.py:
--------------------------------------------------------------------------------
1 | # _*_ coding: utf-8 _*_
2 | # @Date: 5:34 下午
3 | # @File: __init__.py.py
4 | # @Author: liyf
5 |
--------------------------------------------------------------------------------
/aliwx/demo.py:
--------------------------------------------------------------------------------
1 | # _*_ coding: utf-8 _*_
2 | # @Date: 4:33 下午
3 | # @File: demo.py
4 | # @Author: liyf
5 |
6 | import re
7 | import execjs
8 | import requests
9 |
10 | from loguru import logger
11 |
12 | headers = {
13 | 'authority': 'www.aliwx.com.cn',
14 | 'accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9',
15 | 'user-agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/108.0.0.0 Safari/537.36',
16 | }
17 |
18 |
19 | def get_html():
20 | params = {
21 | 'bid': '6813923',
22 | 'cid': '674259',
23 | }
24 | response = requests.get('https://www.aliwx.com.cn/reader', params=params, headers=headers)
25 | return response.text
26 |
27 |
28 | def get_decrypt_data(encrypt_data):
29 | js_str = '''
30 | function _decodeCont(t) {
31 | return t = function (t) {
32 | return t.split("").map(function (t) {
33 | var e, i;
34 | return t.match(/[A-Za-z]/) ? (e = Math.floor(t.charCodeAt(0) / 97),
35 | i = (t.toLowerCase().charCodeAt(0) - 83) % 26 || 26,
36 | String.fromCharCode(i + (0 == e ? 64 : 96))) : t
37 | }).join("")
38 | }(t),
39 | function (t) {
40 | var e, i, a, n, r, c, o, s = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=", d = "",
41 | l = 0;
42 | for (t = t.replace(/[^A-Za-z0-9\+\/\=]/g, ""); l < t.length;)
43 | n = s.indexOf(t.charAt(l++)),
44 | r = s.indexOf(t.charAt(l++)),
45 | c = s.indexOf(t.charAt(l++)),
46 | o = s.indexOf(t.charAt(l++)),
47 | e = n << 2 | r >> 4,
48 | i = (15 & r) << 4 | c >> 2,
49 | a = (3 & c) << 6 | o,
50 | d += String.fromCharCode(e),
51 | 64 != c && (d += String.fromCharCode(i)),
52 | 64 != o && (d += String.fromCharCode(a));
53 | return function (t) {
54 | for (var e, i = "", a = 0, n = 0, r = 0; a < t.length;)
55 | n = t.charCodeAt(a),
56 | n < 128 ? (i += String.fromCharCode(n),
57 | a++) : n > 191 && n < 224 ? (r = t.charCodeAt(a + 1),
58 | i += String.fromCharCode((31 & n) << 6 | 63 & r),
59 | a += 2) : (r = t.charCodeAt(a + 1),
60 | e = t.charCodeAt(a + 2),
61 | i += String.fromCharCode((15 & n) << 12 | (63 & r) << 6 | 63 & e),
62 | a += 3);
63 | return i
64 | }(d)
65 | }(t)
66 | }
67 | '''
68 | ctx = execjs.compile(''.join(js_str))
69 | decrypt_data = ctx.call('_decodeCont', encrypt_data)
70 | return decrypt_data
71 |
72 |
73 | def get_info():
74 | html = get_html()
75 | a_str = re.findall(re.compile(r'dataChapters">(.*?)', re.S), html)[0]
76 | data_info = str(a_str).replace('"', '"').replace('true', 'True').replace('false', 'False').replace('amp;', '')
77 | item = eval(data_info) # 字符串转字典
78 | data_list = item['chapterList']
79 | info = {
80 | volumedata['volumeName']: {
81 | # 判断是否为收费章节的条件为 isFreeRead 字段
82 | chapterdata['chapterName']: chapterdata['contUrlSuffix'] if chapterdata['isFreeRead'] else None
83 | for chapterdata in volumedata['volumeList']
84 | }
85 | for volumedata in data_list
86 | }
87 | return info
88 |
89 |
90 | def get_encrypt_data():
91 | info = get_info()
92 | for volumeName, item in info.items():
93 | for chapterName, url_suffix in item.items():
94 | if url_suffix:
95 | logger.info(f'当前进度: {volumeName}, {chapterName}')
96 | url = f'https://c13.shuqireader.com/pcapi/chapter/contentfree/{url_suffix}'
97 | results = requests.get(url, headers=headers).json()
98 | encrypt_data = results['ChapterContent']
99 | logger.warning('\n'.join(get_decrypt_data(encrypt_data).split('
')))
100 | else:
101 | logger.error(f'收费章节: {volumeName}, {chapterName}')
102 | break
103 |
104 |
105 | if __name__ == '__main__':
106 | get_encrypt_data()
107 |
--------------------------------------------------------------------------------
/appmiu/__init__.py:
--------------------------------------------------------------------------------
1 | # _*_ coding: utf-8 _*_
2 | # @Date: 4:59 下午
3 | # @File: __init__.py.py
4 | # @Author: liyf
5 |
--------------------------------------------------------------------------------
/appmiu/demo.js:
--------------------------------------------------------------------------------
1 | var h = '富强民主文明和谐自由平等公正法治爱国敬业诚信友善';
2 |
3 | function e() {
4 | for (var t = arguments.length, n = Array(t), r = 0; r < t; r++)
5 | n[r] = arguments[r];
6 | var e = n.length
7 | , i = "string" == typeof n[e - 1] ? n[e - 1] : "Assert Error"
8 | , o = !0
9 | , u = !1
10 | , c = void 0;
11 | try {
12 | for (var f, a = n[Symbol.iterator](); !(o = (f = a.next()).done); o = !0) {
13 | if (!f.value)
14 | throw new Error(i)
15 | }
16 | } catch (t) {
17 | u = !0,
18 | c = t
19 | } finally {
20 | try {
21 | !o && a.return && a.return()
22 | } finally {
23 | if (u)
24 | throw c
25 | }
26 | }
27 | }
28 |
29 | function i() {
30 | return Math.random() >= .5
31 | }
32 |
33 | function c(t) {
34 | e("string" == typeof t);
35 | var n = []
36 | , r = !0
37 | , o = !1
38 | , u = void 0;
39 | try {
40 | for (var c, f = t[Symbol.iterator](); !(r = (c = f.next()).done); r = !0) {
41 | var a = c.value
42 | , s = Number.parseInt(a, 16);
43 | s < 10 ? n.push(s) : i() ? (n.push(10),
44 | n.push(s - 10)) : (n.push(11),
45 | n.push(s - 6))
46 | }
47 | } catch (t) {
48 | o = !0,
49 | u = t
50 | } finally {
51 | try {
52 | !r && f.return && f.return()
53 | } finally {
54 | if (o)
55 | throw u
56 | }
57 | }
58 | return n
59 | }
60 |
61 | function o(t) {
62 | var n = /[A-Za-z0-9\-\_\.\!\~\*\'\(\)]/g
63 | , r = t.replace(n, function (t) {
64 | return t.codePointAt(0).toString(16)
65 | });
66 | return encodeURIComponent(r).replace(/%/g, "").toUpperCase()
67 | }
68 |
69 | function a(t) {
70 | return t.map(function (t) {
71 | return h[2 * t] + h[2 * t + 1]
72 | }).join("")
73 | }
74 |
75 | function l(t) {
76 | return a(c(o(t)))
77 | }
78 |
79 | // https://www.appmiu.com/key/
80 | var key = '1234567',
81 | res = l(key);
82 | console.log(res)
--------------------------------------------------------------------------------
/bbs_csdn/__init__.py:
--------------------------------------------------------------------------------
1 | # _*_ coding: utf-8 _*_
2 | # @Date: 4:54 下午
3 | # @File: __init__.py.py
4 | # @Author: liyf
5 |
--------------------------------------------------------------------------------
/bbs_csdn/demo.py:
--------------------------------------------------------------------------------
1 | # _*_ coding: utf-8 _*_
2 | # @Date: 4:22 下午
3 | # @File: demo.py
4 | # @Author: liyf
5 |
6 | '''
7 | 逆向参数
8 | - 请求头中 X-Ca-Signature 和 X-Ca-Nonce 为必要参数,且缺一不可
9 |
10 | 思路
11 | 全局搜索关键字 X-Ca-Signature 即可定位到关键函数,如下
12 | e.headers["X-Ca-Nonce"] = f(),
13 | "[object FormData]" === Object.prototype.toString.call(e.data) && (e.headers["X-Ca-Signed-Content-Type"] = "multipart/form-data",
14 | e.headers["X-Ca-Signature"] = h({
15 | method: a,
16 | url: c,
17 | accept: t,
18 | params: d,
19 | date: n,
20 | contentType: i,
21 | headers: e.headers,
22 | appSecret: r
23 | })
24 |
25 | 在该处下断点,点击下一页,断点即可生效
26 | 其中,生成 X-Ca-Nonce 参数的为 f 函数,且点进去 f 函数,发现 f 函数为一个获取随机uuid的函数。
27 |
28 | 生成 X-Ca-Signature 参数的为 h 函数,接收的参数为一个对象,在该对象中,只有两个参数是变化的,剩下的参数均可为固定
29 | - page参数可变,表示页码
30 | - nonce参数可变,随机生成的uuid
31 |
32 | '''
33 |
34 | import execjs
35 | import requests
36 |
37 | from loguru import logger
38 |
39 | f = open('demo.js', 'r')
40 | js_str = f.read()
41 | ctx = execjs.compile(''.join(js_str))
42 |
43 | headers = {
44 | "authority": "bizapi.csdn.net",
45 | "accept": "application/json, text/plain, */*",
46 | "accept-language": "zh-CN,zh;q=0.9",
47 | "origin": "https://bbs.csdn.net",
48 | "user-agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/116.0.0.0 Safari/537.36",
49 | "x-ca-key": "203899271",
50 | "x-ca-signature-headers": "x-ca-key,x-ca-nonce"
51 | }
52 | url = "https://bizapi.csdn.net/community-cloud/v1/colleges/main_page/list"
53 |
54 | global next_page # 计算下一页的页码
55 |
56 |
57 | def get_results(page):
58 | params = {
59 | "deviceType": "pc",
60 | "page": str(page),
61 | "pageSize": "20",
62 | "category": "37",
63 | "sort": "desc",
64 | "type": "2"
65 | }
66 | para_info = ctx.call('get_nonce_signature', page)
67 | logger.info(f'获取到第 {page} 页请求头加密参数: \n{para_info}')
68 | headers['x-ca-nonce'] = para_info['nonce']
69 | headers['x-ca-signature'] = para_info['signature']
70 | response = requests.get(url, headers=headers, params=params)
71 | return response.json()
72 |
73 |
74 | def get_data(page):
75 | results = get_results(page)
76 | next_page = page
77 | data_list = results['data']['list']
78 | for data in data_list:
79 | communityName = data['communityName']
80 | activeUserNum = data['activeUserNum']
81 | continueLearningDays = data['continueLearningDays']
82 | influence = data['influence']
83 | communityNum = data['communityNum']
84 | user_list = [user['nickName'] for user in data['userList']]
85 | users = '、'.join(user_list)
86 | print(
87 | f'学校名称: {communityName}\n7日活跃人数: {activeUserNum}\n持续学习天数: {continueLearningDays}\n影响力: {influence}\n成员数量: {communityNum}\n明星成员: {users}')
88 | print('===' * 20)
89 | print('***' * 25)
90 | # 自动获取下一页
91 | total_page = results['data']['totalPages']
92 | if next_page < total_page:
93 | next_page += 1
94 | get_data(next_page)
95 |
96 |
97 | def main():
98 | get_data(1)
99 |
100 |
101 | if __name__ == '__main__':
102 | main()
103 |
--------------------------------------------------------------------------------
/bmfw/__init__.py:
--------------------------------------------------------------------------------
1 | # _*_ coding: utf-8 _*_
2 | # @Date: 11:34 上午
3 | # @File: __init__.py.py
4 | # @Author: liyf
5 |
--------------------------------------------------------------------------------
/bmfw/demo.js:
--------------------------------------------------------------------------------
1 | var CryptoJS = require('crypto-js');
2 |
3 | var token = '23y0ufFl5YxIyGrI8hWRUZmKkvtSjLQA',
4 | nonce = '123456789abcdefg',
5 | passid = 'zdww';
6 |
7 |
8 | function get_headers_params(timestamp) {
9 | var zdwwsignature = CryptoJS.SHA256(timestamp + 'fTN2pfuisxTavbTuYVSsNJHetwq5bJvC' + 'QkjjtiLM2dCratiA' + timestamp)
10 | .toString(CryptoJS.enc.Hex)
11 | .toUpperCase();
12 | return {
13 | 'x-wif-nonce': 'QkjjtiLM2dCratiA',
14 | 'x-wif-paasid': 'smt-application',
15 | 'x-wif-signature': zdwwsignature,
16 | 'x-wif-timestamp': timestamp
17 | }
18 | }
19 |
20 | function generateAjaxParmas(params, timestamp) {
21 | return {
22 | paasHeader: passid,
23 | timestampHeader: timestamp,
24 | nonceHeader: nonce,
25 | signatureHeader: CryptoJS.SHA256(timestamp + token + nonce + timestamp)
26 | .toString(CryptoJS.enc.Hex)
27 | .toUpperCase()
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/bmfw/demo.py:
--------------------------------------------------------------------------------
1 | # _*_ coding: utf-8 _*_
2 | # @Date: 11:34 上午
3 | # @File: demo.py
4 | # @Author: liyf
5 |
6 | '''
7 | 网站:http://bmfw.www.gov.cn/hsjcjgcx/index.html?ADTAG=feiyanh5&adcode=440000
8 | 接口:http://bmfw.www.gov.cn/bjww/interface/interfaceJson
9 | 请求方式:post
10 | 需要逆向的参数
11 | -请求头部分,缺一不可
12 | - x-wif-timestamp 长度为10位的时间戳
13 | - x-wif-signature SHA256加密
14 | - x-wif-paasid 定值: `smt-application`
15 | - x-wif-nonce 定值: `QkjjtiLM2dCratiA`
16 | - 请求参数部分,缺一不可
17 | - paasHeader 定值: `zdww`
18 | - timestampHeader 长度为10位的时间戳
19 | - signatureHeader SHA256加密
20 | - nonceHeader 定值: `123456789abcdefg`
21 |
22 | 全局搜索关键字 `signatureHeader`,只有一个js文件,即可定位到加密位置
23 |
24 | 而且,在该js文件中,请求头中的加密参数和发送post请求所携带的参数的加密,都能在该js文件中找到
25 |
26 | 把关键的js代码copy至本地,复现加密逻辑,生成加密参数即可
27 | '''
28 |
29 | import time
30 | import requests
31 |
32 | from utils import *
33 |
34 | ctx = Utils(js_file_name='demo.js').read_js_file()
35 |
36 |
37 | def get_encrypt_data(params, timestamp):
38 | if params:
39 | return ctx.call('generateAjaxParmas', params, timestamp)
40 | else:
41 | return ctx.call('get_headers_params', timestamp)
42 |
43 |
44 | def get_results(page):
45 | headers = {
46 | 'Accept': 'application/json, text/javascript, */*; q=0.01',
47 | 'Accept-Language': 'zh-CN,zh;q=0.9',
48 | 'Content-Type': 'application/json; charset=UTF-8',
49 | 'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/107.0.0.0 Safari/537.36',
50 | }
51 | json_data = {
52 | "code": "",
53 | "serach_key": "",
54 | "page": page,
55 | "appId": "NcApplication",
56 | "key": "818461bc617bb175b8c2b87d6bf1bb07",
57 | "page_size": "4"
58 | }
59 | ts = str(int(time.time()))
60 | encrypt_header = get_encrypt_data(params=None, timestamp=ts)
61 | headers['x-wif-nonce'] = encrypt_header['x-wif-nonce']
62 | headers['x-wif-paasid'] = encrypt_header['x-wif-paasid']
63 | headers['x-wif-signature'] = encrypt_header['x-wif-signature']
64 | headers['x-wif-timestamp'] = encrypt_header['x-wif-timestamp']
65 |
66 | encrypt_params = get_encrypt_data(params=json_data, timestamp=ts)
67 | json_data['paasHeader'] = encrypt_params['paasHeader']
68 | json_data['timestampHeader'] = encrypt_params['timestampHeader']
69 | json_data['nonceHeader'] = encrypt_params['nonceHeader']
70 | json_data['signatureHeader'] = encrypt_params['signatureHeader']
71 | response = requests.post('http://bmfw.www.gov.cn/bjww/interface/interfaceJson', headers=headers, json=json_data,
72 | verify=False)
73 | return response.json()
74 |
75 |
76 | def parse():
77 | for page in range(1, 10):
78 | res = get_results(page)
79 | data_list = res['data']['list']
80 | for data in data_list:
81 | name = data['name']
82 | phone = data['phone']
83 | address = data['address']
84 | area_address = data['area_address']
85 | print(f'机构名称: {name}\n联系电话: {phone}\n所在区县: {area_address}\n机构地址: {address}')
86 | print('===' * 20)
87 |
88 |
89 | if __name__ == '__main__':
90 | parse()
91 |
--------------------------------------------------------------------------------
/cas_gench/__init__.py:
--------------------------------------------------------------------------------
1 | # _*_ coding: utf-8 _*_
2 | # @Date: 5:00 下午
3 | # @File: __init__.py.py
4 | # @Author: liyf
5 |
--------------------------------------------------------------------------------
/cas_gench/demo.py:
--------------------------------------------------------------------------------
1 | # _*_ coding: utf-8 _*_
2 | # @Date: 5:32 下午
3 | # @File: demo.py
4 | # @Author: liyf
5 |
6 | '''
7 | 第一次请求
8 | - 主页 https://cas.gench.edu.cn/cas/login
9 | - get请求,从源码中获取 execution 字段
10 |
11 | 第二次请求
12 | - 登录接口 https://cas.gench.edu.cn/cas/login
13 | - post请求
14 | - params包括 execution、加密后的密码、账户
15 | - 如果不带 execution 的画,请求出来的源码为主页源码,不是接口返回的源码
16 |
17 | 全局搜索关键字 'password' 可在 'login.js' 文件中,找到如下代码:
18 | - result = RSAUtils.encryptedString(key, thisPwd)
19 | result 就是最终加密后的结果
20 | 在该处下断点,进入 RSAUtils.encryptedString 函数中
21 | - 把该文件中的所有js代码复制下来,放在本地运行即可
22 | - 无需进行额外修改
23 | '''
24 |
25 | import re
26 | import execjs
27 | import requests
28 |
29 | from loguru import logger
30 |
31 | headers = {
32 | "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7",
33 | "Accept-Language": "zh-CN,zh;q=0.9",
34 | "Content-Type": "application/x-www-form-urlencoded",
35 | "Origin": "https://cas.gench.edu.cn",
36 | "Pragma": "no-cache",
37 | "Referer": "https://cas.gench.edu.cn/cas/login",
38 | "User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.0.0 Safari/537.36",
39 | }
40 |
41 | f = open('demo.js', 'r')
42 | js_str = f.readlines()
43 | ctx = execjs.compile(''.join(js_str))
44 |
45 |
46 | def get_results(url):
47 | response = requests.get(url, headers=headers)
48 | return response.text
49 |
50 |
51 | def get_api_status(username, pwd, execution):
52 | url = "https://cas.gench.edu.cn/cas/login"
53 | data = {
54 | "username": username,
55 | "password": pwd,
56 | "execution": execution,
57 | "encrypted": "true",
58 | "_eventId": "submit",
59 | "loginType": "1"
60 | }
61 | response = requests.post(url, headers=headers, data=data)
62 | return response.text
63 |
64 |
65 | def get_execution():
66 | url = 'https://cas.gench.edu.cn/cas/login'
67 | html = get_results(url)
68 | execution = re.findall(re.compile(r'name="execution".*?value="(.*?)".*?/>', re.S), html)[0]
69 | return execution
70 |
71 |
72 | def main():
73 | execution = get_execution()
74 | logger.info(f'execution: {execution}')
75 | user_name = 'test_test'
76 | pwd = '123456'
77 | encrypt_pwd = ctx.call('get_encrypt_pwd', pwd)
78 | logger.info(f'密码加密结果: {encrypt_pwd}')
79 | results = get_api_status(user_name, encrypt_pwd, execution)
80 | if '账户或密码不正确' in results:
81 | logger.info(f'登录完成,状态为【账户或密码不正确】')
82 |
83 |
84 | if __name__ == '__main__':
85 | main()
86 |
--------------------------------------------------------------------------------
/chacewang/__init__.py:
--------------------------------------------------------------------------------
1 | # _*_ coding: utf-8 _*_
2 | # @Date: 10:19 上午
3 | # @File: __init__.py.py
4 | # @Author: liyf
5 |
--------------------------------------------------------------------------------
/chacewang/demo.py:
--------------------------------------------------------------------------------
1 | # _*_ coding: utf-8 _*_
2 | # @Date: 10:36 上午
3 | # @File: demo.py
4 | # @Author: liyf
5 |
6 | '''
7 | 对查策网(https://www.chacewang.com/chanye/index#)的响应数据进行解密
8 |
9 | 打xhr断点,一步一步调试
10 | 或者搜索关键字`decrypt(`或者`JSON.parse(`也可以定位到加密位置
11 |
12 |
13 | 已完成:
14 | - 响应数据解密已破解
15 |
16 | 未完成:
17 | - 响应数据中的申报时间字段(start_time、end_time)进行了字体加密,未破解
18 | '''
19 |
20 | import requests
21 |
22 | from utils import *
23 |
24 |
25 | def get_encrypt_data(page: str):
26 | headers = {
27 | 'authority': 'web.chace-ai.com',
28 | 'accept': 'application/json, text/plain, */*',
29 | 'accept-language': 'zh-CN,zh;q=0.9',
30 | 'user-agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/107.0.0.0 Safari/537.36',
31 | # "authorization": "Bearer xxxxxx"
32 | }
33 | params = {
34 | 'page': page,
35 | 'size': '20',
36 | 'industry': '',
37 | 'area': 'RegisterArea_ZXS_Shanghai',
38 | 'dept': '',
39 | 'partition': '',
40 | 'pe_name': '',
41 | 'currentArea': 'RegisterArea_ZXS_Shanghai',
42 | 'query_date': '0',
43 | 'full_search': '0',
44 | 'sort_type': '0',
45 | }
46 | response = requests.get('https://web.chace-ai.com/api/ccw/project/evaluation/getList/', params=params,
47 | headers=headers)
48 | return response.json()
49 |
50 |
51 | def get_decrypt_data(encrypt_data):
52 | ctx = Utils(js_file_name='demo.js').read_js_file()
53 | return ctx.call('get_decrypt_data', encrypt_data)
54 |
55 |
56 | def parse():
57 | for page in range(1, 10):
58 | results = get_encrypt_data(str(page))
59 | encrypt_data = results['data']
60 | decrypt_data = get_decrypt_data(encrypt_data)
61 | print(decrypt_data)
62 | break
63 |
64 |
65 | if __name__ == '__main__':
66 | parse()
67 |
--------------------------------------------------------------------------------
/changelog.md:
--------------------------------------------------------------------------------
1 | ## changelog version 20230920
2 |
3 | #### 搜狐网(souhu)
4 |
5 | - 经观察,新闻详情页面: https://www.sohu.com/a/611710835_123753)
6 | - 包含的图片链接已经恢复正常,故该项目失效
7 |
8 | #### 福建省公共资源交易-交易信息(ggzyfu_fujian)
9 |
10 | - 获取请求头 `portal-sign` 时
11 | - md5盐值:`3637CB36B2E54A72A7002978D0506CDF` ==> `B3978D054A72A7002063637CCDF6B2E5`
12 |
13 | - 响应数据解密
14 | - AES
15 | - key值: `BE45D593014E4A4EB4449737660876CE` ==> `EB444973714E4A40876CE66BE45D5930`
16 | - iv值: `A8909931867B0425` ==> `B5A8904209931867`
17 |
18 | ***
19 |
20 | ## changelog version 20230630
21 |
22 | #### 查策网(chacewang)
23 |
24 | - 请求头发生变化,解密方式未发生变化
25 | - 添加了登录认证
26 | - 请求头需携带 `authorization` 字段
27 |
28 | #### 新榜资讯-废弃(newrank)
29 |
30 | - 必须登录才能请求到数据
31 |
32 | ***
33 |
34 | ## changelog version 20230328
35 |
36 | #### 易车网(yiche)
37 |
38 | - api接口发生变化
39 | - 原接口 `https://car.yiche.com/web_api/car_model_api/api/v1/car/config_new_param`
40 | - 新接口 `https://mapi.yiche.com/web_api/car_model_api/api/v1/car/config_new_param`
41 |
42 | #### 全国建筑市场监管公共服务平台 (jzsc)
43 |
44 | - api接口变更
45 | - 原接口 `https://jzsc.mohurd.gov.cn/Api/webApi/dataservice/query/comp/list`
46 | - 新接口 `https://jzsc.mohurd.gov.cn/APi/webApi/dataservice/query/comp/list`
47 | - 具体是 `/Api/` 变为 `/APi/`。字母`p`由小写变为大写
48 |
49 | ***
50 |
51 | ## changelog version 20230314
52 |
53 | #### 美食优惠聚合 (waitpay)
54 |
55 | - 网站停止维护
56 | - 主页: [https://static.waitwaitpay.com/web/sd_se/index.html#/](https://static.waitwaitpay.com/web/sd_se/index.html#/)
57 |
58 | #### 中国招投标公告服务中心 (ctbpsp)
59 |
60 | - 对响应数据进行解密的js进行变更
61 | - 原代码 `var keyHex = CryptoJS.enc.Utf8.parse("ctpstp@custominfo!@#qweASD");`
62 | - 新代码 `var keyHex = CryptoJS.enc.Utf8.parse("1qaz@wsx3e");`
63 |
64 | #### 中国·国家地名信息库 (dmfw_mca)
65 |
66 | - api接口变更
67 | - 原接口 `https://dmfw.mca.gov.cn/9095/stname/list`
68 | - 新接口 `https://dmfw.mca.gov.cn/stname/listPub`
69 |
70 | - 响应数据变更
71 | - 原接口 https://dmfw.mca.gov.cn/9095/stname/list 响应数据为密文,需要解密
72 | - 新接口 https://dmfw.mca.gov.cn/stname/listPub 响应数据为明文
73 |
74 | #### 全国建筑市场监管公共服务平台 (jzsc)
75 |
76 | - api接口变更
77 | - 原接口 `http://jzsc.mohurd.gov.cn/api/webApi/dataservice/query/comp/list`
78 | - 新接口 `https://jzsc.mohurd.gov.cn/Api/webApi/dataservice/query/comp/list`
79 |
80 | #### 黑猫投诉 (tousu_sign)
81 |
82 | - 部分字段的解析规则发生变化
83 |
--------------------------------------------------------------------------------
/chrome.md:
--------------------------------------------------------------------------------
1 | ## 更改chrome设置,使source面板显示具体行号
2 |
3 | - 修改前
4 | - 左侧栏不显示行号
5 | - 
6 |
7 | ***
8 |
9 | - 修改后
10 | - 
11 |
12 | ***
13 |
14 | > 步骤
15 |
16 | - 点击控制台中的设置按钮
17 | - 
18 |
19 | - 在显示出来的设置页面,取消勾选 `Experiments` 设置下的 `Automatically pretty print in the Sources Pabel` 即可
20 | - 
--------------------------------------------------------------------------------
/chromedriver.md:
--------------------------------------------------------------------------------
1 | ### 关于配置 `chromedriver` 环境
2 |
3 | 1. 在 `chrome` 浏览器上确认浏览器的环境 
4 | 2. 在 [http://chromedriver.storage.googleapis.com/index.html](http://chromedriver.storage.googleapis.com/index.html)
5 | 里,找到对应的 `chromedriver` 版本 
6 | 3. 下载该`chromedriver` 版本,并在使用selenium时,指定该驱动的路径即可,如下:
7 | ```@python
8 | driver = webdriver.Chrome(executable_path=f'{os.path.abspath(os.path.dirname(os.getcwd()))}/driver_path/chromedriver',options=option)
9 | ```
10 |
--------------------------------------------------------------------------------
/cnpub/__init__.py:
--------------------------------------------------------------------------------
1 | # _*_ coding: utf-8 _*_
2 | # @Date: 3:35 下午
3 | # @File: __init__.py.py
4 | # @Author: liyf
5 |
--------------------------------------------------------------------------------
/cnpub/demo.js:
--------------------------------------------------------------------------------
1 | var CryptoJS = require('crypto-js');
2 |
3 | var e1 = '16weizifuchuan16',
4 | i1 = '1suibianshurude6';
5 |
6 | function get_decrypt_data(t) {
7 | var s = CryptoJS["enc"].Utf8.parse(e1),
8 | n = CryptoJS["enc"].Utf8.parse(i1),
9 | o = CryptoJS["AES"].decrypt(CryptoJS["format"].Hex.parse(t), s, {
10 | iv: n,
11 | mode: CryptoJS["mode"].CBC,
12 | padding: CryptoJS["pad"].Pkcs7
13 | });
14 | return JSON.parse(CryptoJS["enc"].Utf8.stringify(o).toString())
15 | }
16 |
17 | function get_encrypt_params(para) {
18 | var s = CryptoJS["enc"].Utf8.parse(e1),
19 | n = CryptoJS["enc"].Utf8.parse(i1),
20 | o = CryptoJS["enc"].Utf8.parse(JSON.stringify(para)),
21 | c = CryptoJS["AES"].encrypt(o, s, {
22 | iv: n,
23 | mode: CryptoJS["mode"].CBC,
24 | padding: CryptoJS["pad"].Pkcs7
25 | });
26 | return c.ciphertext.toString()
27 | }
28 |
29 | var encrypt_data = {
30 | "newsType": 1,
31 | "pageNum": 6,
32 | "pageSize": 10,
33 | "title": ""
34 | },
35 | decrypt_data = get_encrypt_params(encrypt_data);
36 | console.log(decrypt_data)
37 |
--------------------------------------------------------------------------------
/cnpub/demo.py:
--------------------------------------------------------------------------------
1 | # _*_ coding: utf-8 _*_
2 | # @Date: 3:46 下午
3 | # @File: demo.py
4 | # @Author: liyf
5 |
6 | '''
7 | 标准aes加密解密
8 | '''
9 |
10 | import execjs
11 | import requests
12 |
13 | from loguru import logger
14 |
15 | headers = {
16 | "Accept": "application/json, text/plain, */*",
17 | "Accept-Language": "zh-CN,zh;q=0.9",
18 | "Content-Type": "application/json;charset=UTF-8",
19 | "Origin": "https://cnpub.com.cn",
20 | "Referer": "https://cnpub.com.cn/information.html",
21 | "User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/116.0.0.0 Safari/537.36",
22 | }
23 | url = "https://cnpub.com.cn/prod-api/api/index/newsList"
24 |
25 | f = open('demo.js', 'r', encoding='utf8')
26 | js_str = f.read()
27 | ctx = execjs.compile(''.join(js_str))
28 |
29 |
30 | def get_para_data(para, encrypt_data):
31 | if para:
32 | return ctx.call('get_encrypt_params', para)
33 | return ctx.call('get_decrypt_data', encrypt_data)
34 |
35 |
36 | def get_results(page):
37 | para = {
38 | "newsType": 1,
39 | "pageNum": page,
40 | "pageSize": 10,
41 | "title": ""
42 | }
43 | data = get_para_data(para=para, encrypt_data=None)
44 | logger.info(f'第 {page} 页加密参数: {data}')
45 | response = requests.post(url, headers=headers, data=data)
46 | return str(response.text).strip('"')
47 |
48 |
49 | def parse_data(page):
50 | encrypt_data = get_results(page)
51 | decrypt_data = get_para_data(para=None, encrypt_data=encrypt_data)
52 | rows = decrypt_data['list']['rows']
53 | for row in rows:
54 | title = row['title']
55 | author = row['author']
56 | origin = row['platformName']
57 | update_time = row['publishTime']
58 | print(f'标题: {title}\n作者: {author}\n出自: {origin}\n更新时间: {update_time}')
59 | print('***' * 25)
60 |
61 |
62 | def main():
63 | for page in range(1, 10):
64 | parse_data(page)
65 | print('===' * 30)
66 |
67 |
68 | if __name__ == '__main__':
69 | main()
70 |
--------------------------------------------------------------------------------
/cpws/__init__.py:
--------------------------------------------------------------------------------
1 | # _*_ coding: utf-8 _*_
2 | # @Date: 2:56 下午
3 | # @File: __init__.py.py
4 | # @Author: liyf
5 |
--------------------------------------------------------------------------------
/cpws/login.js:
--------------------------------------------------------------------------------
1 | window = global;
2 | var JSEncrypt = require('jsencrypt')
3 |
4 |
5 | function encrypt_pwd(e) {
6 | var t = "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA5GVku07yXCndaMS1evPIPyWwhbdWMVRqL4qg4OsKbzyTGmV4YkG8H0hwwrFLuPhqC5tL136aaizuL/lN5DRRbePct6syILOLLCBJ5J5rQyGr00l1zQvdNKYp4tT5EFlqw8tlPkibcsd5Ecc8sTYa77HxNeIa6DRuObC5H9t85ALJyDVZC3Y4ES/u61Q7LDnB3kG9MnXJsJiQxm1pLkE7Zfxy29d5JaXbbfwhCDSjE4+dUQoq2MVIt2qVjZSo5Hd/bAFGU1Lmc7GkFeLiLjNTOfECF52ms/dks92Wx/glfRuK4h/fcxtGB4Q2VXu5k68e/2uojs6jnFsMKVe+FVUDkQIDAQAB";
7 | var o = new JSEncrypt;
8 | o.setPublicKey(t);
9 | return encodeURIComponent(o.encrypt(e))
10 | }
11 |
12 | var pwd = encrypt_pwd('123456')
13 | console.log(pwd)
--------------------------------------------------------------------------------
/cpws/login.py:
--------------------------------------------------------------------------------
1 | # _*_ coding: utf-8 _*_
2 | # @Date: 10:20 上午
3 | # @File: login.py
4 | # @Author: liyf
5 |
6 | import requests
7 |
8 | from utils import *
9 |
10 | ctx = Utils(js_file_name='login.js').read_js_file()
11 |
12 |
13 | def get_login_res(username, pwd):
14 | headers = {
15 | 'Accept': '*/*',
16 | 'Accept-Language': 'zh-CN,zh;q=0.9',
17 | 'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8',
18 | 'Origin': 'https://account.court.gov.cn',
19 | 'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/111.0.0.0 Safari/537.36',
20 | 'X-Requested-With': 'XMLHttpRequest',
21 | }
22 | encrypt_pwd = ctx.call('encrypt_pwd', pwd)
23 | data = {
24 | 'username': username,
25 | 'password': encrypt_pwd,
26 | 'appDomain': 'wenshu.court.gov.cn',
27 | }
28 | response = requests.post('https://account.court.gov.cn/api/login', headers=headers, data=data)
29 | return response.json()
30 |
31 |
32 | def main():
33 | user = '1234567890'
34 | pwd = '123456'
35 | login_res = get_login_res(user, pwd)
36 | logger.info(f'登录结果如下:\n{login_res}') # {'code': '999999', 'data': None, 'message': '账户格式不正确', 'success': False}
37 | msg = login_res['message']
38 | logger.info(f'登录状态: {msg}') # 登录状态: 账户格式不正确
39 |
40 |
41 | if __name__ == '__main__':
42 | main()
43 |
--------------------------------------------------------------------------------
/ctbpsp/__init__.py:
--------------------------------------------------------------------------------
1 | # _*_ coding: utf-8 _*_
2 | # @Date: 2:53 下午
3 | # @File: __init__.py.py
4 | # @Author: liyf
5 |
--------------------------------------------------------------------------------
/ctbpsp/demo.js:
--------------------------------------------------------------------------------
1 | var CryptoJS = require('crypto-js');
2 |
3 | function decryptByDES(ciphertext) {
4 | // todo changelog20230314
5 | // 更改了key
6 | // ctpstp@custominfo!@#qweASD 变为了 1qaz@wsx3e
7 |
8 | // var keyHex = CryptoJS.enc.Utf8.parse("ctpstp@custominfo!@#qweASD");
9 | var keyHex = CryptoJS.enc.Utf8.parse("1qaz@wsx3e");
10 | // direct decrypt ciphertext
11 | var decrypted = CryptoJS.DES.decrypt(
12 | {
13 | ciphertext: CryptoJS.enc.Base64.parse(ciphertext),
14 | },
15 | keyHex,
16 | {
17 | mode: CryptoJS.mode.ECB,
18 | padding: CryptoJS.pad.Pkcs7,
19 | }
20 | );
21 | return decrypted.toString(CryptoJS.enc.Utf8);
22 | }
--------------------------------------------------------------------------------
/ctbpsp/demo.py:
--------------------------------------------------------------------------------
1 | # _*_ coding: utf-8 _*_
2 | # @Date: 2:53 下午
3 | # @File: demo.py
4 | # @Author: liyf
5 |
6 | import json
7 | import requests
8 |
9 | from utils import *
10 |
11 |
12 | def get_decrypt_data(encrypt_data):
13 | ctx = Utils(js_file_name='demo.js').read_js_file()
14 | return json.loads(ctx.call('decryptByDES', encrypt_data))
15 |
16 |
17 | def get_results(page):
18 | headers = {
19 | 'Accept': 'application/json, text/plain, */*',
20 | 'Accept-Language': 'zh-CN,zh;q=0.9',
21 | 'Cache-Control': 'no-cache',
22 | 'Connection': 'keep-alive',
23 | 'Origin': 'http://ctbpsp.com',
24 | 'Referer': 'http://ctbpsp.com/',
25 | 'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/105.0.0.0 Safari/537.36',
26 | }
27 |
28 | response = requests.get(
29 | f'https://custominfo.cebpubservice.com/cutominfoapi/recommand/type/5/pagesize/10/currentpage/{page}',
30 | headers=headers)
31 | return response.text
32 |
33 |
34 | def parse():
35 | for page in range(1, 31):
36 | encrypt_data = get_results(page)
37 | # solve error: execjs._exceptions.ProgramError: Error: Malformed UTF-8 data
38 | # 把返回的加密数据进行strip('"')操作
39 | decrypt_data = get_decrypt_data(encrypt_data.strip('"'))
40 | data_list = decrypt_data['data']['dataList']
41 | for data in data_list:
42 | title = data['noticeName']
43 | province = data['reginProvince']
44 | bulletin_type = data['bulletinTypeName']
45 | accept_time = data['noticeSendTime']
46 | uuid = data['bulletinID']
47 | detail_url = f'http://ctbpsp.com/#/bulletinDetail?uuid={uuid}&inpvalue=&dataSource=0'
48 | print(f'标题: {title}\n公告类型: {bulletin_type}\n省份: {province}\n接收时间: {accept_time}\n详情url地址: {detail_url}')
49 | print('===' * 30)
50 |
51 |
52 | if __name__ == '__main__':
53 | parse()
54 |
--------------------------------------------------------------------------------
/ctyun/__init__.py:
--------------------------------------------------------------------------------
1 | # _*_ coding: utf-8 _*_
2 | # @Date: 4:15 下午
3 | # @File: __init__.py
4 | # @Author: liyf
5 |
--------------------------------------------------------------------------------
/ctyun/demo.js:
--------------------------------------------------------------------------------
1 | var CryptoJS = require('crypto-js'),
2 | // Object(u["c"]
3 | T = function (e) {
4 | var n = arguments.length > 1 && void 0 !== arguments[1] ? arguments[1] : ""
5 | , t = arguments.length > 2 && void 0 !== arguments[2] ? arguments[2] : {}
6 | , a = t.enc
7 | , r = void 0 === a ? "Utf8" : a
8 | , c = t.mode
9 | , i = void 0 === c ? "ECB" : c
10 | , o = t.padding
11 | , u = void 0 === o ? "Pkcs7" : o
12 | , d = CryptoJS.enc[r].parse(n)
13 | , l = {
14 | mode: CryptoJS.mode[i],
15 | padding: CryptoJS.pad[u]
16 | }
17 | , s = CryptoJS.TripleDES.encrypt(e, d, l);
18 | return s.toString()
19 | },
20 | // Object(u["f"])
21 | F = function (e) {
22 | var n = arguments.length > 1 && void 0 !== arguments[1] ? arguments[1] : {};
23 | if (e && "string" === typeof e) {
24 | var t = n.text || "0"
25 | , a = n.length || 24;
26 | if (e.length < a)
27 | for (var r = e.length; r < a; r++)
28 | e += t;
29 | else
30 | e = e.substring(0, a);
31 | return e
32 | }
33 | };
34 |
35 | //password: encodeURI(Object(u["c"])(s.value, Object(u["f"])(Object(u["g"])(r.value))))
36 | function get_pwd(pwd, username) {
37 | return encodeURI(T(pwd, F(username)))
38 | }
39 |
40 | var pwd = '123456',
41 | username = 'liyufeng123',
42 | enc_pwd = get_pwd(pwd, username);
43 | console.log(enc_pwd)
44 |
--------------------------------------------------------------------------------
/dewu/__init__.py:
--------------------------------------------------------------------------------
1 | # _*_ coding: utf-8 _*_
2 | # @Date: 3:21 下午
3 | # @File: __init__.py.py
4 | # @Author: liyf
5 |
--------------------------------------------------------------------------------
/dewu/demo.py:
--------------------------------------------------------------------------------
1 | # _*_ coding: utf-8 _*_
2 | # @Date: 3:21 下午
3 | # @File: demo.py
4 | # @Author: liyf
5 |
6 | """
7 | todo: https://m.poizon.com/router/
8 | 破解得物产品列表页中请求参数 `sign`
9 | 接口: https://app.poizon.com/api/v1/h5/index/fire/index
10 | - POST请求
11 | - params中 `sign` 需要破解
12 | 通过搜索关键字 `sign:` 可以定位到加密函数在 `index.7cee99cc.js`文件第9296行,如下:
13 | todo```
14 | var n = C(e.params);
15 | return e.params = L({
16 | sign: n
17 | }, e.params),
18 | ```
19 | 其中 `C(e.params)` 就是生成sign的入口,且e.params=发送post请求需要的参数。
20 | 接着就是常规操作,下断点,进入该函数之后,看下该函数做了什么操作,然后实行 `缺啥补啥` 的准则,扣js代码。
21 | """
22 |
23 | import requests
24 |
25 | from utils import *
26 |
27 |
28 | def get_sign(page):
29 | ctx = Utils(js_file_name='demo.js').read_js_file()
30 | return ctx.call('get_sign', page)
31 |
32 |
33 | def get_results(page):
34 | headers = {
35 | 'Accept': 'application/json, text/plain, */*',
36 | 'Accept-Language': 'zh-CN,zh;q=0.9',
37 | 'Origin': 'https://m.poizon.com',
38 | 'Referer': 'https://m.poizon.com/',
39 | 'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/104.0.0.0 Safari/537.36',
40 | }
41 | sign = get_sign(page)
42 | logger.info(f'第 {page} 页: {sign}')
43 | json_data = {
44 | 'sign': sign,
45 | 'tabId': '',
46 | 'limit': 20,
47 | 'lastId': page,
48 | 'platform': 'h5',
49 | 'version': '4.73.0',
50 | 'isVisitor': False,
51 | 'newAdvForH5': True,
52 | }
53 |
54 | response = requests.post('https://app.poizon.com/api/v1/h5/index/fire/index', headers=headers, json=json_data)
55 | return response.json()
56 |
57 |
58 | def parse():
59 | for page in range(1, 10):
60 | results = get_results(page)
61 | data_list = results['data']['hotList']
62 | for data in data_list:
63 | product = data['product']
64 | title = product['title']
65 | soldCountText = product['soldCountText']
66 | price = int(product['price']) / 100
67 | logoUrl = product['logoUrl']
68 | print(f'产品名称: {title}\n价格: {price}\n销量: {soldCountText}\n图片地址: {logoUrl}')
69 | print('===' * 35)
70 |
71 |
72 | if __name__ == '__main__':
73 | parse()
74 |
--------------------------------------------------------------------------------
/didiwaimai/__init__.py:
--------------------------------------------------------------------------------
1 | # _*_ coding: utf-8 _*_
2 | # @Date: 4:56 下午
3 | # @File: __init__.py.py
4 | # @Author: liyf
5 |
--------------------------------------------------------------------------------
/didiwaimai/demo.py:
--------------------------------------------------------------------------------
1 | # _*_ coding: utf-8 _*_
2 | # @Date: 4:45 下午
3 | # @File: demo.py
4 | # @Author: liyf
5 |
6 | '''
7 | 主页: https://passport.didichuxing.com/#/
8 | 接口: https://epassport.diditaxi.com.cn/passport/login/v5/signInByPassword?wsgsig=xxx
9 | - get请求
10 | - 需要破解 `wsgsig` 参数
11 | todo 破解流程
12 | - 直接通过全局搜索关键字 `wsgsig` 可以直接定位到加密位置,如下
13 | - `wsgsig: E.a.getSign.apply(E.a, e)`
14 | - 在此处下断点,并点击登录。断点生效,说明此处为加密位置
15 |
16 | - 通过格式可以判断出,该参数的加密大概率是webpack,所以在该处往上查找 `E` 的定义,找到如下代码
17 | - `O = n("Yt3Z")
18 | , E = n.n(O);`
19 | - 从而确定该加密为webpack
20 |
21 | - 所以老老实实的找分发器,并扣所需要的模块
22 | - 在 `O = n("Yt3Z")` 处下断点,重新刷新页面,断点即可生效,在控制台输入 `n`,即为分发器,复制下来即可
23 | - 所需要的模块只有两个,分别为 `Yt3Z` 和 `3IRH`
24 |
25 | - 封装js代码,使入口函数返回值为 `wsgsig` 即可,带入到python代码中测试
26 | - 测试结果,当传入的账号和密码分别为 `16677882222` 和 `123456` 时,接口返回的结果如下:
27 | - `
28 | {'errno': 51003, 'error': '用户信息不存在', 'requestid': '1673860276422932612', 'traceid': '0a22221b63c514b4950e7b955d141b02', 'time': '2023-01-16 17:11:16'}
29 | `
30 | - 跟网页上的返回结果一致,验证成功!
31 |
32 | - 难度,入门
33 | '''
34 | import requests
35 |
36 | from utils import *
37 |
38 |
39 | def get_wsgsig(data):
40 | ctx = Utils(js_file_name='demo.js').read_js_file()
41 | return ctx.call('get_wsgsig', data)
42 |
43 |
44 | def get_results(username, pwd):
45 | """
46 | 获取接口返回信息
47 | :param username: 明文账号
48 | :param pwd: 明文密码
49 | :return: 响应结果
50 | """
51 | headers = {
52 | 'Accept': 'application/json, text/plain, */*',
53 | 'Accept-Language': 'zh-CN,zh;q=0.9',
54 | 'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/109.0.0.0 Safari/537.36',
55 | }
56 | data = {
57 | 'q': '{"domain":"https://epassport.diditaxi.com.cn","role":13,"appid":50001,"source":70001,"api_version":"1.0.1","lang":"zh-CN","imei":"cef8ea1124037639533c070c708e672d","cell":"%s","country_calling_code":"+86","country_id":156,"password":"%s"}' % (
58 | username, pwd),
59 | }
60 | wsgsig = get_wsgsig(data)
61 | logger.info(f'wsgsig: {wsgsig}')
62 | params = {
63 | 'wsgsig': wsgsig,
64 | }
65 | response = requests.post(
66 | 'https://epassport.diditaxi.com.cn/passport/login/v5/signInByPassword',
67 | params=params,
68 | headers=headers,
69 | data=data,
70 | )
71 | return response.json()
72 |
73 |
74 | if __name__ == '__main__':
75 | results = get_results('16677882222', '123456')
76 | logger.info(f'接口响应结果:\n{results}')
77 | logger.info(f'账号信息: {results["error"]}')
78 |
--------------------------------------------------------------------------------
/dmfw_mca/__init__.py:
--------------------------------------------------------------------------------
1 | # _*_ coding: utf-8 _*_
2 | # @Date: 5:05 下午
3 | # @File: __init__.py.py
4 | # @Author: liyf
5 |
--------------------------------------------------------------------------------
/dmfw_mca/demo.js:
--------------------------------------------------------------------------------
1 | var CryptoJS = require('crypto-js');
2 |
3 | function decryptByDES(ciphertext, key) {
4 | var keyHex = CryptoJS.enc.Utf8.parse(key);
5 | var decrypted = CryptoJS.DES.decrypt({
6 | ciphertext: CryptoJS.enc.Base64.parse(ciphertext)
7 | }, keyHex, {
8 | mode: CryptoJS.mode.ECB,
9 | padding: CryptoJS.pad.ZeroPadding
10 | });
11 | var data = decrypted.toString(CryptoJS.enc.Utf8);
12 | var lastNum = data.lastIndexOf("}");
13 | data = JSON.parse(data.substring(0, lastNum + 1));
14 | return data;
15 | }
--------------------------------------------------------------------------------
/dmfw_mca/demo.py:
--------------------------------------------------------------------------------
1 | # _*_ coding: utf-8 _*_
2 | # @Date: 5:18 下午
3 | # @File: demo.py
4 | # @Author: liyf
5 |
6 | '''
7 | todo changelog 20230314
8 | 接口变更
9 | - https://dmfw.mca.gov.cn/9095/stname/list 改变为 https://dmfw.mca.gov.cn/stname/listPub
10 | - 请求参数不变和请求方法都不变
11 | 响应数据变更
12 | - 原接口 https://dmfw.mca.gov.cn/9095/stname/list 响应数据为密文,需要解密
13 | - 新接口 https://dmfw.mca.gov.cn/stname/listPub 响应数据为明文
14 |
15 | '''
16 | import requests
17 |
18 | headers = {
19 | 'Accept': '*/*',
20 | 'Accept-Language': 'zh-CN,zh;q=0.9',
21 | 'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8',
22 | 'Origin': 'https://dmfw.mca.gov.cn',
23 | 'Referer': 'https://dmfw.mca.gov.cn/online/map.html',
24 | 'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/105.0.0.0 Safari/537.36',
25 | 'X-Requested-With': 'XMLHttpRequest',
26 | }
27 |
28 |
29 | def get_results(keyword):
30 | data = {
31 | 'type': 'place',
32 | 'stName': keyword,
33 | 'placeTypeCode': '',
34 | 'placeTypeCodeLen': '0',
35 | 'code': '',
36 | 'adminCodeLen': '0',
37 | 'year': '2022',
38 | 'searchType': '模糊',
39 | 'page': '1',
40 | 'size': '10',
41 | }
42 | response = requests.post('https://dmfw.mca.gov.cn/stname/listPub', headers=headers, data=data)
43 | return response.json()
44 |
45 |
46 | def parse():
47 | while True:
48 | keyword = input('请输入关键字:')
49 | results = get_results(keyword)
50 | records = results['records']
51 | if not records:
52 | print(f'该关键字 (`{keyword}`) 下没有数据')
53 | print(f'===' * 20)
54 | for record in records:
55 | title = record['standard_name']
56 | province = record['province_name']
57 | city = record['city_name']
58 | area_name = record['area_name']
59 | pca = f'{province}-{city}-{area_name}'
60 | place_type = record['place_type']
61 | print(f'搜索关键字: {keyword}\n标准名称: {title}\n地址: {pca}\n地区所属类型: {place_type}')
62 | print('===' * 20)
63 |
64 |
65 | if __name__ == '__main__':
66 | parse()
67 |
--------------------------------------------------------------------------------
/driver_path/chromedriver:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/liyf-code/reverse_practice/e7e984ab8926770c4c193f4e717bcc02cfe1cf44/driver_path/chromedriver
--------------------------------------------------------------------------------
/ehsy/__init__.py:
--------------------------------------------------------------------------------
1 | # _*_ coding: utf-8 _*_
2 | # @Date: 10:50 上午
3 | # @File: __init__.py.py
4 | # @Author: liyf
5 |
--------------------------------------------------------------------------------
/ehsy/demo.js:
--------------------------------------------------------------------------------
1 | /*
2 | 全局搜索请求头关键字 'ehsy-verify'
3 | 搜索结果只有一个,代码如下:
4 | "ehsy-verify": (0, o.aes_gobal)()
5 | 在该处下断点。下拉页面,断点生效。
6 |
7 | - 进入该函数内部,可定位到请求头参数生成的具体逻辑
8 |
9 | todo 逻辑如下
10 | - 生成一个长度为10的时间戳,并转字符串 t
11 | - 对该时间戳 t 进行md5加密得到n
12 | - 对 n 进行一系列数组操作
13 | - n.splice(2, 1, "e"),意思是在索引为2的位置删除一个元素,并添加新元素 'e'
14 | - 之后再把新数组转字符串,并加上最开始的时间戳 t。作为aes待加密的数据
15 | - aes的key就是对字符串 GvcaHhBsKa9kkHmf 进行md5加密
16 | - 最终返回的至就是请求头的值
17 | */
18 |
19 |
20 | var CryptoJS = require('crypto-js');
21 |
22 | function g(e) {
23 | var n = CryptoJS.enc.Utf8.parse(e)
24 | , i = CryptoJS.MD5('GvcaHhBsKa9kkHmf')
25 | , o = CryptoJS.AES.encrypt(n, i, {
26 | mode: CryptoJS.mode.ECB,
27 | padding: CryptoJS.pad.Pkcs7
28 | });
29 | return o.toString()
30 | }
31 |
32 | function p() {
33 | var n, i, o, t = ((new Date).getTime() + "").slice(0, 10);
34 | var e = CryptoJS.MD5(t).toString();
35 | return n = e.split(""),
36 | n.splice(2, 1, "e"),
37 | n.splice(6, 1, "h"),
38 | n.splice(12, 1, 6),
39 | n.splice(25, 1, "b"),
40 | i = n.join("") + t,
41 | o = g(i),
42 | o
43 | }
44 |
--------------------------------------------------------------------------------
/ehsy/demo.py:
--------------------------------------------------------------------------------
1 | # _*_ coding: utf-8 _*_
2 | # @Date: 10:50 上午
3 | # @File: demo.py
4 | # @Author: liyf
5 |
6 | import execjs
7 | import requests
8 |
9 | from loguru import logger
10 |
11 | headers = {
12 | "Accept": "*/*",
13 | "Accept-Language": "zh-CN,zh;q=0.9",
14 | "Cache-Control": "no-cache",
15 | "Connection": "keep-alive",
16 | "Origin": "https://m.ehsy.com",
17 | "Pragma": "no-cache",
18 | "Referer": "https://m.ehsy.com/",
19 | "Sec-Fetch-Dest": "empty",
20 | "Sec-Fetch-Mode": "cors",
21 | "Sec-Fetch-Site": "same-site",
22 | "User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.0.0 Safari/537.36",
23 | "content-type": "application/x-www-form-urlencoded",
24 | }
25 |
26 | url = "https://m2.ehsy.com/pb/product/search/filter"
27 | f = open('demo.js', 'r')
28 | js_str = f.readlines()
29 | ctx = execjs.compile(''.join(js_str))
30 |
31 |
32 | def get_results(start):
33 | data = {
34 | "search": "{'catId':'16474','filterFieldsValues':{},'filters':{}}",
35 | "flag": "true",
36 | "sortType": "0",
37 | "start": start,
38 | "rows": "20",
39 | "cityId": "321",
40 | "token": "",
41 | "createFrom": "m"
42 | }
43 | ehsy_verify = ctx.call('p')
44 | logger.info(f'ehsy_verify: {ehsy_verify}')
45 | headers['ehsy-verify'] = ehsy_verify
46 | response = requests.post(url, headers=headers, data=data)
47 | return response.json()
48 |
49 |
50 | def main():
51 | for start in range(0, 200, 20):
52 | results = get_results(start)
53 | data_list = results['data']['queryPage']['data']
54 | for data in data_list:
55 | title = data['productName']
56 | brand = data['brandName']
57 | sku_code = data['skuCode']
58 | sale = data['salePrice']
59 | print(f'名称: {title}\n品牌型号: {brand}\n订货号: {sku_code}\n含税: {sale}')
60 | print('=====' * 15)
61 |
62 |
63 | if __name__ == '__main__':
64 | main()
65 |
--------------------------------------------------------------------------------
/endata/__init__.py:
--------------------------------------------------------------------------------
1 | # _*_ coding: utf-8 _*_
2 | # @Date: 4:33 下午
3 | # @File: __init__.py.py
4 | # @Author: liyf
5 |
--------------------------------------------------------------------------------
/endata/demo.py:
--------------------------------------------------------------------------------
1 | # _*_ coding: utf-8 _*_
2 | # @Date: 4:42 下午
3 | # @File: demo.py
4 | # @Author: liyf
5 | import json
6 | import requests
7 |
8 | from utils import *
9 |
10 |
11 | def get_results(params):
12 | headers = {
13 | 'Accept': 'text/plain, */*; q=0.01',
14 | 'Accept-Language': 'zh-CN,zh;q=0.9',
15 | 'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8',
16 | 'Origin': 'https://www.endata.com.cn',
17 | 'Pragma': 'no-cache',
18 | 'Sec-Fetch-Dest': 'empty',
19 | 'Sec-Fetch-Mode': 'cors',
20 | 'Sec-Fetch-Site': 'same-origin',
21 | 'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/104.0.0.0 Safari/537.36',
22 | 'X-Requested-With': 'XMLHttpRequest',
23 | 'sec-ch-ua': '"Chromium";v="104", " Not A;Brand";v="99", "Google Chrome";v="104"',
24 | 'sec-ch-ua-mobile': '?0',
25 | 'sec-ch-ua-platform': '"macOS"',
26 | }
27 |
28 | data = {
29 | 'startTime': params,
30 | 'MethodName': 'BoxOffice_GetMonthBox',
31 | }
32 |
33 | response = requests.post('https://www.endata.com.cn/API/GetData.ashx', headers=headers, data=data)
34 | return response.text
35 |
36 |
37 | def get_decrypt_data(encrypt_data):
38 | ctx = Utils(js_file_name='demo.js').read_js_file()
39 | return ctx.call('webInstace.shell', encrypt_data)
40 |
41 |
42 | def parse():
43 | time_list = ['2021-12-01', '2022-01-01', '2022-02-01', '2022-03-01', '2022-04-01', '2022-05-01', '2022-06-01',
44 | '2022-07-01', '2022-08-01', '2022-09-01']
45 | for params in time_list:
46 | results = get_results(params)
47 | decrypt_data = json.loads(get_decrypt_data(results))
48 | data_list = decrypt_data['Data']['Table']
49 | ymd_list = params.split('-')
50 | logger.info(f'{ymd_list[0]} 年 {ymd_list[1]} 月份票房数据如下:')
51 | for data in data_list:
52 | ranking = data['Irank']
53 | m_name = data['MovieName']
54 | r_time = data['releaseTime']
55 | boxoffice = data['boxoffice']
56 | avgboxoffice = data['avgboxoffice']
57 | avgshowcount = data['avgshowcount']
58 | box_pro = data['box_pro']
59 | detail_url = f'https://www.endata.com.cn/BoxOffice/MovieStock/movieShow.html?id={data["EnMovieID"]}'
60 | print(
61 | f'排序: {ranking}\n电影名称: {m_name}\n上映时间: {r_time}\n单月票房(万): {boxoffice}\n平均票价: {avgboxoffice}\n场均人次: {avgshowcount}\n月度占比: {box_pro}%\n详情地址: {detail_url}')
62 | print('===' * 30)
63 |
64 |
65 | if __name__ == '__main__':
66 | parse()
67 |
--------------------------------------------------------------------------------
/fenbi/__init__.py:
--------------------------------------------------------------------------------
1 | # _*_ coding: utf-8 _*_
2 | # @Date: 4:24 下午
3 | # @File: __init__.py.py
4 | # @Author: liyf
5 |
--------------------------------------------------------------------------------
/fenbi/demo.py:
--------------------------------------------------------------------------------
1 | # _*_ coding: utf-8 _*_
2 | # @Date: 4:24 下午
3 | # @File: demo.py
4 | # @Author: liyf
5 |
6 | '''
7 | 粉笔网登录破解 - https://fenbi.com/page/home
8 | 简单的RAS加密
9 | '''
10 | import requests
11 |
12 | from utils import *
13 |
14 |
15 | def get_js_pwd(password):
16 | ctx = Utils(js_file_name='demo.js').read_js_file()
17 | return ctx.call('get_password', password)
18 |
19 |
20 | def get_json_data(user, pwd):
21 | headers = {
22 | 'Accept': 'application/json, text/plain, */*',
23 | 'Accept-Language': 'zh-CN,zh;q=0.9',
24 | 'Content-Type': 'application/x-www-form-urlencoded;charset=UTF-8',
25 | 'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/102.0.0.0 Safari/537.36',
26 | }
27 |
28 | params = {
29 | 'kav': '12',
30 | 'app': 'web',
31 | }
32 | data = {
33 | 'password': get_js_pwd(pwd),
34 | 'persistent': 'true',
35 | 'app': 'web',
36 | 'phone': user,
37 | }
38 | response = requests.post('https://login.fenbi.com/api/users/loginV2?kav=12&app=web&av=80', params=params,
39 | headers=headers, data=data)
40 | return response.json()
41 |
42 |
43 | def main():
44 | # user = input('请输入账号:')
45 | # pwd = input('请输入密码:')
46 | user = '1234567890'
47 | pwd = '111111'
48 | results = get_json_data(user, pwd)
49 | print(results)
50 |
51 |
52 | if __name__ == '__main__':
53 | # https://fenbi.com/page/home
54 | main()
55 |
--------------------------------------------------------------------------------
/ggzyfw_fujian/__init__.py:
--------------------------------------------------------------------------------
1 | # _*_ coding: utf-8 _*_
2 | # @Date: 10:30 上午
3 | # @File: __init__.py.py
4 | # @Author: liyf
5 |
--------------------------------------------------------------------------------
/ggzyfw_fujian/demo.js:
--------------------------------------------------------------------------------
1 | var CryptoJS = require('crypto-js')
2 |
3 | function b(e) {
4 | var t = CryptoJS.enc.Utf8.parse('EB444973714E4A40876CE66BE45D5930')
5 | , n = CryptoJS.enc.Utf8.parse('B5A8904209931867')
6 | , a = CryptoJS.AES.decrypt(e, t, {
7 | iv: n,
8 | mode: CryptoJS.mode.CBC,
9 | padding: CryptoJS.pad.Pkcs7
10 | });
11 | return a.toString(CryptoJS.enc.Utf8)
12 | }
--------------------------------------------------------------------------------
/ggzyfw_fujian/demo.py:
--------------------------------------------------------------------------------
1 | # _*_ coding: utf-8 _*_
2 | # @Date: 10:30 上午
3 | # @File: demo.py
4 | # @Author: liyf
5 |
6 | '''
7 | changelog 20221018
8 | 加密方法没有变化,只是post请求的接口url地址发生变化
9 | 变化前的接口: https://ggzyfw.fujian.gov.cn/Trade/TradeInfo
10 | 变化后的接口: https://ggzyfw.fujian.gov.cn/FwPortalApi/Trade/TradeInfo
11 | **************************************************************
12 |
13 | changelog 20220818
14 | todo: https://ggzyfw.fujian.gov.cn/web/index.html#/business/list
15 | 该网站需要破解两处加密
16 | 1. 请求头 `portal-sign` 破解
17 | portal-sign 是通过对请求参数的一些操作之后,合并成一串字符串,然后对这个字符串进行md5加密
18 | 2. 返回数据解密
19 | - 由于是需要对接口返回的值进行解密
20 | - 所以通过搜索关键字 `decrypt(` 定位到解密函数在 `app.3cebabfd.js` 文件中,在返回值处下断点,点击下一页,断点生效
21 | function b(e) {
22 | var t = CryptoJS.enc.Utf8.parse('BE45D593014E4A4EB4449737660876CE')
23 | , n = CryptoJS.enc.Utf8.parse('A8909931867B0425')
24 | , a = CryptoJS.AES.decrypt(e, t, {
25 | iv: n,
26 | mode: CryptoJS.mode.CBC,
27 | padding: CryptoJS.pad.Pkcs7
28 | });
29 | return a.toString(CryptoJS.enc.Utf8)
30 | }
31 | - 在控制台输出 a.toString(CryptoJS.enc.Utf8),为明文数据。
32 | - AES-CBC模式,Pkcs7填充方式
33 | '''
34 |
35 | import time
36 | import json
37 | import js2py
38 | import requests
39 |
40 | from utils import *
41 |
42 |
43 | def get_n(params):
44 | js_str = '''
45 | function l(e, t) {
46 | return e.toString().toUpperCase() > t.toString().toUpperCase() ? 1 : e.toString().toUpperCase() == t.toString().toUpperCase() ? 0 : -1
47 | }
48 |
49 | function s(e) {
50 | for (var t = Object.keys(e).sort(l), n = "", a = 0; a < t.length; a++)
51 | if (void 0 !== e[t[a]])
52 | if (e[t[a]] && e[t[a]] instanceof Object || e[t[a]] instanceof Array) {
53 | var c = JSON.stringify(e[t[a]]);
54 | n += t[a] + c
55 | } else
56 | n += t[a] + e[t[a]];
57 | return n
58 | }
59 |
60 | function get_n(e) {
61 | for (var t in e)
62 | "" !== e[t] && void 0 !== e[t] || delete e[t];
63 | var n = 'B3978D054A72A7002063637CCDF6B2E5' + s(e);
64 | return n
65 | }
66 | '''
67 | context = js2py.EvalJs()
68 | context.execute(js_str)
69 | n = context.get_n(params)
70 | return n
71 |
72 |
73 | def get_data(Data):
74 | ctx = Utils(js_file_name='demo.js').read_js_file()
75 | return ctx.call('b', Data)
76 |
77 |
78 | def get_results(page):
79 | json_data = {
80 | 'pageNo': page,
81 | 'pageSize': 20,
82 | 'total': 6473,
83 | 'KIND': 'GCJS',
84 | 'GGTYPE': '1',
85 | 'PROTYPE': '',
86 | 'AREACODE': '',
87 | 'M_PROJECT_TYPE': '',
88 | 'timeType': '6',
89 | 'BeginTime': '2022-02-17 00:00:00',
90 | 'EndTime': '2022-08-17 23:59:59',
91 | 'createTime': [],
92 | 'ts': int(time.time() * 1000),
93 | }
94 | n = get_n(json_data)
95 | portal_sign = Utils(origin_md5_str=n).encrypt_md5()
96 | logger.info(f'第 {page} 页,portal_sign:{portal_sign}')
97 | headers = {
98 | 'Accept': 'application/json, text/plain, */*',
99 | 'Accept-Language': 'zh-CN,zh;q=0.9',
100 | 'Content-Type': 'application/json;charset=UTF-8',
101 | 'Origin': 'https://ggzyfw.fujian.gov.cn',
102 | 'Referer': 'https://ggzyfw.fujian.gov.cn/web/index.html',
103 | 'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/104.0.0.0 Safari/537.36',
104 | 'portal-sign': portal_sign,
105 | }
106 | response = requests.post('https://ggzyfw.fujian.gov.cn/FwPortalApi/Trade/TradeInfo', headers=headers,
107 | json=json_data)
108 | return response.json()
109 |
110 |
111 | def parse():
112 | for page in range(1, 324):
113 | results = get_results(page)
114 | data = json.loads(get_data(results['Data']))
115 | table_list = data['Table']
116 | for table in table_list:
117 | city_level = table['AREANAME']
118 | name = table['PLATFORM_NAME']
119 | title = table['NAME']
120 | update_time = table['TM1']
121 | print(f'【{city_level} - {name}】{title} {str(update_time).split(" ")[0]}')
122 | print('===' * 35)
123 |
124 |
125 | if __name__ == '__main__':
126 | parse()
127 |
--------------------------------------------------------------------------------
/hh1024/__init__.py:
--------------------------------------------------------------------------------
1 | # _*_ coding: utf-8 _*_
2 | # @Date: 3:08 下午
3 | # @File: __init__.py.py
4 | # @Author: liyf
5 |
--------------------------------------------------------------------------------
/hh1024/demo.py:
--------------------------------------------------------------------------------
1 | # _*_ coding: utf-8 _*_
2 | # @Date: 3:08 下午
3 | # @File: demo.py
4 | # @Author: liyf
5 |
6 | '''
7 | 主页: http://www.hh1024.com/#/login?redirect=%2FrealTimeLiving
8 | 登录接口: https://user.hrdjyun.com/wechat/phonePwdLogin
9 | - post请求
10 | - 请求参数中pwd和sig参数需要破解
11 |
12 | todo 破解流程
13 | - pwd
14 | - 根据经验,可以确定为md5加密
15 |
16 | - sig
17 | - 全局搜索 `sig:` 可以定位到关键代码如下:
18 | var l = Object(g["a"])(P(S(e)));
19 | sig: l
20 | - 接下来就是扣代码环节,缺啥补啥,没啥难度
21 |
22 | - 封装js代码,代入到python文件中
23 | - 当账号和密码分别为 `12345678919` 和 `123456` 时
24 | - 测试结果:{'status': 3, 'message': '手机号还未注册', 'data': None}
25 | - 跟网页上的返回结果一致,验证成功!
26 |
27 | - 基础入门,适合新手练习
28 | '''
29 |
30 | import time
31 | import requests
32 |
33 | from utils import *
34 |
35 |
36 | def get_sig(params):
37 | ctx = Utils(js_file_name='demo.js').read_js_file()
38 | return ctx.call('get_sig', params)
39 |
40 |
41 | def get_results(username, pwd):
42 | headers = {
43 | 'Accept': 'application/json, text/plain, */*',
44 | 'Accept-Language': 'zh-CN,zh;q=0.9',
45 | 'Content-Type': 'application/json',
46 | 'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/109.0.0.0 Safari/537.36',
47 | }
48 | pwd = Utils(origin_md5_str=pwd).encrypt_md5()
49 | logger.info(f'加密后的密码: {pwd}')
50 | json_data = {
51 | 'phoneNum': str(username),
52 | 'pwd': pwd,
53 | 't': int(time.time() * 1000),
54 | 'tenant': 1,
55 | }
56 | sig = get_sig(json_data)
57 | logger.info(f'sig参数获取: {sig}')
58 | json_data['sig'] = sig
59 | response = requests.post('https://user.hrdjyun.com/wechat/phonePwdLogin', headers=headers, json=json_data)
60 | return response.json()
61 |
62 |
63 | if __name__ == '__main__':
64 | results = get_results('12345678919', '123456')
65 | logger.info(f'接口响应结果:\n{results}')
66 | logger.info(f'账号信息: {results["message"]}')
67 |
--------------------------------------------------------------------------------
/hjs/__init__.py:
--------------------------------------------------------------------------------
1 | # _*_ coding: utf-8 _*_
2 | # @Date: 11:30 上午
3 | # @File: __init__.py.py
4 | # @Author: liyf
5 |
--------------------------------------------------------------------------------
/hjs/demo.py:
--------------------------------------------------------------------------------
1 | # _*_ coding: utf-8 _*_
2 | # @Date: 11:30 上午
3 | # @File: demo.py
4 | # @Author: liyf
5 |
6 | '''
7 | 主页地址: https://www.hfax.com/login.html#/?rsrc=https%3A%2F%2Fwww.hfax.com%2Fabout.html%23%2Fquestions
8 |
9 | 逆向参数: 登录所需的pwd
10 | 加密方式: 加盐的md5
11 |
12 | todo list
13 | - 全局搜索 `password:`
14 | - 可定位参数在 `login.xxx.js` 文件中。点击进入该文件之后,在再该文件中重新搜索 `password:`,可定位到以下代码
15 | - a = encryptByDES(this.password);
16 | - 在该处下断点,重新点击登录按钮,断点生效。
17 | - 单步调试,进入该函数后,发现以下代码
18 | - CryptoJS.MD5(t + "TuD00Iqz4ge7gzIe2rmjSAFFKtaIBmnr8S").toString()
19 | - 经过测试,该参数为md5加密
20 | - 在原密码的后边拼接了 `TuD00Iqz4ge7gzIe2rmjSAFFKtaIBmnr8S`,然后在进行md5加密
21 |
22 | '''
23 |
24 | import requests
25 |
26 | from utils import *
27 |
28 | headers = {
29 | 'Accept': '*/*',
30 | 'Accept-Language': 'zh-CN,zh;q=0.9',
31 | 'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/111.0.0.0 Safari/537.36',
32 | 'X-Requested-With': 'XMLHttpRequest',
33 | }
34 | cookies = {
35 | # 经过测试,请求头中的cookies必须带上,并且里边的session不可少,值可为None
36 | 'SESSION': None,
37 | }
38 |
39 |
40 | def get_image_msg():
41 | response = requests.get('https://www.hfax.com/pc-api/common/imageCode/login', headers=headers, cookies=cookies)
42 | results = response.json()
43 | data = results['data']
44 | img_base64 = data['base64Str']
45 | img_token = data['token']
46 | return img_base64, img_token
47 |
48 |
49 | def verify_captcha(base64str):
50 | '''
51 | 根据接收的base64图片,识别结果并返回
52 | :param base64str: 原始的图片base64信息,data:image/png;base64,/9j/4AA
53 | :return:
54 | '''
55 | # 把 data:image/png;base64,的图片前缀信息删掉,这不属于图片内的信息
56 | image_base64 = str(base64str).split('base64,')[-1]
57 | res_code = ocr.classification(image_base64)
58 | return res_code
59 |
60 |
61 | def login(user_name, pwd):
62 | base64str, token = get_image_msg()
63 | img_code = verify_captcha(base64str)
64 | logger.info(f'验证码识别结果: {img_code}')
65 | encrypt_pwd = Utils(origin_md5_str=f'{pwd}TuD00Iqz4ge7gzIe2rmjSAFFKtaIBmnr8S').encrypt_md5()
66 | logger.info(f'加密之后的密码: {encrypt_pwd}')
67 | json_data = {
68 | 'username': user_name,
69 | 'password': encrypt_pwd,
70 | 'imgCode': img_code,
71 | 'imgToken': token,
72 | }
73 | response = requests.post('https://www.hfax.com/pc-api/user/login', headers=headers, json=json_data, cookies=cookies)
74 | return response.json()
75 |
76 |
77 | def main():
78 | res = login('12345768090', '123456')
79 | # 因为我使用的是错误的账号和密码,故以下代码肯定能取到值
80 | code = res['errCode']
81 | msg = res['errMsg']
82 | logger.info(f'\nerror code: {code}\nerror msg: {msg}')
83 |
84 |
85 | if __name__ == '__main__':
86 | main()
87 |
--------------------------------------------------------------------------------
/hsddcx/__init__.py:
--------------------------------------------------------------------------------
1 | # _*_ coding: utf-8 _*_
2 | # @Date: 5:51 下午
3 | # @File: __init__.py.py
4 | # @Author: liyf
5 |
--------------------------------------------------------------------------------
/hsddcx/demo.py:
--------------------------------------------------------------------------------
1 | # _*_ coding: utf-8 _*_
2 | # @Date: 6:25 下午
3 | # @File: demo.py
4 | # @Author: liyf
5 |
6 | import requests
7 |
8 | from utils import *
9 |
10 | ctx = Utils(js_file_name='demo.js').read_js_file()
11 |
12 |
13 | def get_decrypt(page, encrypt_data):
14 | if page:
15 | return ctx.call('get_encrypt_params', page)
16 | return ctx.call('get_decrypt_data', encrypt_data)
17 |
18 |
19 | def get_encrypt_results(page):
20 | headers = {
21 | 'Accept': 'application/json, text/plain, */*',
22 | 'Accept-Language': 'zh-CN,zh;q=0.9',
23 | 'Ali-Version': '7.6.15',
24 | 'Content-Type': 'application/json; charset=UTF-8',
25 | 'Origin': 'https://hsddcx.wsjkw.zj.gov.cn',
26 | 'Pragma': 'no-cache',
27 | 'Referer': 'https://hsddcx.wsjkw.zj.gov.cn/webapp/app-mobile/epidMap',
28 | 'Sec-Fetch-Dest': 'empty',
29 | 'Sec-Fetch-Mode': 'cors',
30 | 'Sec-Fetch-Site': 'same-origin',
31 | 'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/105.0.0.0 Safari/537.36',
32 | 'channel': 'H5',
33 | 'sec-ch-ua': '"Google Chrome";v="105", "Not)A;Brand";v="8", "Chromium";v="105"',
34 | 'sec-ch-ua-mobile': '?0',
35 | 'sec-ch-ua-platform': '"macOS"',
36 | 'x-resp-encrypt': '1',
37 | }
38 | data = get_decrypt(page, encrypt_data=None)
39 | logger.info(f'第 {page} 页加密参数: {data}')
40 | response = requests.post('https://hsddcx.wsjkw.zj.gov.cn/client-api/search/getNucleicAcidOrgList', headers=headers,
41 | data=data)
42 | return response.text
43 |
44 |
45 | def parse(encrypt_data):
46 | results = get_decrypt(page=None, encrypt_data=encrypt_data)
47 | t_res = results['result']['t']
48 | data_list = t_res['data']
49 | for data in data_list:
50 | name = data['orgName']
51 | address = data['address']
52 | level = data['levelName']
53 | phone = data['phone'] if data['phone'] else '未知'
54 | is_free = data['isFree']
55 | res_free = True if is_free == 1 else False
56 | work_time = data['workTime']
57 | status = data['serviceStatus']
58 | res = '畅通' if status == 2 else '休息'
59 | print(f'名称: {name}\n电话: {phone}\n地址: {address}\n级别: {level}\n是否免费: {res_free}\n工作时间: {work_time}\n当前状态: {res}')
60 | print('===' * 25)
61 |
62 | # 下一页逻辑,循环入口
63 | is_next_page = t_res['hasNextPage']
64 | cur_page = t_res['pageNum']
65 | if is_next_page:
66 | next_page = t_res['nextPage']
67 | logger.info(f'有下一页, 当前页码: {cur_page}, 下一页: {next_page}')
68 | encrypt_data = get_encrypt_results(next_page)
69 | parse(encrypt_data)
70 | else:
71 | logger.info(f'没有下一页了,最后一页: {cur_page}')
72 | return
73 |
74 |
75 | if __name__ == '__main__':
76 | # 脚本启动入口
77 | encrypt_data = get_encrypt_results(1)
78 | parse(encrypt_data)
79 |
--------------------------------------------------------------------------------
/images/chrome_version.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/liyf-code/reverse_practice/e7e984ab8926770c4c193f4e717bcc02cfe1cf44/images/chrome_version.png
--------------------------------------------------------------------------------
/images/chromedriver_version.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/liyf-code/reverse_practice/e7e984ab8926770c4c193f4e717bcc02cfe1cf44/images/chromedriver_version.png
--------------------------------------------------------------------------------
/images/fix_origin_chrome.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/liyf-code/reverse_practice/e7e984ab8926770c4c193f4e717bcc02cfe1cf44/images/fix_origin_chrome.png
--------------------------------------------------------------------------------
/images/origin_chrome.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/liyf-code/reverse_practice/e7e984ab8926770c4c193f4e717bcc02cfe1cf44/images/origin_chrome.png
--------------------------------------------------------------------------------
/images/response_type.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/liyf-code/reverse_practice/e7e984ab8926770c4c193f4e717bcc02cfe1cf44/images/response_type.png
--------------------------------------------------------------------------------
/images/setting.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/liyf-code/reverse_practice/e7e984ab8926770c4c193f4e717bcc02cfe1cf44/images/setting.png
--------------------------------------------------------------------------------
/images/setting_button.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/liyf-code/reverse_practice/e7e984ab8926770c4c193f4e717bcc02cfe1cf44/images/setting_button.png
--------------------------------------------------------------------------------
/iyunzhi/__init__.py:
--------------------------------------------------------------------------------
1 | # _*_ coding: utf-8 _*_
2 | # @Date: 1:52 下午
3 | # @File: __init__.py.py
4 | # @Author: liyf
5 |
--------------------------------------------------------------------------------
/iyunzhi/demo.py:
--------------------------------------------------------------------------------
1 | # _*_ coding: utf-8 _*_
2 | # @Date: 1:47 下午
3 | # @File: demo.py
4 | # @Author: liyf
5 | import requests
6 | import json
7 |
8 | import execjs
9 |
10 | from loguru import logger
11 |
12 | headers = {
13 | "authority": "lark-acl.alibaba.com",
14 | "accept": "application/json, text/plain, */*",
15 | "accept-language": "zh-CN,zh;q=0.9",
16 | "cache-control": "no-cache",
17 | "content-type": "application/json;charset=UTF-8",
18 | "origin": "https://www.iyunzhi.com",
19 | "pragma": "no-cache",
20 | "referer": "https://www.iyunzhi.com/",
21 | "user-agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/116.0.0.0 Safari/537.36"
22 | }
23 |
24 | f = open('demo.js')
25 | js_str = f.read()
26 | ctx = execjs.compile(''.join(js_str))
27 |
28 |
29 | def get_login_res(password):
30 | url = "https://lark-acl.alibaba.com/idp/loginAccountAndPwd"
31 | params = {
32 | "access_token": ""
33 | }
34 | enc_pwd = ctx.call('get_encrypted_pwd', password)
35 | logger.info(f'\n加密前密码: {password}\n加密后密码: {enc_pwd}')
36 | data = {
37 | "loginId": "19929939949",
38 | "password": enc_pwd
39 | }
40 | data = json.dumps(data, separators=(',', ':'))
41 | response = requests.post(url, headers=headers, params=params, data=data)
42 | return response.json()
43 |
44 |
45 | def main():
46 | pwd = '123456'
47 | login_res = get_login_res(pwd)
48 | logger.info(login_res)
49 |
50 |
51 | if __name__ == '__main__':
52 | main()
53 |
54 |
--------------------------------------------------------------------------------
/jzsc/__init__.py:
--------------------------------------------------------------------------------
1 | # _*_ coding: utf-8 _*_
2 | # @Date: 3:11 下午
3 | # @File: __init__.py.py
4 | # @Author: liyf
5 |
--------------------------------------------------------------------------------
/jzsc/demo.js:
--------------------------------------------------------------------------------
1 | var CryptoJS = require('crypto-js')
2 |
3 | var f = CryptoJS.enc.Utf8.parse("jo8j9wGw%6HbxfFn")
4 | , m = CryptoJS.enc.Utf8.parse("0123456789ABCDEF");
5 |
6 | function get_encrypt_data(t) {
7 | var e = CryptoJS.enc.Hex.parse(t)
8 | , n = CryptoJS.enc.Base64.stringify(e)
9 | , a = CryptoJS.AES.decrypt(n, f, {
10 | iv: m,
11 | mode: CryptoJS.mode.CBC,
12 | padding: CryptoJS.pad.Pkcs7
13 | })
14 | , r = a.toString(CryptoJS.enc.Utf8);
15 | return r.toString()
16 | }
17 |
--------------------------------------------------------------------------------
/jzsc/demo.py:
--------------------------------------------------------------------------------
1 | # _*_ coding: utf-8 _*_
2 | # @Date: 3:15 下午
3 | # @File: demo.py
4 | # @Author: liyf
5 |
6 |
7 | """
8 | todo changelog version 20230314
9 | - 接口变更
10 | - 原接口: http://jzsc.mohurd.gov.cn/api/webApi/dataservice/query/comp/list
11 | - 变更后的接口: https://jzsc.mohurd.gov.cn/Api/webApi/dataservice/query/comp/list
12 |
13 | todo: http://jzsc.mohurd.gov.cn/data/company
14 | 由于是破解该网站返回数据加密的过程,所以可以根据关键字 `decrypt` 搜索进行定位关键代码。在`app.xxx.js`中可以定位到解密位置,打断点,点击下一页,断点生效。
15 | 把解密的函数copy下来,缺啥补啥。
16 | """
17 |
18 | import json
19 | import requests
20 |
21 | from utils import *
22 |
23 |
24 | def get_decrypt_data(encrypt_data):
25 | """
26 | 调用js,传入需要解密的数据,返回解密后的数据
27 | :param encrypt_data: 需要解密的数据
28 | :return: 解密后的数据
29 | """
30 | ctx = Utils(js_file_name='demo.js').read_js_file()
31 | decrypt_data = ctx.call('get_encrypt_data', encrypt_data)
32 | return json.loads(decrypt_data)
33 |
34 |
35 | def get_encrypt_data(page):
36 | """
37 | 获取数据
38 | :param page: 页码
39 | :return:
40 | """
41 | headers = {
42 | 'Accept': 'application/json, text/plain, */*',
43 | 'Referer': 'http://jzsc.mohurd.gov.cn/data/company',
44 | 'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/104.0.0.0 Safari/537.36',
45 | 'timeout': '30000',
46 | }
47 | params = {
48 | 'pg': str(page),
49 | 'pgsz': '15',
50 | 'total': '450',
51 | }
52 | response = requests.get('https://jzsc.mohurd.gov.cn/APi/webApi/dataservice/query/comp/list', params=params,
53 | headers=headers)
54 | return response.text
55 |
56 |
57 | def parse():
58 | for page in range(0, 30):
59 | logger.info(f'正在抓取第 {page + 1} 页数据...')
60 | encrypt_data = get_encrypt_data(page)
61 | decrypt_data = get_decrypt_data(encrypt_data)
62 | data_list = decrypt_data['data']['list']
63 | for data in data_list:
64 | org_code = data['QY_ORG_CODE']
65 | coname = data['QY_NAME']
66 | try:
67 | faren = data['QY_FR_NAME']
68 | except KeyError:
69 | faren = None
70 | address = data['QY_REGION_NAME']
71 | print(f'统一社会信用代码: {org_code}\n企业名称: {coname}\n企业法定代表人: {faren}\n企业注册属地: {address}')
72 | print('===' * 20)
73 |
74 |
75 | if __name__ == '__main__':
76 | parse()
77 |
--------------------------------------------------------------------------------
/kanzhun/__init__.py:
--------------------------------------------------------------------------------
1 | # _*_ coding: utf-8 _*_
2 | # @Date: 2:09 下午
3 | # @File: __init__.py.py
4 | # @Author: liyf
5 |
--------------------------------------------------------------------------------
/kanzhun/demo.py:
--------------------------------------------------------------------------------
1 | # _*_ coding: utf-8 _*_
2 | # @Date: 2:09 下午
3 | # @File: demo.py
4 | # @Author: liyf
5 |
6 | """
7 | 典型的 webpack 案例
8 | """
9 | import requests
10 |
11 | from utils import *
12 |
13 | ctx = Utils(js_file_name='demo.js').read_js_file()
14 |
15 |
16 | def get_decrypt(company_id, page, encrypt_data, req_params):
17 | if not encrypt_data: # 破解加密参数
18 | results = ctx.call('get_params_b_kiv', company_id, page)
19 | else: # 对返回的加密数据进行解密
20 | results = ctx.call('get_decrypt_data', encrypt_data, req_params)
21 | return results
22 |
23 |
24 | def get_encrypt_data(company_id, page):
25 | headers = {
26 | 'authority': 'www.kanzhun.com',
27 | 'accept': 'application/json, text/plain, */*',
28 | 'accept-language': 'zh-CN,zh;q=0.9',
29 | 'content-type': 'application/x-www-form-urlencoded;charset=utf-8',
30 | 'user-agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/105.0.0.0 Safari/537.36',
31 | 'x-requested-with': 'XMLHttpRequest',
32 | }
33 | req_params = get_decrypt(company_id, page, encrypt_data=None, req_params=None)
34 | logger.info(f'加密后的参数: {req_params}')
35 | response = requests.get('https://www.kanzhun.com/api_to/com_salary_v2/list.json', params=req_params,
36 | headers=headers)
37 | return req_params, response.text
38 |
39 |
40 | def parse():
41 | company_id = '1HV52g~~' # 华为
42 | for page in range(1, 10):
43 | req_params, encrypt_data = get_encrypt_data(company_id, page)
44 | decrypt_data = get_decrypt(None, None, encrypt_data, req_params)
45 | salary_list = decrypt_data['resdata']['salarys']
46 | for salary in salary_list:
47 | job_name = salary['jobTitle']
48 | avgSalary = salary['avgSalary']
49 | lowestSalary = salary['lowestSalary']
50 | highestSalary = salary['highestSalary']
51 | percentage = salary['percentage']
52 | staffCount = salary['staffCount']
53 | salaryContrast = salary['salaryContrast']
54 | tag = '增加' if salaryContrast == 1 else '减少'
55 | updateTime = salary['updateTime']
56 | print(
57 | f'职位名称: {job_name}\n数据来自 {staffCount} 名用户的贡献\n月均值: {avgSalary}\n较同行: {tag}{percentage}%\n同行最低工资: {lowestSalary}\n同行最高工资: {highestSalary}\n职位更新日期: {updateTime}')
58 | print('===' * 10)
59 |
60 |
61 | if __name__ == '__main__':
62 | parse()
63 |
--------------------------------------------------------------------------------
/landchina/__init__.py:
--------------------------------------------------------------------------------
1 | # _*_ coding: utf-8 _*_
2 | # @Date: 5:33 下午
3 | # @File: __init__.py.py
4 | # @Author: liyf
5 |
--------------------------------------------------------------------------------
/landchina/demo.py:
--------------------------------------------------------------------------------
1 | # _*_ coding: utf-8 _*_
2 | # @Date: 5:49 下午
3 | # @File: demo.py
4 | # @Author: liyf
5 |
6 | '''
7 | 网址:https://www.landchina.com/#/supplyPlan
8 | 破解参数:请求头 Hash
9 |
10 | 步骤:
11 | - 全局搜索 'hash=',可定位到以下代码
12 | var e = t.headers
13 | , n = (c.a.isKey("manageLoginToken") && (n = c.a.get("manageLoginToken"),
14 | !Object.prototype.hasOwnProperty.call(e, "manageLoginToken")) && n && (e.Authorization = "Bearer " + n),
15 | i("lPiR"))
16 | , a = t.url.split("/");
17 | return e.Hash = n(navigator.userAgent + (new Date).getDate() + a[a.length - 1])
18 |
19 | - hash参数是由n函数生成,其中接收的参数为
20 | useragent + 【今天】的日期 + url以 / 分割后最后一个元素
21 | - n 是由 i("lPiR") 生成的
22 |
23 | 显然是webpack,接下来就是常规的扣代码
24 | - 生成器是 i
25 | - 总共只需要扣取三个模块 lPiR Ib8C yLpj
26 |
27 | 接下来就可以正常生成hash参数了
28 |
29 | 经过测试,不携带该参数也可以请求到数据
30 |
31 | 该站点纯属练习webpack
32 |
33 | '''
34 |
35 | import json
36 | import execjs
37 | import requests
38 |
39 | from loguru import logger
40 |
41 | f = open('demo.js', 'r', encoding='utf8')
42 | js_str = f.read()
43 | ctx = execjs.compile(''.join(js_str))
44 |
45 | headers = {
46 | "Accept": "application/json, text/plain, */*",
47 | "Accept-Language": "zh-CN,zh;q=0.9",
48 | "Content-Type": "application/json",
49 | "User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/118.0.0.0 Safari/537.36",
50 | }
51 |
52 |
53 | def get_results(page):
54 | url = "https://api.landchina.com/tGyjh/plan/list"
55 | data = {
56 | "pageNum": page,
57 | "pageSize": 10,
58 | "startDate": "",
59 | "endDate": ""
60 | }
61 | hash = ctx.call('get_headers_hash', headers['User-Agent'])
62 | headers['Hash'] = hash
63 | logger.info(hash)
64 | data = json.dumps(data, separators=(',', ':'))
65 | response = requests.post(url, headers=headers, data=data)
66 | return response.json()
67 |
68 |
69 | def parse():
70 | for page in range(1, 11):
71 | results = get_results(page)
72 | data_list = results['data']['list']
73 | for data in data_list:
74 | xzq = data['xzqFullName']
75 | title = data['biaoti']
76 | update_date = data['fbSj']
77 | print(f'行政区: {xzq}\n公告标题: {title}\n发布日期: {update_date}')
78 | print('---' * 20)
79 | print('***' * 30)
80 |
81 |
82 | if __name__ == '__main__':
83 | parse()
84 |
--------------------------------------------------------------------------------
/liepin/__init__.py:
--------------------------------------------------------------------------------
1 | # _*_ coding: utf-8 _*_
2 | # @Date: 4:33 下午
3 | # @File: __init__.py.py
4 | # @Author: liyf
5 |
--------------------------------------------------------------------------------
/liepin/demo.js:
--------------------------------------------------------------------------------
1 | /*
2 | - 控制台全局搜索 `X-Fscp-Trace-Id`,可以定位到在 `common.ee5c9e85.js` 文件中,有该参数的赋值,代码如下:
3 | ```javascript
4 | e.headers["X-Fscp-Trace-Id"] = w()
5 | ```
6 | - 在该处打上断点,点击下一页,断点生效
7 | - 进入 w 函数中,发现如下代码
8 | ```javascript
9 | var w = function(e, t, n) {
10 | var r = (e = e || {}).random || (e.rng || h)();
11 | if (r[6] = 15 & r[6] | 64,
12 | r[8] = 63 & r[8] | 128,
13 | t) {
14 | n = n || 0;
15 | for (var a = 0; a < 16; ++a)
16 | t[n + a] = r[a];
17 | return t
18 | }
19 | return x(r)
20 | }
21 | ```
22 | 最终返回的 `x(r)` 即最终的结果。
23 |
24 | - x 函数如下:
25 | ```javascript
26 | function x(e) {
27 | var t = arguments.length > 1 && void 0 !== arguments[1] ? arguments[1] : 0
28 | ,
29 | n = (g[e[t + 0]] + g[e[t + 1]] + g[e[t + 2]] + g[e[t + 3]] + "-" + g[e[t + 4]] + g[e[t + 5]] + "-" + g[e[t + 6]] + g[e[t + 7]] + "-" + g[e[t + 8]] + g[e[t + 9]] + "-" + g[e[t + 10]] + g[e[t + 11]] + g[e[t + 12]] + g[e[t + 13]] + g[e[t + 14]] + g[e[t + 15]]).toLowerCase();
30 | return n
31 | }
32 | ```
33 | - 缺啥补啥,需要注意的是 `new Uint8Array(16)`,参考博客 [js逆向 模拟window.Crypto.getRandomValues](https://blog.csdn.net/Little__Panda/article/details/113566803)
34 | */
35 |
36 | // js逆向 模拟window.Crypto.getRandomValues
37 | function randoms(min, max) {
38 | return Math.floor(Math.random() * (max - min + 1) + min)
39 | }
40 |
41 | function getRandomValues(buf) {
42 | var min = 0,
43 | max = 255;
44 | if (buf instanceof Uint16Array) {
45 | max = 65535;
46 | } else if (buf instanceof Uint32Array) {
47 | max = 4294967295;
48 | }
49 | for (var element in buf) {
50 | buf[element] = randoms(min, max);
51 | }
52 | return buf;
53 | }
54 |
55 | for (var g = [], b = 0; b < 256; ++b)
56 | g.push((b + 256).toString(16).substr(1));
57 |
58 | function m() {
59 | var p = new Uint8Array(16), r = [];
60 | for (getRandomValues(p), G = 0; G < p.length; ++G)
61 | r.push(p[G])
62 | return r
63 | }
64 |
65 | function x(e) {
66 | var t = arguments.length > 1 && void 0 !== arguments[1] ? arguments[1] : 0
67 | ,
68 | n = (g[e[t + 0]] + g[e[t + 1]] + g[e[t + 2]] + g[e[t + 3]] + "-" + g[e[t + 4]] + g[e[t + 5]] + "-" + g[e[t + 6]] + g[e[t + 7]] + "-" + g[e[t + 8]] + g[e[t + 9]] + "-" + g[e[t + 10]] + g[e[t + 11]] + g[e[t + 12]] + g[e[t + 13]] + g[e[t + 14]] + g[e[t + 15]]).toLowerCase();
69 | return n
70 | }
71 |
72 | function get_x_fscp_teace_id() {
73 | var r = m();
74 | return x(r)
75 | }
76 |
77 | console.log(get_x_fscp_teace_id())
78 |
--------------------------------------------------------------------------------
/liuyan/__init__.py:
--------------------------------------------------------------------------------
1 | # _*_ coding: utf-8 _*_
2 | # @Date: 6:27 下午
3 | # @File: __init__.py.py
4 | # @Author: liyf
5 |
--------------------------------------------------------------------------------
/liuyan/demo.py:
--------------------------------------------------------------------------------
1 | # _*_ coding: utf-8 _*_
2 | # @Date: 6:27 下午
3 | # @File: demo.py
4 | # @Author: liyf
5 |
6 | """
7 | 网站首页(http://liuyan.people.com.cn/messageSearch)
8 | 需要逆向的参数: 请求参数中的signature
9 | 步骤:
10 | - 全局搜索 `signature`,可在`app.xxx.js`文件中找到如下代码:
11 | ```
12 | h = function(e, t, c, s) {
13 | var a = e.indexOf("?");
14 | a > 0 && (e = e.substring(0, a));
15 | var i = e + JSON.stringify(t) + c;
16 | return s && (i += s),
17 | l()(i)
18 | }
19 | , d = function(e, t, c, s) {
20 | var a;
21 | a = c ? l()(c).substring(0, 16) : l()(s).substring(0, 16);
22 | var i = {
23 | appCode: s,
24 | token: c,
25 | signature: h(e, t, a, c),
26 | param: JSON.stringify(t)
27 | };
28 | ```
29 | - 通过分析该代码,可发现signature由h函数生成,且接收四个参数`e, t, a, c`
30 | - 而h函数最终返回 `l()(i)`
31 | - 其中i的值为: '/v2/threads/search{"position":0,"keywords":"","fid":null,"domainId":null,"typeId":null,"timeRange":null,"ansChecked":false,"stTime":null,"sortType":"0","page":10,"rows":10}a2eb17f65d6f4b3f'
32 | - 经过测试,最终signature的值就是对i进行md5加密得到的结果
33 | - 分析参数`i`的构成
34 | - 大致可分为三部分
35 | - para1: /v2/threads/search, 此为post请求所需要的url的后缀
36 | - para2: {"position":0,"keywords":"","fid":null,"domainId":null,"typeId":null,"timeRange":null,"ansChecked":false,"stTime":null,"sortType":"0","page":10,"rows":10}, 此为post请求,所携带的参数,其中page可变
37 | - para3: a2eb17f65d6f4b3f, 此为对 `appcode` 的值进行md5加密,并取前16位得到的值
38 | - 最终把这三部分进行拼接,得到最终的值,并进行md5加密,即可得到signature
39 | """
40 |
41 | import requests
42 | import time
43 |
44 | from utils import *
45 |
46 |
47 | def get_results(page):
48 | headers = {
49 | 'Accept': 'application/json, text/plain, */*',
50 | 'Accept-Language': 'zh-CN',
51 | 'Content-Type': 'application/json;charset=UTF-8',
52 | 'Origin': 'http://liuyan.people.com.cn',
53 | 'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/106.0.0.0 Safari/537.36',
54 | 'token': '',
55 | }
56 | app_code = 'PC42ce3bfa4980a9'
57 | # app_code的值可由http://liuyan.people.com.cn/messageSearch,在其源代码中通过正则规则 `window.SITE_CONFIG['appCode'] =(.*?)'`得到
58 | params = {
59 | 'sortType': '0',
60 | }
61 | json_data = {
62 | 'appCode': 'PC42ce3bfa4980a9',
63 | 'token': '',
64 | 'param': '{"position":0,"keywords":"","fid":null,"domainId":null,"typeId":null,"timeRange":null,"ansChecked":false,"stTime":null,"sortType":"0","page":%s,"rows":10}' % page,
65 | }
66 | para1 = '/v2/threads/search'
67 | para2 = json_data['param']
68 | para3 = Utils(origin_md5_str=app_code).encrypt_md5()[0:16]
69 | encrypt_str = para1 + para2 + para3
70 | signature = Utils(origin_md5_str=encrypt_str).encrypt_md5()
71 | json_data['signature'] = signature
72 | response = requests.post('http://liuyan.people.com.cn/v2/threads/search', params=params, headers=headers,
73 | json=json_data, verify=False)
74 | return response.json()
75 |
76 |
77 | def parse():
78 | for page in range(1, 100):
79 | results = get_results(page)
80 | data_list = results['data']['data']
81 | for data in data_list:
82 | title = data['subject']
83 | typeName = data['typeName']
84 | domainName = data['domainName']
85 | content = data['content']
86 | status = data['stateInfo']
87 | forumName = data['forumName']
88 | nickName = data['nickName']
89 | date = data['createDateline']
90 | # 时间戳转换为时间格式
91 | dateline = time.strftime("%Y-%m-%d %H:%M", time.localtime(date))
92 | print(
93 | f'标题: {title}\n类型: {typeName}\n区域: {domainName}\n状态: {status}\n留言对象: {forumName}\n留言用户: {nickName}\n留言日期: {dateline}\n留言内容: {content}')
94 | print('===' * 30)
95 |
96 |
97 | if __name__ == '__main__':
98 | parse()
99 |
--------------------------------------------------------------------------------
/maomaozu/__init__.py:
--------------------------------------------------------------------------------
1 | # _*_ coding: utf-8 _*_
2 | # @Date: 11:43 上午
3 | # @File: __init__.py.py
4 | # @Author: liyf
5 |
--------------------------------------------------------------------------------
/maomaozu/demo.js:
--------------------------------------------------------------------------------
1 | var CryptoJS = require('crypto-js');
2 | var k = '55b3b62613aef1a0';
3 |
4 | function aes_decrypt(e) {
5 | var a = k.split("").reverse().join("");
6 | return decrypt(a, e)
7 | }
8 |
9 | function aes_encrypt(e) {
10 | return encrypt(k, e)
11 | }
12 |
13 | function decrypt(e, a) {
14 | e = CryptoJS.enc.Utf8.parse(e);
15 | var l = CryptoJS.AES.decrypt(a, e, {
16 | mode: CryptoJS.mode.CBC,
17 | padding: CryptoJS.pad.Pkcs7,
18 | iv: e
19 | });
20 | return CryptoJS.enc.Utf8.stringify(l).toString()
21 | }
22 |
23 | function encrypt(e, a) {
24 | return e = CryptoJS.enc.Utf8.parse(e),
25 | a = CryptoJS.enc.Utf8.parse(a),
26 | CryptoJS.AES.encrypt(a, e, {
27 | mode: CryptoJS.mode.CBC,
28 | padding: CryptoJS.pad.Pkcs7,
29 | iv: e
30 | }).toString()
31 | }
32 |
33 | function get_encrypt_params(page) {
34 | var a = {
35 | "Type": 0,
36 | "page": page,
37 | "expire": (new Date).getTime()
38 | },
39 | data = aes_encrypt(JSON.stringify(a));
40 | return data
41 | }
42 |
43 | function get_decrypt_res(encrypt_data) {
44 | var decrypt_res = aes_decrypt(encrypt_data);
45 | return JSON.parse(decrypt_res)
46 | }
47 |
48 |
--------------------------------------------------------------------------------
/maomaozu/demo.py:
--------------------------------------------------------------------------------
1 | # _*_ coding: utf-8 _*_
2 | # @Date: 5:07 下午
3 | # @File: demo.py
4 | # @Author: liyf
5 |
6 | import time
7 | import requests
8 |
9 | from utils import *
10 |
11 | ctx = Utils(js_file_name='demo.js').read_js_file()
12 |
13 |
14 | def get_data(page, encrypt_data):
15 | if page:
16 | return ctx.call('get_encrypt_params', page)
17 | return ctx.call('get_decrypt_res', encrypt_data)
18 |
19 |
20 | def get_encrypt_res(page):
21 | headers = {
22 | 'Accept': '*/*',
23 | 'Accept-Language': 'zh-CN,zh;q=0.9',
24 | 'Cache-Control': 'no-cache',
25 | 'Content-Type': 'application/json; charset=UTF-8',
26 | 'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/111.0.0.0 Safari/537.36',
27 | }
28 | encrypt_para = get_data(page=page, encrypt_data=None)
29 | logger.info(f'第{page}页,加密参数: {encrypt_para}')
30 | response = requests.post('https://www.maomaozu.com/index/build.json', headers=headers, data=encrypt_para)
31 | return response.text
32 |
33 |
34 | def parse(page):
35 | encrypt_data = get_encrypt_res(page)
36 | decrypt_data = get_data(page=None, encrypt_data=encrypt_data)
37 | data_list = decrypt_data['list']
38 | for data in data_list:
39 | title = data['Name']
40 | address = data['Address']
41 | addr = '-'.join(address[0: 2])
42 | walk_time = address[-1]
43 | nearby_line = data['Line']
44 | line = ', '.join(nearby_line)
45 | update_str = data['UpdateTimeStr']
46 | update_ts = data['UpdateTime']
47 | update_time = time.strftime("%Y-%m-%d", time.localtime(update_ts))
48 | room_list = data['RoomList']
49 | area_list = [f'{room[0]} m²' for room in room_list]
50 | area = ' | '.join(area_list)
51 | price = data['Price']
52 | price_str = f'¥{price}/m² · 天'
53 | print(
54 | f'标题: {title}\n地址: {addr}, 步行 {walk_time} 分钟到\n附近地铁: {line}\n更新时间: {update_str}, {update_time}\n面积: {area}\n价格: {price_str}')
55 | print('===' * 30)
56 |
57 |
58 | if __name__ == '__main__':
59 | for page in range(1, 10):
60 | parse(page)
61 |
--------------------------------------------------------------------------------
/music163/__init__.py:
--------------------------------------------------------------------------------
1 | # _*_ coding: utf-8 _*_
2 | # @Date: 5:36 下午
3 | # @File: __init__.py.py
4 | # @Author: liyf
5 |
--------------------------------------------------------------------------------
/music_kuwo/__init__.py:
--------------------------------------------------------------------------------
1 | # _*_ coding: utf-8 _*_
2 | # @Date: 3:53 下午
3 | # @File: __init__.py.py
4 | # @Author: liyf
5 |
--------------------------------------------------------------------------------
/my_37/__init__.py:
--------------------------------------------------------------------------------
1 | # _*_ coding: utf-8 _*_
2 | # @Date: 3:49 下午
3 | # @File: __init__.py.py
4 | # @Author: liyf
5 |
--------------------------------------------------------------------------------
/my_37/demo.js:
--------------------------------------------------------------------------------
1 | /*
2 | * https://my.37.com/login.html?url=//my.37.com/
3 | * 全局搜索 `password=`,在sq.login2015.js中发现 `h.password = td(f)`
4 | * 此处即为加密位置
5 | * 下断,重新点击登录按钮,单步调试就可以进入td的函数内部
6 | * 代码全部复制下来即可
7 | */
8 |
9 | var ch = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
10 |
11 | function __rsa(str) {
12 | var out, i, len;
13 | var c1, c2, c3;
14 | len = str.length;
15 | i = 0;
16 | out = "";
17 | while (i < len) {
18 | c1 = str.charCodeAt(i++) & 0xff;
19 | if (i == len) {
20 | out += ch.charAt(c1 >> 2);
21 | out += ch.charAt((c1 & 0x3) << 4);
22 | out += "==";
23 | break
24 | }
25 | c2 = str.charCodeAt(i++);
26 | if (i == len) {
27 | out += ch.charAt(c1 >> 2);
28 | out += ch.charAt(((c1 & 0x3) << 4) | ((c2 & 0xF0) >> 4));
29 | out += ch.charAt((c2 & 0xF) << 2);
30 | out += "=";
31 | break
32 | }
33 | c3 = str.charCodeAt(i++);
34 | out += ch.charAt(c1 >> 2);
35 | out += ch.charAt(((c1 & 0x3) << 4) | ((c2 & 0xF0) >> 4));
36 | out += ch.charAt(((c2 & 0xF) << 2) | ((c3 & 0xC0) >> 6));
37 | out += ch.charAt(c3 & 0x3F)
38 | }
39 | return out
40 | }
41 |
42 | function td(a) {
43 | var maxPos = ch.length - 2
44 | , w = [];
45 | for (i = 0; i < 15; i++) {
46 | w.push(ch.charAt(Math.floor(Math.random() * maxPos)));
47 | if (i === 7) {
48 | w.push(a.substr(0, 3))
49 | }
50 | if (i === 12) {
51 | w.push(a.substr(3))
52 | }
53 | }
54 | return __rsa(w.join(""))
55 | }
56 |
57 | console.log(td('123456'))
58 |
--------------------------------------------------------------------------------
/mytokencap/__init__.py:
--------------------------------------------------------------------------------
1 | # _*_ coding: utf-8 _*_
2 | # @Date: 11:46 上午
3 | # @File: __init__.py.py
4 | # @Author: liyf
5 |
--------------------------------------------------------------------------------
/newrank/__init__.py:
--------------------------------------------------------------------------------
1 | # _*_ coding: utf-8 _*_
2 | # @Date: 4:08 下午
3 | # @File: __init__.py.py
4 | # @Author: liyf
5 |
--------------------------------------------------------------------------------
/newrank/demo.py:
--------------------------------------------------------------------------------
1 | # _*_ coding: utf-8 _*_
2 | # @Date: 4:13 下午
3 | # @File: demo.py
4 | # @Author: liyf
5 |
6 | import js2py
7 | import requests
8 |
9 | from utils import *
10 |
11 |
12 | def get_nonce():
13 | js_str = """
14 | function get_nonce() {
15 | for (var a = ["0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "a", "b", "c", "d", "e", "f"], b = 0; b < 500; b++)
16 | for (var c = "", d = 0; d < 9; d++) {
17 | var e = Math.floor(16 * Math.random());
18 | c += a[e]
19 | }
20 | return c
21 | }
22 | """
23 | context = js2py.EvalJs() # 实例化解析js对象
24 | context.execute(js_str) # js对象转python
25 | nonce = context.get_nonce() # 调用js中的get_nonce,没有传参
26 | return nonce
27 |
28 |
29 | def get_xyz(h):
30 | ctx = Utils(js_file_name='demo.js').read_js_file()
31 | return ctx.call('b', h)
32 |
33 |
34 | def get_results(page):
35 | headers = {
36 | 'accept': 'application/json, text/javascript, */*; q=0.01',
37 | 'accept-language': 'zh-CN,zh;q=0.9',
38 | 'content-type': 'application/x-www-form-urlencoded; charset=UTF-8',
39 | 'origin': 'https://www.newrank.cn',
40 | 'referer': 'https://www.newrank.cn/public/news.html',
41 | 'user-agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/103.0.0.0 Safari/537.36',
42 | 'x-requested-with': 'XMLHttpRequest',
43 | }
44 | nonce = get_nonce()
45 | h = f'/xdnphb/index/getMedia?AppKey=joker&keyword=&pageNumber={page}&pageSize=10&nonce={nonce}'
46 | xyz = get_xyz(h)
47 | logger.info({'nonce': nonce, 'xyz': xyz})
48 | data = {
49 | 'keyword': '',
50 | 'pageNumber': str(page),
51 | 'pageSize': '10',
52 | 'nonce': nonce,
53 | 'xyz': xyz,
54 | } # 请求携带的data参数,缺一不可
55 | response = requests.post('https://www.newrank.cn/xdnphb/index/getMedia', headers=headers, data=data)
56 | return response.json()
57 |
58 |
59 | def parse():
60 | for page in range(1, 100):
61 | results = get_results(page)
62 | data_list = results['value']
63 | for data in data_list:
64 | title = data['title']
65 | desc = data['summary']
66 | label = data['label']
67 | author = data['author']
68 | public_time = data['public_time']
69 | url = data['url']
70 | print(f'标题: {title}\n描述: {desc}\n标签: {label}\n作者: {author}\n更新时间: {public_time}\n详情页地址: {url}')
71 | print('***' * 30)
72 |
73 |
74 | if __name__ == '__main__':
75 | # https://www.newrank.cn/public/news.html
76 | parse()
77 |
--------------------------------------------------------------------------------
/oauth/__init__.py:
--------------------------------------------------------------------------------
1 | # _*_ coding: utf-8 _*_
2 | # @Date: 2:58 下午
3 | # @File: __init__.py.py
4 | # @Author: liyf
5 |
--------------------------------------------------------------------------------
/oklink/__init__.py:
--------------------------------------------------------------------------------
1 | # _*_ coding: utf-8 _*_
2 | # @Date: 5:54 下午
3 | # @File: __init__.py
4 | # @Author: liyf
5 |
--------------------------------------------------------------------------------
/oklink/demo.js:
--------------------------------------------------------------------------------
1 | global.Buffer = global.Buffer || require('buffer').Buffer;
2 |
3 | if (typeof btoa === 'undefined') {
4 | global.btoa = function (str) {
5 | return new Buffer.from(str).toString('base64');
6 | };
7 | }
8 |
9 | if (typeof atob === 'undefined') {
10 | global.atob = function (b64Encoded) {
11 | return new Buffer.from(b64Encoded, 'base64').toString();
12 | };
13 | }
14 | var self = global
15 |
16 | window = {}
17 |
18 | function encryptTime(t){
19 | var e = (1 * t + 1111111111111).toString().split(""),
20 | r = parseInt(10 * Math.random(), 10),
21 | n = parseInt(10 * Math.random(), 10),
22 | o = parseInt(10 * Math.random(), 10);
23 | return e.concat([r, n, o]).join("")
24 | }
25 |
26 | function encryptApiKey(){
27 | //this.API_KEY = "a2c903cc-b31e-4547-9299-b6d07b7631ab"
28 | var t = "a2c903cc-b31e-4547-9299-b6d07b7631ab",
29 | e = t.split(""),
30 | r = e.splice(0, 8);
31 | return e.concat(r).join("")
32 | }
33 |
34 | function comb(e, t){
35 | /*
36 | * var r = "".concat(t, "|").concat(e) 时
37 | * 得到的结果为:Mjc2ODExNzExOTg2MTg4OXwtYjMxZS00NTQ3LTkyOTktYjZkMDdiNzYzMWFiYTJjOTAzY2M=
38 | * 经过base64解密后的结果为:2768117119861889|-b31e-4547-9299-b6d07b7631aba2c903cc
39 | *
40 | * 而浏览器最终生成的x-apiKey的值为:LWIzMWUtNDU0Ny05Mjk5LWI2ZDA3Yjc2MzFhYmEyYzkwM2NjfDI3NjgxMTM1Nzc3MzE4ODk=
41 | * 经过解密后的值为:-b31e-4547-9299-b6d07b7631aba2c903cc|2768113577731889
42 | *
43 | * 两次解密的结果不一样,区别就是 `|` 前后的顺序不一致
44 | *
45 | * 所以,把t和e的位置颠倒一下即可
46 | * 即:当 r = "".concat(e, "|").concat(t) 时,能得到正确的x-apiKey
47 | */
48 | var r = "".concat(e, "|").concat(t);
49 | return self.btoa(r)
50 | }
51 |
52 | function getApiKey(){
53 | var t = (new Date).getTime(),
54 | e = encryptApiKey();
55 | return t = encryptTime(t), comb(e, t)
56 | }
57 |
58 | var res = getApiKey();
59 | console.log(res)
--------------------------------------------------------------------------------
/oklink/demo.py:
--------------------------------------------------------------------------------
1 | # _*_ coding: utf-8 _*_
2 | # @Date: 5:56 下午
3 | # @File: demo.py
4 | # @Author: liyf
5 |
6 | import time
7 | import requests
8 |
9 | from utils import *
10 |
11 |
12 | def get_apikey():
13 | ctx = Utils(js_file_name='demo.js').read_js_file()
14 | return ctx.call('getApiKey')
15 |
16 |
17 | def get_json_data():
18 | url = f'https://www.oklink.com/api/explorer/v1/btc/transactionsNoRestrict?t={str(int(time.time()) * 1000)}&limit=20&offset=0'
19 | headers = {
20 | 'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/103.0.0.0 Safari/537.36',
21 | 'x-apiKey': get_apikey()
22 | }
23 | response = requests.get(url, headers=headers)
24 | return response.json()
25 |
26 |
27 | def parse():
28 | result = get_json_data()
29 | data_list = result['data']['hits']
30 | for data in data_list:
31 | print(
32 | f'交易哈希: {data["hash"]}\n所在区块: {data["blockHeight"]}\n输入: {data["inputsCount"]}\n输出: {data["outputsCount"]}\n数量(BTC): {data["realTransferValue"]}')
33 | print('***' * 30)
34 |
35 |
36 | if __name__ == '__main__':
37 | parse()
38 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "reverse_practice",
3 | "version": "1.0.0",
4 | "description": "***",
5 | "main": "index.js",
6 | "dependencies": {
7 | "crypto-js": "^4.1.1",
8 | "jsdom": "^20.0.0",
9 | "jsencrypt": "^3.2.1",
10 | "md5": "^2.3.0",
11 | "node-rsa": "^1.1.1",
12 | "zlib": "^1.0.5"
13 | },
14 | "devDependencies": {},
15 | "scripts": {
16 | "test": "echo \"Error: no test specified\" && exit 1"
17 | },
18 | "repository": {
19 | "type": "git",
20 | "url": "git+https://github.com/18839782321/reverse_practice.git"
21 | },
22 | "keywords": [],
23 | "author": "",
24 | "license": "ISC",
25 | "bugs": {
26 | "url": "https://github.com/18839782321/reverse_practice/issues"
27 | },
28 | "homepage": "https://github.com/18839782321/reverse_practice#readme"
29 | }
30 |
--------------------------------------------------------------------------------
/passport_fang/__init__.py:
--------------------------------------------------------------------------------
1 | # _*_ coding: utf-8 _*_
2 | # @Date: 6:03 下午
3 | # @File: __init__.py
4 | # @Author: liyf
5 |
--------------------------------------------------------------------------------
/passport_fang/demo.py:
--------------------------------------------------------------------------------
1 | # _*_ coding: utf-8 _*_
2 | # @Date: 6:03 下午
3 | # @File: demo.py
4 | # @Author: liyf
5 |
6 | import execjs
7 | import requests
8 | from loguru import logger
9 |
10 |
11 | def get_js_pwd(password):
12 | with open('demo.js', 'r') as f:
13 | js_str = f.readlines()
14 | ctx = execjs.compile(''.join(js_str))
15 | return ctx.call('get_password', password)
16 |
17 |
18 | def get_json_data(user, pwd):
19 | headers = {
20 | 'Accept': '*/*',
21 | 'Accept-Language': 'zh-CN,zh;q=0.9',
22 | 'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8',
23 | 'Referer': 'https://passport.fang.com/', # 这个请求头不能少,否则报错
24 | 'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/102.0.0.0 Safari/537.36',
25 | }
26 | data = {
27 | 'uid': user,
28 | 'pwd': get_js_pwd(pwd),
29 | 'Service': 'soufun-passport-web',
30 | 'AutoLogin': '1',
31 | }
32 |
33 | response = requests.post('https://passport.fang.com/login.api', headers=headers, data=data)
34 | return response.json()
35 |
36 |
37 | def main():
38 | user = 'username'
39 | pwd = 'password'
40 | results = get_json_data(user, pwd)
41 | print(results)
42 | msg = results['Message']
43 | tip = results['Tip']
44 | if msg == 'Success':
45 | logger.info(
46 | f'\n账号信息\nUserID: {results["UserID"]}\nUserName: {results["UserName"]}n\nCurrentIP: {results["Ip"]}')
47 | else:
48 | logger.info(f'Account Login Status: {msg}\t{tip}')
49 |
50 |
51 | if __name__ == '__main__':
52 | main()
53 |
--------------------------------------------------------------------------------
/pycharm激活方案汇总/README.MD:
--------------------------------------------------------------------------------
1 | - 方案一:无限试用(靠谱,支持所有版本)
2 | - 方案二:永久激活(支持2020 3.3以下所有版本)
3 | - 方案三:正版激活(支持所有版本,永久更新)
4 | - 方案四:JetBrains 产品正版激活码,每个激活码有效期一年,会定期更新
--------------------------------------------------------------------------------
/pycharm激活方案汇总/激活方案一/无限30天试用(靠谱)/ide-eval-resetter-2.1.13.zip:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/liyf-code/reverse_practice/e7e984ab8926770c4c193f4e717bcc02cfe1cf44/pycharm激活方案汇总/激活方案一/无限30天试用(靠谱)/ide-eval-resetter-2.1.13.zip
--------------------------------------------------------------------------------
/pycharm激活方案汇总/激活方案一/无限30天试用(靠谱)/操作步骤.docx:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/liyf-code/reverse_practice/e7e984ab8926770c4c193f4e717bcc02cfe1cf44/pycharm激活方案汇总/激活方案一/无限30天试用(靠谱)/操作步骤.docx
--------------------------------------------------------------------------------
/pycharm激活方案汇总/激活方案三/正版激活(支持所有版本)(永久更新)/支持所有版本-正版激活.txt:
--------------------------------------------------------------------------------
1 | 1、正版激活的条件是不能破解过软件
2 |
3 | 2、如果破解过软件就按照下面步骤还原一下
4 |
5 | 3、用试用身份进入软件
6 |
7 | 4、进入软件后点help edit vm options
8 |
9 | 5、删掉最下面的一行,jar包路径
10 |
11 | 6、重启软件
12 |
13 | 7、然后就可以用正版激活码激活了
14 |
15 | 8、正版激活码是永久更新的,到期后重新在网站提取,重新激活即可
16 |
17 | 9、正版激活码永久更新地址:idea.medeming.com/jets
--------------------------------------------------------------------------------
/pycharm激活方案汇总/激活方案二/永久破解(亲测2020 3.3以下版本通用)/BetterIntelliJ.zip:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/liyf-code/reverse_practice/e7e984ab8926770c4c193f4e717bcc02cfe1cf44/pycharm激活方案汇总/激活方案二/永久破解(亲测2020 3.3以下版本通用)/BetterIntelliJ.zip
--------------------------------------------------------------------------------
/pycharm激活方案汇总/激活方案二/永久破解(亲测2020 3.3以下版本通用)/reset_script/reset_jetbrains_eval_mac_linux.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 | # reset jetbrains ide evals
3 |
4 | OS_NAME=$(uname -s)
5 | JB_PRODUCTS="IntelliJIdea CLion PhpStorm GoLand PyCharm WebStorm Rider DataGrip RubyMine AppCode"
6 |
7 | if [ $OS_NAME == "Darwin" ]; then
8 | echo 'macOS:'
9 |
10 | for PRD in $JB_PRODUCTS; do
11 | rm -rf ~/Library/Preferences/${PRD}*/eval
12 | rm -rf ~/Library/Application\ Support/JetBrains/${PRD}*/eval
13 | done
14 | elif [ $OS_NAME == "Linux" ]; then
15 | echo 'Linux:'
16 |
17 | for PRD in $JB_PRODUCTS; do
18 | rm -rf ~/.${PRD}*/config/eval
19 | rm -rf ~/.config/${PRD}*/eval
20 | done
21 | else
22 | echo 'unsupport'
23 | exit
24 | fi
25 |
26 | echo 'done.'
27 |
--------------------------------------------------------------------------------
/pycharm激活方案汇总/激活方案二/永久破解(亲测2020 3.3以下版本通用)/reset_script/reset_jetbrains_eval_windows.vbs:
--------------------------------------------------------------------------------
1 | Set oShell = CreateObject("WScript.Shell")
2 | Set oFS = CreateObject("Scripting.FileSystemObject")
3 | sHomeFolder = oShell.ExpandEnvironmentStrings("%USERPROFILE%")
4 | sJBDataFolder = oShell.ExpandEnvironmentStrings("%APPDATA%") + "\JetBrains"
5 |
6 | Set re = New RegExp
7 | re.Global = True
8 | re.IgnoreCase = True
9 | re.Pattern = "\.?(IntelliJIdea|GoLand|CLion|PyCharm|DataGrip|RubyMine|AppCode|PhpStorm|WebStorm|Rider).*"
10 |
11 | Sub removeEval(ByVal file, ByVal sEvalPath)
12 | bMatch = re.Test(file.Name)
13 | If Not bMatch Then
14 | Exit Sub
15 | End If
16 |
17 | If oFS.FolderExists(sEvalPath) Then
18 | oFS.DeleteFolder sEvalPath, True
19 | End If
20 | End Sub
21 |
22 | If oFS.FolderExists(sHomeFolder) Then
23 | For Each oFile In oFS.GetFolder(sHomeFolder).SubFolders
24 | removeEval oFile, sHomeFolder + "\" + oFile.Name + "\config\eval"
25 | Next
26 | End If
27 |
28 | If oFS.FolderExists(sJBDataFolder) Then
29 | For Each oFile In oFS.GetFolder(sJBDataFolder).SubFolders
30 | removeEval oFile, sJBDataFolder + "\" + oFile.Name + "\eval"
31 | Next
32 | End If
33 |
34 | MsgBox "done"
--------------------------------------------------------------------------------
/pycharm激活方案汇总/激活方案二/永久破解(亲测2020 3.3以下版本通用)/操作说明.txt:
--------------------------------------------------------------------------------
1 | 1、不需要重新下载应用;
2 | 2、本激活方法适用于2020全系列版本;
3 | 3、如果软件目前已过试用期且无法输入激活码(即激活码框不能输入),请卸载软件重新安装后再激活;
4 | 4、使用前请仔细阅读方法内的【使用步骤】;
5 |
6 | 图文教程:https://mp.weixin.qq.com/s/g6SnJCEP86dntNlRDFyfZw
7 |
8 | 注意:破解补丁的位置不要更换,不要删除,否则激活之后还会失效
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/pycharm激活方案汇总/激活方案二/永久破解(亲测2020 3.3以下版本通用)/激活补丁key-.txt:
--------------------------------------------------------------------------------
1 | BISACXYELK-eyJsaWNlbnNlSWQiOiJCSVNBQ1hZRUxLIiwibGljZW5zZWVOYW1lIjoiQ2hpbmFOQiIsImFzc2lnbmVlTmFtZSI6IiIsImFzc2lnbmVlRW1haWwiOiIiLCJsaWNlbnNlUmVzdHJpY3Rpb24iOiIiLCJjaGVja0NvbmN1cnJlbnRVc2UiOmZhbHNlLCJwcm9kdWN0cyI6W3siY29kZSI6IklJIiwicGFpZFVwVG8iOiIyMDk5LTEyLTMxIiwiZXh0ZW5kZWQiOmZhbHNlfSx7ImNvZGUiOiJBQyIsInBhaWRVcFRvIjoiMjA5OS0xMi0zMSIsImV4dGVuZGVkIjpmYWxzZX0seyJjb2RlIjoiRFBOIiwicGFpZFVwVG8iOiIyMDk5LTEyLTMxIiwiZXh0ZW5kZWQiOnRydWV9LHsiY29kZSI6IlJTQyIsInBhaWRVcFRvIjoiMjA5OS0xMi0zMSIsImV4dGVuZGVkIjp0cnVlfSx7ImNvZGUiOiJQUyIsInBhaWRVcFRvIjoiMjA5OS0xMi0zMSIsImV4dGVuZGVkIjpmYWxzZX0seyJjb2RlIjoiUlNGIiwicGFpZFVwVG8iOiIyMDk5LTEyLTMxIiwiZXh0ZW5kZWQiOnRydWV9LHsiY29kZSI6IkdPIiwicGFpZFVwVG8iOiIyMDk5LTEyLTMxIiwiZXh0ZW5kZWQiOmZhbHNlfSx7ImNvZGUiOiJETSIsInBhaWRVcFRvIjoiMjA5OS0xMi0zMSIsImV4dGVuZGVkIjp0cnVlfSx7ImNvZGUiOiJDTCIsInBhaWRVcFRvIjoiMjA5OS0xMi0zMSIsImV4dGVuZGVkIjpmYWxzZX0seyJjb2RlIjoiUlMwIiwicGFpZFVwVG8iOiIyMDk5LTEyLTMxIiwiZXh0ZW5kZWQiOnRydWV9LHsiY29kZSI6IlJDIiwicGFpZFVwVG8iOiIyMDk5LTEyLTMxIiwiZXh0ZW5kZWQiOnRydWV9LHsiY29kZSI6IlJEIiwicGFpZFVwVG8iOiIyMDk5LTEyLTMxIiwiZXh0ZW5kZWQiOmZhbHNlfSx7ImNvZGUiOiJQQyIsInBhaWRVcFRvIjoiMjA5OS0xMi0zMSIsImV4dGVuZGVkIjpmYWxzZX0seyJjb2RlIjoiUlNWIiwicGFpZFVwVG8iOiIyMDk5LTEyLTMxIiwiZXh0ZW5kZWQiOnRydWV9LHsiY29kZSI6IlJTVSIsInBhaWRVcFRvIjoiMjA5OS0xMi0zMSIsImV4dGVuZGVkIjpmYWxzZX0seyJjb2RlIjoiUk0iLCJwYWlkVXBUbyI6IjIwOTktMTItMzEiLCJleHRlbmRlZCI6ZmFsc2V9LHsiY29kZSI6IldTIiwicGFpZFVwVG8iOiIyMDk5LTEyLTMxIiwiZXh0ZW5kZWQiOmZhbHNlfSx7ImNvZGUiOiJEQiIsInBhaWRVcFRvIjoiMjA5OS0xMi0zMSIsImV4dGVuZGVkIjpmYWxzZX0seyJjb2RlIjoiREMiLCJwYWlkVXBUbyI6IjIwOTktMTItMzEiLCJleHRlbmRlZCI6dHJ1ZX0seyJjb2RlIjoiUERCIiwicGFpZFVwVG8iOiIyMDk5LTEyLTMxIiwiZXh0ZW5kZWQiOnRydWV9LHsiY29kZSI6IlBXUyIsInBhaWRVcFRvIjoiMjA5OS0xMi0zMSIsImV4dGVuZGVkIjp0cnVlfSx7ImNvZGUiOiJQR08iLCJwYWlkVXBUbyI6IjIwOTktMTItMzEiLCJleHRlbmRlZCI6dHJ1ZX0seyJjb2RlIjoiUFBTIiwicGFpZFVwVG8iOiIyMDk5LTEyLTMxIiwiZXh0ZW5kZWQiOnRydWV9LHsiY29kZSI6IlBQQyIsInBhaWRVcFRvIjoiMjA5OS0xMi0zMSIsImV4dGVuZGVkIjp0cnVlfSx7ImNvZGUiOiJQUkIiLCJwYWlkVXBUbyI6IjIwOTktMTItMzEiLCJleHRlbmRlZCI6dHJ1ZX0seyJjb2RlIjoiUFNXIiwicGFpZFVwVG8iOiIyMDk5LTEyLTMxIiwiZXh0ZW5kZWQiOnRydWV9LHsiY29kZSI6IkRQIiwicGFpZFVwVG8iOiIyMDk5LTEyLTMxIiwiZXh0ZW5kZWQiOnRydWV9LHsiY29kZSI6IlJTIiwicGFpZFVwVG8iOiIyMDk5LTEyLTMxIiwiZXh0ZW5kZWQiOnRydWV9XSwibWV0YWRhdGEiOiIwMTIwMjAwNzI4RVBKQTAwODAwNiIsImhhc2giOiIxNTAyMTM1NC8wOi0xMjUxMTE0NzE3IiwiZ3JhY2VQZXJpb2REYXlzIjowLCJhdXRvUHJvbG9uZ2F0ZWQiOmZhbHNlLCJpc0F1dG9Qcm9sb25nYXRlZCI6ZmFsc2V9-H7NUmWcLyUNV1ctnlzc4P79j15qL56G0jeIYWPk/HViNdMg1MqPM7BR+aHR28yyuxK7Odb2bFDS8CeHNUtv7nT+4fUs85JJiqc3wc1psRpZq5R77apXLOmvmossWpbAw8T1hOGV9IPUm1f2O1+kLBxrOkdqPpv9+JanbdL7bvchAid2v4/dyQMBYJme/feZ0Dy2l7Jjpwno1TeblEAu0KZmarEo15or5RUNwtaGBL5+396TLhnw1qL904/uPnGftjxWYluLjabO/uRu/+5td8UA/39a1nvGU2nORNLk2IdRGIheiwIiuirAZrII9+OxB+p52i3TIv7ugtkw0E3Jpkw==-MIIDlzCCAn+gAwIBAgIBCTANBgkqhkiG9w0BAQsFADAYMRYwFAYDVQQDEw1KZXRQcm9maWxlIENBMCAXDTE4MTEwMTEyMjk0NloYDzIwOTkwODA5MDIyNjA3WjBoMQswCQYDVQQGEwJDWjEOMAwGA1UECBMFTnVzbGUxDzANBgNVBAcTBlByYWd1ZTEZMBcGA1UEChMQSmV0QnJhaW5zIHMuci5vLjEdMBsGA1UEAxMUcHJvZDN5LWZyb20tMjAxODExMDEwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCdXyaNhhRySH1a8d7c8SlLLFdNcQP8M3gNnq7gudcpHC651qxRrN7Qks8gdXlIkA4u3/lp9ylp95GiIIDo4ydYje8vlTWDq02bkyWW/G7gZ3hkbBhRUK/WnNyr2vwWoOgwx5CfTRMjKkPkfD/+jffkfNfdGmGcg9yfnqPP9/AizKzWTsXSeS+0jZ8Nw5tiYFW+lpceqlzwzKdTHug7Vs0QomUPccRtZB/TBBEuiC7YzrvLg4Amu0I48ETAcch/ztt00nx/oj/fu1DTnz4Iz4ilrNY+WVIEfDz/n3mz+PKI9kM+ZeB0jAuyLsiC7skGpIVGX/2HqmZTtJKBZCoveAiVAgMBAAGjgZkwgZYwSAYDVR0jBEEwP4AUo562SGdCEjZBvW3gubSgUouX8bOhHKQaMBgxFjAUBgNVBAMMDUpldFByb2ZpbGUgQ0GCCQDSbLGDsoN54TAJBgNVHRMEAjAAMBMGA1UdJQQMMAoGCCsGAQUFBwMBMAsGA1UdDwQEAwIFoDAdBgNVHQ4EFgQUYSkb2hkZx8swY0GRjtKAeIwaBNwwDQYJKoZIhvcNAQELBQADggEBAJZOakWgjfY359glviVffBQFxFS6C+4WjYDYzvzjWHUQoGBFKTHG4xUmTVW7y5GnPSvIlkaj49SzbD9KuiTc77GHyFCTwYMz+qITgbDg3/ao/x/be4DD/k/byWqW4Rb8OSYCshX/fNI4Xu+hxazh179taHX4NaH92ReLVyXNYsooq7mE5YhR9Qsiy35ORviQLrgFrMCGCxT9DWlFBuiPWIOqN544sL9OzFMz+bjqjCoAE/xfIJjI7H7SqGFNrx/8/IuF0hvZbO3bLIz+BOR1L2O+qT728wK6womnp2LLANTPbwu7nf39rpP182WW+xw2z9MKYwwMDwGR1iTYnD4/Sjw=
--------------------------------------------------------------------------------
/pycharm激活方案汇总/激活方案四/README.MD:
--------------------------------------------------------------------------------
1 | - 获取激活码[JetBrains 产品正版激活码](http://jets.idejihuo.com/)
--------------------------------------------------------------------------------
/python2encrypt/__init__.py:
--------------------------------------------------------------------------------
1 | # _*_ coding: utf-8 _*_
2 | # @Date: 3:30 下午
3 | # @File: __init__.py.py
4 | # @Author: liyf
5 | import base64
6 |
7 |
8 | def base64_encode(text):
9 | encode_data = base64.b64encode(text.encode())
10 | return encode_data
11 |
12 |
13 | def base64_decode(encode_data):
14 | decode_data = base64.b64decode(encode_data)
15 | return decode_data
16 |
17 |
18 | if __name__ == '__main__':
19 | text = 'I love Python!'
20 | encode_data = base64_encode(text)
21 | decode_data = base64_decode(encode_data)
22 | print('Base64 编码:', encode_data)
23 | print('Base64 解码:', decode_data)
--------------------------------------------------------------------------------
/python2encrypt/base64_encrypt.py:
--------------------------------------------------------------------------------
1 | # _*_ coding: utf-8 _*_
2 | # @Date: 3:40 下午
3 | # @File: base64_encrypt.py
4 | # @Author: liyf
5 | import base64
6 | from loguru import logger
7 |
8 |
9 | def base64_encode(encrypt_str):
10 | """
11 | 编码
12 | :param str: 待编码的内容
13 | :return: 编码后的结果,返回字节类型
14 | """
15 | # base64.b64encode(str) 报错:TypeError: a bytes-like object is required, not 'str'
16 | # 解决:str指定encode
17 | encode_res = base64.b64encode(encrypt_str.encode())
18 | return encode_res
19 |
20 |
21 | def base64_decode(encode_res):
22 | """
23 | 解码
24 | :param str: 待解码的内容
25 | :return: 解码后的结果
26 | """
27 | decode_res = base64.b64decode(encode_res)
28 | return decode_res
29 |
30 |
31 | if __name__ == '__main__':
32 | encrypt_str = '123456'
33 | logger.info(f'待编码内容: {encrypt_str}') # 待编码内容: 123456
34 | encode_res = base64_encode(encrypt_str)
35 | logger.info(f'Base64 编码结果: {encode_res}') # Base64 编码结果: b'dXRmOA=='
36 |
37 | decode_res = base64_decode(encode_res)
38 | logger.info(f'待解码内容: {encode_res}') # 待解码内容: b'dXRmOA=='
39 | logger.info(f'Base64 解码结果: {decode_res}') # Base64 解码结果: b'123456'
40 |
--------------------------------------------------------------------------------
/python2encrypt/md5_encrypt.py:
--------------------------------------------------------------------------------
1 | # _*_ coding: utf-8 _*_
2 | # @Date: 3:31 下午
3 | # @File: md5_encrypt.py
4 | # @Author: liyf
5 |
6 | import hashlib
7 | from loguru import logger
8 |
9 |
10 | def encrypt(str) -> str:
11 | """
12 | 实现md5加密
13 | :param str: 待加密字符串
14 | :return: 加密后的结果
15 | """
16 | md5 = hashlib.md5()
17 | # md5.update(str) 报错信息:TypeError: Unicode-objects must be encoded before hashing
18 | # 解决:必须指定encode
19 | md5.update(str.encode('utf8'))
20 | return md5.hexdigest()
21 |
22 |
23 | if __name__ == '__main__':
24 | encrypt_str = '123456'
25 | logger.info(f'md5加密前为: {encrypt_str}') # md5加密前为: 123456
26 | res = encrypt(encrypt_str)
27 | logger.info(f'md5加密后为: {res}') # md5加密后为: e10adc3949ba59abbe56e057f20f883e
28 |
--------------------------------------------------------------------------------
/python2encrypt/rsa_encrypt.py:
--------------------------------------------------------------------------------
1 | # _*_ coding: utf-8 _*_
2 | # @Date: 4:01 下午
3 | # @File: rsa_encrypt.py
4 | # @Author: liyf
5 |
6 | import rsa
7 |
8 |
9 | def encrypt(public_key, encrypt_str):
10 | """
11 | 加密
12 | :param public_key: 公钥
13 | :param encrypt_res: 待加密内容
14 | :return: 加密后结果
15 | """
16 | encrypt_res = rsa.encrypt(encrypt_str.encode('utf8'), public_key)
17 | return encrypt_res
18 |
19 |
20 | def decrypt(private_key, decrypt_res):
21 | """
22 | 解密
23 | :param private_key: 私钥
24 | :param decrypt_res: 待解密内容
25 | :return: 解密结果
26 | """
27 | decrypt_res = rsa.decrypt(decrypt_res, private_key).decode('utf8')
28 | return decrypt_res
29 |
30 |
31 | if __name__ == '__main__':
32 | # 生成256位的公钥和私钥
33 | public_key, private_key = rsa.newkeys(256)
34 | print(f'公钥: {public_key}')
35 | # 公钥: PublicKey(80329290882825905238094319536975561780227467875701686277278961529165919738557, 65537)
36 | print(f'私钥: {private_key}')
37 | # 私钥: PrivateKey(80329290882825905238094319536975561780227467875701686277278961529165919738557, 65537, 70670703944811224473393719296632436057098567468736946452812955406438254630273, 63972005125771969816027718000509430022301, 1255694435791011123719403715131447457)
38 |
39 | encrypt_str = '123456'
40 | print(f'待加密内容: {encrypt_str}') # 待加密内容: 123456
41 | encrypt_res = encrypt(public_key, encrypt_str)
42 | print(f'rsa加密结果: {encrypt_res}')
43 | # rsa加密结果: b'SQ\x1f\xac\x9f\x91\xf4K\xc3H)c9\xa6\xf2<\xd4^b\xc2X\x95Z1\xcd\xee\xc0\xb2u\xd6\x90\xaf'
44 | decrypt_res = decrypt(private_key, encrypt_res)
45 | print(f'待解密内容: {encrypt_res}')
46 | # 待解密内容: b'\x9e\xac\x82\x87;A@7\x01\x1co\x06>W\xc9gy\xe3\xdc[l2\x14\xf0!+u\x8f\xe7N\xc4?'
47 | print(f'解密结果: {decrypt_res}') # 解密结果: 123456
48 |
--------------------------------------------------------------------------------
/python2encrypt/sha_encrypt.py:
--------------------------------------------------------------------------------
1 | # _*_ coding: utf-8 _*_
2 | # @Date: 6:19 下午
3 | # @File: sha_encrypt.py
4 | # @Author: liyf
5 |
6 | import hashlib
7 | from loguru import logger
8 |
9 |
10 | def sha1(text):
11 | results = hashlib.sha1(text.encode('utf8')).hexdigest()
12 | return results
13 |
14 |
15 | def sha256(text):
16 | results = hashlib.sha256(text.encode('utf8')).hexdigest()
17 | return results
18 |
19 |
20 | def sha512(text):
21 | results = hashlib.sha512(text.encode('utf8')).hexdigest()
22 | return results
23 |
24 |
25 | if __name__ == '__main__':
26 | text = '123456'
27 | logger.info(f'加密前的字符串: {text}') # 加密前的字符串: 123456
28 | res_sha1 = sha1(text)
29 | logger.success(f'sha1\n\tsha1加密结果: {res_sha1}\n\t长度: {len(res_sha1)}')
30 | # sha1加密结果: 7c4a8d09ca3762af61e59520943dc26494f8941b
31 | # 长度: 40
32 | res_sha256 = sha256(text)
33 | logger.success(f'sha256\n\tsha256加密结果: {res_sha256}\n\t长度: {len(res_sha256)}')
34 | # sha256加密结果: 8d969eef6ecad3c29a3a629280e686cf0c3f5d5a86aff3ca12020c923adc6c92
35 | # 长度: 64
36 | res_sha512 = sha512(text)
37 | logger.success(f'sha512\n\tsha512加密结果: {res_sha512}\n\t长度: {len(res_sha512)}')
38 | # sha512加密结果: ba3253876aed6bc22d4a6ff53d8406c6ad864195ed144ab5c87621b6c233b548baeae6956df346ec8c17f5ea10f35ee3cbc514797ed7ddd3145464e2a0bab413
39 | # 长度: 128
40 |
--------------------------------------------------------------------------------
/qimingpian/__init__.py:
--------------------------------------------------------------------------------
1 | # _*_ coding: utf-8 _*_
2 | # @Date: 11:34 上午
3 | # @File: __init__.py.py
4 | # @Author: liyf
5 |
--------------------------------------------------------------------------------
/qimingpian/demo.py:
--------------------------------------------------------------------------------
1 | # _*_ coding: utf-8 _*_
2 | # @Date: 2:45 下午
3 | # @File: demo.py
4 | # @Author: liyf
5 |
6 | import requests
7 |
8 | from utils import *
9 |
10 |
11 | def get_encrypt_data():
12 | headers = {
13 | 'Accept': 'application/json, text/plain, */*',
14 | 'Accept-Language': 'zh-CN,zh;q=0.9',
15 | 'Connection': 'keep-alive',
16 | 'Origin': 'https://www.qimingpian.cn',
17 | 'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/103.0.0.0 Safari/537.36',
18 | 'sec-ch-ua': '".Not/A)Brand";v="99", "Google Chrome";v="103", "Chromium";v="103"',
19 | 'sec-ch-ua-mobile': '?0',
20 | 'sec-ch-ua-platform': '"macOS"',
21 | }
22 |
23 | data = {
24 | 'tag': '',
25 | 'unionid': '',
26 | }
27 |
28 | response = requests.post('https://vipapi.qimingpian.cn/DataList/productListVip', headers=headers, data=data).json()
29 | encrypt_data = response['encrypt_data']
30 | return encrypt_data
31 |
32 |
33 | def get_decrypt_data(encrypt_data):
34 | ctx = Utils(js_file_name='demo.js').read_js_file()
35 | results = ctx.call('s', encrypt_data)
36 | data_list = results['list']
37 | for data in data_list:
38 | investor_info = data['investor_info']
39 | investors = '、'.join([investor['investor'] for investor in investor_info])
40 | print(
41 | f'项目: {data["product"]}\n业务: {data["yewu"]}\n行业领域: {data["hangye1"]}\n地区: {data["province"]}\n投资轮次: {data["lunci"]}\n投资时间: {data["time"]}\n投资金额: {data["money"]}\n投资方: {investors}')
42 | print('***' * 40)
43 |
44 |
45 | if __name__ == '__main__':
46 | encrypt_data = get_encrypt_data()
47 | get_decrypt_data(encrypt_data)
48 |
--------------------------------------------------------------------------------
/remark.md:
--------------------------------------------------------------------------------
1 | ### 生成 `requirements.txt`
2 |
3 | ```
4 | pipreqs reverse_practice --encoding=utf8 --force
5 | ```
6 |
7 | ***
8 |
9 | ### 一些常见的乱码
10 |
11 | - 数据来源于爬虫交流群里边,一个大佬发的,如有侵权,请联系本人删除。
12 | 
13 |
14 | ***
15 |
16 | ### 关于chrome浏览器
17 |
18 | - 逆向定位关键参数时,source面板不显示行号。[解决办法](chrome.md)
19 |
20 | ***
21 |
22 | ### 关于 `pycharm激活码` 和 `chromedriver` 环境的配置
23 |
24 | - [chromedriver](chromedriver.md)
25 | - [pycharm激活码配置](pycharm激活方案汇总)
26 |
27 | ***
28 |
29 | ### 忽略某个目录或者文件
30 |
31 | - 由于 `node_modules` 太大,且默认是可以被上传的。所以我们需要创建一个 `.gitignore` 文件,目的是忽略上传某个文件或者文件夹。
32 | - 步骤如下:
33 | > 创建 `.gitignore` 文件
34 | ```text
35 | cd reverse_practice
36 | touch .gitignore
37 | ```
38 | > 创建好文件之后,在里边添加需要忽略的目录和文件即可
39 | - 忽略规则如下:
40 | ```text
41 | target // 忽略这个target目录
42 | angular.json // 忽略这个angular.json文件
43 | log/* // 忽略log下的所有文件
44 | css/*.css // 忽略css目录下的.css文件
45 | ```
46 |
47 | ***
48 |
--------------------------------------------------------------------------------
/requirements.txt:
--------------------------------------------------------------------------------
1 | loguru==0.5.3
2 | requests==2.25.1
3 | ddddocr==1.4.4
4 | PyExecJS==1.5.1
5 | Js2Py==0.71
6 | lxml==4.6.3
7 | rsa==4.7.2
8 | fontTools==4.39.3
9 |
--------------------------------------------------------------------------------
/souhu/__init__.py:
--------------------------------------------------------------------------------
1 | # _*_ coding: utf-8 _*_
2 | # @Date: 11:42 上午
3 | # @File: __init__.py.py
4 | # @Author: liyf
5 |
--------------------------------------------------------------------------------
/souhu/demo.js:
--------------------------------------------------------------------------------
1 | /*
2 | 搜狐网,新闻详情页(https://www.sohu.com/a/611710835_123753)
3 | 图片解密
4 | 请求url地址,返回响应数据,返回的图片地址是加密的,但是所在的img标签的属性为data-src
5 |
6 | 故全局搜索data-src关键字,定位到关键代码
7 | aes解密
8 | */
9 |
10 | window = global;
11 | var CryptoJS = require('crypto-js')
12 |
13 | function e(e, t) {
14 | return CryptoJS.AES.decrypt(e, CryptoJS.enc.Utf8.parse(t), {
15 | mode: CryptoJS.mode.ECB,
16 | padding: CryptoJS.pad.Pkcs7
17 | }).toString(CryptoJS.enc.Utf8)
18 | }
19 |
20 | var o = '9T8IQfyP7e1sMsEyWbYPvujwr47D8luFD15aBAmwHor+FqTy1mjFyNrrLjJO3WxqRwAgxG5o8r1Lcqis/SEI2lID2kTy3JccQzzIBZfATLE=',
21 | s = e(o, "www.souhu.com6666"),
22 | url = 'https:' + s;
23 | console.log('需要解密的data-src值:', o)
24 | console.log('解密后的值:', url)
25 |
--------------------------------------------------------------------------------
/stream_capital/__init__.py:
--------------------------------------------------------------------------------
1 | # _*_ coding: utf-8 _*_
2 | # @Date: 11:33 上午
3 | # @File: __init__.py.py
4 | # @Author: liyf
5 |
--------------------------------------------------------------------------------
/stream_capital/demo.js:
--------------------------------------------------------------------------------
1 | var CryptoJS = require('crypto-js');
2 | var nh = CryptoJS.enc.Utf8.parse("r4rt5A8L6ye6ts8y"),
3 | rh = CryptoJS.enc.Utf8.parse("fs0Hkjg8a23u8sE0"),
4 | oh = {
5 | Decrypt: function (e) {
6 | if (0 === e.length)
7 | return e;
8 | var t = CryptoJS.AES.decrypt(e, nh, {
9 | iv: rh,
10 | mode: CryptoJS.mode.CBC,
11 | padding: CryptoJS.pad.Pkcs7
12 | })
13 | , n = CryptoJS.enc.Utf8.stringify(t);
14 | return JSON.parse(n)
15 | },
16 | Encrypt: function (e) {
17 | var t = JSON.stringify(e);
18 | return CryptoJS.AES.encrypt(t, nh, {
19 | iv: rh,
20 | mode: CryptoJS.mode.CBC,
21 | padding: CryptoJS.pad.Pkcs7
22 | }).toString()
23 | }
24 | };
25 |
26 | function get_enc_para(page) {
27 | var params = {
28 | "type": 0,
29 | "name": null,
30 | "page": page
31 | };
32 | return oh.Encrypt(params)
33 | }
34 |
--------------------------------------------------------------------------------
/stream_capital/demo.py:
--------------------------------------------------------------------------------
1 | # _*_ coding: utf-8 _*_
2 | # @Date: 11:33 上午
3 | # @File: demo.py
4 | # @Author: liyf
5 |
6 | import execjs
7 | import requests
8 |
9 | from loguru import logger
10 |
11 | f = open('demo.js', 'r')
12 | js_str = f.read()
13 | ctx = execjs.compile(''.join(js_str))
14 |
15 | headers = {
16 | "authority": "api.yuanchuan.cn",
17 | "accept": "application/json, text/plain, */*",
18 | "accept-language": "zh-CN,zh;q=0.9",
19 | "user-agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/115.0.0.0 Safari/537.36"
20 | }
21 | url = "https://api.yuanchuan.cn/yc/webbloglist?apptype=9"
22 |
23 |
24 | def get_results(page):
25 | enc_para = ctx.call('get_enc_para', page)
26 | logger.info(f'第{page}页请求参数: {enc_para}')
27 | response = requests.post(url, headers=headers, data=enc_para)
28 | return response.json()
29 |
30 |
31 | def get_decrypt_data():
32 | for page in range(1, 11):
33 | results = get_results(page)
34 | decrypt_data = ctx.call('oh.Decrypt', results['data'])
35 | data_list = decrypt_data['list']
36 | for data in data_list:
37 | title = data['title']
38 | user_name = data['userName']
39 | content = data['content']
40 | post_date = data['ctime']
41 | theme = data['themeTitle']
42 | tags = '、'.join([tag['tagName'] for tag in data['tags']])
43 | print(f'标题: {title}\n内容: {content}\n作者: {user_name}\t更新日期: {post_date}\n标签: {tags}\t主题标题: {theme}')
44 | print('===' * 20)
45 | print('***' * 30)
46 | break
47 |
48 |
49 | def main():
50 | get_decrypt_data()
51 |
52 |
53 | if __name__ == '__main__':
54 | main()
55 |
--------------------------------------------------------------------------------
/tonghuashun/__init__.py:
--------------------------------------------------------------------------------
1 | # _*_ coding: utf-8 _*_
2 | # @Date: 10:21 上午
3 | # @File: __init__.py.py
4 | # @Author: liyf
5 |
--------------------------------------------------------------------------------
/tonghuashun/demo.py:
--------------------------------------------------------------------------------
1 | # _*_ coding: utf-8 _*_
2 | # @Date: 11:36 上午
3 | # @File: demo.py
4 | # @Author: liyf
5 |
6 | import requests
7 |
8 | from lxml import etree
9 |
10 | from utils import *
11 |
12 |
13 | headers = {
14 | "Accept": "text/html, */*; q=0.01",
15 | "Accept-Language": "zh-CN,zh;q=0.9",
16 | "Cache-Control": "no-cache",
17 | "Pragma": "no-cache",
18 | "Proxy-Connection": "keep-alive",
19 | "Referer": "http://q.10jqka.com.cn/",
20 | "User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/113.0.0.0 Safari/537.36",
21 | "X-Requested-With": "XMLHttpRequest",
22 | }
23 |
24 |
25 | def get_results(page):
26 | ctx = Utils(js_file_name='demo.js').read_js_file()
27 | hexin_v = ctx.call('get_cookie')
28 | headers['hexin-v'] = hexin_v
29 | headers['cookie'] = f'v={hexin_v};'
30 | logger.info(f'hexin-v: {hexin_v}')
31 | url = f"http://q.10jqka.com.cn/index/index/board/all/field/zdf/order/desc/page/{page}/ajax/1/"
32 | response = requests.get(url, headers=headers, verify=False)
33 | return response.text
34 |
35 |
36 | def parse():
37 | for page in range(1, 10):
38 | html = get_results(page)
39 | response = etree.HTML(html)
40 | tr_list = response.xpath('//tr')
41 | for tr in tr_list[1:]:
42 | item = {}
43 | item['code'] = tr.xpath('td[2]/a/text()')[0] # 股票代码
44 | item['name'] = tr.xpath('td[3]/a/text()')[0] # 股票名称
45 | item['cur_price'] = tr.xpath('td[4]/text()')[0] # 现价
46 | item['up_down_rate'] = tr.xpath('td[5]/text()')[0] # 涨跌幅
47 | item['up_down'] = tr.xpath('td[6]/text()')[0] # 涨跌
48 | item['up_speed'] = tr.xpath('td[7]/text()')[0] # 涨速
49 | item['change_hand'] = tr.xpath('td[8]/text()')[0] # 换手
50 | item['volume_rate'] = tr.xpath('td[9]/text()')[0] # 量比
51 | item['amplitude'] = tr.xpath('td[10]/text()')[0] # 振幅
52 | item['volume_business'] = tr.xpath('td[11]/text()')[0] # 成交额
53 | item['tradable_share'] = tr.xpath('td[12]/text()')[0] # 流通股
54 | item['tradable_market_value'] = tr.xpath('td[13]/text()')[0] # 流通市值
55 | item['earn_ratio'] = tr.xpath('td[14]/text()')[0] # 市盈率
56 | print(item)
57 | logger.info(f'第 {page} 页抓取结束~')
58 |
59 |
60 | if __name__ == '__main__':
61 | parse()
62 |
--------------------------------------------------------------------------------
/tousu_sign/__init__.py:
--------------------------------------------------------------------------------
1 | # _*_ coding: utf-8 _*_
2 | # @Date: 4:23 下午
3 | # @File: __init__.py.py
4 | # @Author: liyf
5 |
--------------------------------------------------------------------------------
/tousu_sign/demo.py:
--------------------------------------------------------------------------------
1 | # _*_ coding: utf-8 _*_
2 | # @Date: 4:55 下午
3 | # @File: demo.py
4 | # @Author: liyf
5 |
6 | import time
7 | import requests
8 |
9 | from utils import *
10 |
11 |
12 | def get_req_params(page):
13 | ctx = Utils(js_file_name='demo.js').read_js_file()
14 | return ctx.call('get_signature', page)
15 |
16 |
17 | def ts2time(ts):
18 | time_local = time.localtime(ts)
19 | dt = time.strftime("%Y-%m-%d", time_local)
20 | return dt
21 |
22 |
23 | def get_results(page):
24 | headers = {
25 | 'accept': 'text/javascript, application/javascript, application/ecmascript, application/x-ecmascript, */*; q=0.01',
26 | 'accept-language': 'zh-CN,zh;q=0.9',
27 | 'user-agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/107.0.0.0 Safari/537.36',
28 | 'x-requested-with': 'XMLHttpRequest',
29 | }
30 | req_params = get_req_params(page)
31 | params = {
32 | 'ts': req_params['ts'],
33 | 'rs': req_params['rs'],
34 | 'signature': req_params['signature'],
35 | 'couid': '6384912431',
36 | 'sid': '26873',
37 | 'page_size': '10',
38 | 'page': str(page),
39 | }
40 | response = requests.get('https://tousu.sina.com.cn/api/company/service_complaints', params=params, headers=headers)
41 | return response.json()
42 |
43 |
44 | def parse():
45 | for page in range(1, 20):
46 | results = get_results(page)
47 | data_list = results['result']['data']['complaints']
48 | for data in data_list:
49 | title = data['main']['title']
50 | cotitle = data['main']['cotitle']
51 | appeal = data['main']['appeal']
52 | dz = data['main']['upvote_amount']
53 | zf = data['main']['share_amount']
54 | pl = data['main']['comment_amount']
55 | summary = data['main']['summary']
56 | author = data['author']['title'] if 'title' in data['author'].keys() else '未知'
57 | ts = data['main']['timestamp']
58 | # dt = ts2time(int(ts))
59 | print(
60 | f'标题: {title}\n投诉人: {author} 在 {ts} 于黑猫投诉平台发起\n投诉对象: {cotitle}\n投诉要求: {appeal}\n投诉内容: {summary}\n点赞数({dz})评论数({pl})转发数({zf})')
61 | print('===' * 35)
62 |
63 |
64 | if __name__ == '__main__':
65 | parse()
66 |
--------------------------------------------------------------------------------
/utils.py:
--------------------------------------------------------------------------------
1 | # _*_ coding: utf-8 _*_
2 | # @Date: 4:37 下午
3 | # @File: utils.py
4 | # @Author: liyf
5 |
6 | import execjs
7 | import hashlib
8 |
9 | import ddddocr
10 |
11 | from loguru import logger
12 |
13 | ocr = ddddocr.DdddOcr(show_ad=False)
14 |
15 |
16 | class Utils:
17 | def __init__(self, js_file_name=None, origin_md5_str=None):
18 | '''
19 | 初始化参数
20 | :param js_file_name: 需要读取的js文件名称
21 | :param origin_md5_str: 需要进行md5加密的字符串
22 | '''
23 | self.js_file_name = js_file_name
24 | self.origin_md5_str = origin_md5_str
25 |
26 | def read_js_file(self):
27 | f = open(self.js_file_name, 'r', encoding='utf8')
28 | js_str = f.read()
29 | ctx = execjs.compile(''.join(js_str))
30 | return ctx
31 |
32 | def encrypt_md5(self) -> str:
33 | md5 = hashlib.md5()
34 | md5.update(self.origin_md5_str.encode('utf8'))
35 | return md5.hexdigest()
36 |
--------------------------------------------------------------------------------
/waitpay/__init__.py:
--------------------------------------------------------------------------------
1 | # _*_ coding: utf-8 _*_
2 | # @Date: 5:02 下午
3 | # @File: __init__.py.py
4 | # @Author: liyf
5 |
--------------------------------------------------------------------------------
/waitpay/demo.py:
--------------------------------------------------------------------------------
1 | # _*_ coding: utf-8 _*_
2 | # @Date: 5:02 下午
3 | # @File: demo.py
4 | # @Author: liyf
5 |
6 | '''
7 | 主页: https://static.waitwaitpay.com/web/sd_se/index.html#/
8 |
9 | 参考文章: https://mp.weixin.qq.com/s/EQnBJwD8Uo6dHZ6RRPGhFQ
10 |
11 | webpack加密
12 | 采用自吐的办法,快速补全解密所需的模块
13 |
14 | todo 步骤:
15 | - 找到分发器,添加以下代码(首先需要在头部定义`var map_ = {}, code_ = '';`)
16 | ```
17 | function n(r) {
18 | if (t[r])
19 | return t[r].exports;
20 | var o = t[r] = {
21 | i: r,
22 | l: !1,
23 | exports: {}
24 | };
25 | ==================================================
26 | // 自吐,只需要添加这几行代码即可,code_这个变量里面存的是导出的代码
27 | if (typeof (map_[r]) == "undefined") {
28 | map_[r] = 1;
29 | code_ = code_ + '"' + r + '":' + e[r] + ',';
30 | }
31 | ==================================================
32 | return e[r].call(o.exports, o, o.exports, n),
33 | o.l = !0,
34 | o.exports
35 | }
36 | ```
37 | - 找到所有的模块,全部copy至本地,使用自吐的办法,在本地输出_code即可
38 | - 优点
39 | - 速度快,省去了扣代码的步骤
40 | '''
41 | import requests
42 |
43 | from utils import *
44 |
45 |
46 | def get_decrypt_data(encrypt_data):
47 | # 传入加密数据,返回明文数据
48 | ctx = Utils(js_file_name='demo.js').read_js_file()
49 | return ctx.call('decrypt', encrypt_data)
50 |
51 |
52 | def get_encrypt_data(page):
53 | # 传入参数page,获取响应加密数据
54 | headers = {
55 | 'authority': 'api.waitwaitpay.com',
56 | 'accept': '*/*',
57 | 'accept-language': 'zh-CN,zh;q=0.9',
58 | 'cache-control': 'no-cache',
59 | 'origin': 'https://static.waitwaitpay.com',
60 | 'sec-ch-ua': '"Google Chrome";v="107", "Chromium";v="107", "Not=A?Brand";v="24"',
61 | 'sec-ch-ua-mobile': '?0',
62 | 'user-agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/107.0.0.0 Safari/537.36',
63 | }
64 | params = {
65 | 'latitude': '39.9349',
66 | 'longitude': '116.454',
67 | 'page': str(page),
68 | # 'request_id': '5e50f62c-6662-4213-acd3-ec50ad7b8862',
69 | 'type': 'all',
70 | 'with_vouchers': 'false',
71 | }
72 | response = requests.get('https://api.waitwaitpay.com/api/vendors/nearby', params=params, headers=headers)
73 | return response.text
74 |
75 |
76 | def parse():
77 | for page in range(1, 10):
78 | encrypt_data = get_encrypt_data(page)
79 | decrypt_data = get_decrypt_data(encrypt_data)
80 | data_list = decrypt_data['result']['list']
81 | for data in data_list:
82 | shop_name = data['name']
83 | brand = data['brand']
84 | phone = data['phone']
85 | city = data['city_name']
86 | cate = data['category_name']
87 | address = data['address']
88 | avg_price = data['avg_price']
89 | tag_list = data['recommand_vouchers']
90 | tag = ';'.join([tag['title'] for tag in tag_list])
91 | discount_rate = data['discount_rate']
92 | print(
93 | f'店铺名称: {shop_name}\n品牌: {brand}\n电话: {phone}\n类别: {cate}\n标签: {tag}\n城市及详细地址: {city};{address}\n人均{avg_price},折扣: {discount_rate}折')
94 | print('===' * 20)
95 |
96 |
97 | if __name__ == '__main__':
98 | parse()
99 |
--------------------------------------------------------------------------------
/webapi/__init__.py:
--------------------------------------------------------------------------------
1 | # _*_ coding: utf-8 _*_
2 | # @Date: 3:04 下午
3 | # @File: __init__.py.py
4 | # @Author: liyf
5 |
--------------------------------------------------------------------------------
/webapi/demo.js:
--------------------------------------------------------------------------------
1 | function get_mcode() {
2 | var e = Math.floor((new Date).getTime() / 1e3);
3 | var input = "" + e;
4 | var keyStr = "ABCDEFGHIJKLMNOP" + "QRSTUVWXYZabcdef" + "ghijklmnopqrstuv" + "wxyz0123456789+/" + "=";
5 | var output = "";
6 | var chr1, chr2, chr3 = "";
7 | var enc1, enc2, enc3, enc4 = "";
8 | var i = 0;
9 | do {
10 | chr1 = input.charCodeAt(i++);
11 | chr2 = input.charCodeAt(i++);
12 | chr3 = input.charCodeAt(i++);
13 | enc1 = chr1 >> 2;
14 | enc2 = ((chr1 & 3) << 4) | (chr2 >> 4);
15 | enc3 = ((chr2 & 15) << 2) | (chr3 >> 6);
16 | enc4 = chr3 & 63;
17 | if (isNaN(chr2)) {
18 | enc3 = enc4 = 64;
19 | } else if (isNaN(chr3)) {
20 | enc4 = 64;
21 | }
22 | output = output + keyStr.charAt(enc1) + keyStr.charAt(enc2)
23 | + keyStr.charAt(enc3) + keyStr.charAt(enc4);
24 | chr1 = chr2 = chr3 = "";
25 | enc1 = enc2 = enc3 = enc4 = "";
26 | } while (i < input.length);
27 | console.log(output)
28 | return output;
29 | }
30 | get_mcode()
31 |
--------------------------------------------------------------------------------
/webapi/demo.py:
--------------------------------------------------------------------------------
1 | # _*_ coding: utf-8 _*_
2 | # @Date: 3:19 下午
3 | # @File: demo.py
4 | # @Author: liyf
5 |
6 | import execjs
7 | import requests
8 |
9 | from utils import *
10 |
11 |
12 | def get_mcode():
13 | ctx = Utils(js_file_name='demo.js').read_js_file()
14 | return ctx.call('get_mcode')
15 |
16 |
17 | def get_results():
18 | """
19 | 请求头中 `Referer` 参数不能缺,否则报错:
20 | {"resultmsg":"未经授权的访问,code:005","resultcode":401}
21 | """
22 | headers = {
23 | 'Accept': 'application/json, text/javascript, */*; q=0.01',
24 | 'Accept-Language': 'zh-CN,zh;q=0.9',
25 | 'Referer': 'https://webapi.cninfo.com.cn/',
26 | 'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/103.0.0.0 Safari/537.36',
27 | 'X-Requested-With': 'XMLHttpRequest',
28 | 'mcode': get_mcode(),
29 | }
30 | response = requests.post('https://webapi.cninfo.com.cn/api/sysapi/p_sysapi1128', headers=headers)
31 | return response.json()
32 |
33 |
34 | def parse():
35 | records = get_results()['records']
36 | index = 0
37 | for record in records:
38 | index += 1
39 | print(
40 | f'序号: {index}\n证券代码: {record["SECCODE"]}\n资讯类型: {record["F003V"]}\n发布时间: {record["DECLAREDATE"]}\n资讯标题: {record["F001V"]}\n公告摘要: {record["F002V"]}')
41 | print('===' * 35)
42 |
43 |
44 | if __name__ == '__main__':
45 | # https://webapi.cninfo.com.cn/#/aiInfos
46 | parse()
47 |
--------------------------------------------------------------------------------
/weibotop/__init__.py:
--------------------------------------------------------------------------------
1 | # _*_ coding: utf-8 _*_
2 | # @Date: 5:39 下午
3 | # @File: __init__.py.py
4 | # @Author: liyf
5 |
--------------------------------------------------------------------------------
/weibotop/demo.js:
--------------------------------------------------------------------------------
1 | var CryptoJS = require('crypto-js');
2 |
3 | let s = CryptoJS.SHA1(CryptoJS.enc.Utf8.parse("tSdGtmwh49BcR1irt18mxG41dGsBuGKS"))
4 | , a = CryptoJS.enc.Hex.parse(s.toString(CryptoJS.enc.Hex).substr(0, 32));
5 |
6 | function l(t) {
7 | var e = t
8 | , i = a
9 | , o = CryptoJS.AES.encrypt(e, i, {
10 | mode: CryptoJS.mode.ECB,
11 | padding: CryptoJS.pad.Pkcs7
12 | });
13 | return CryptoJS.enc.Base64.stringify(o.ciphertext)
14 | }
15 |
16 | function h(t) {
17 | let e = (i = t = String(t),
18 | o = CryptoJS.enc.Base64.parse(i),
19 | r = a,
20 | CryptoJS.AES.decrypt({
21 | ciphertext: o
22 | }, r, {
23 | mode: CryptoJS.mode.ECB,
24 | padding: CryptoJS.pad.Pkcs7
25 | }).toString(CryptoJS.enc.Utf8));
26 | var i, o, r;
27 | return JSON.parse(e)
28 | }
29 |
--------------------------------------------------------------------------------
/weibotop/demo.py:
--------------------------------------------------------------------------------
1 | # _*_ coding: utf-8 _*_
2 | # @Date: 5:57 下午
3 | # @File: demo.py
4 | # @Author: liyf
5 |
6 | import execjs
7 | import requests
8 |
9 | from loguru import logger
10 |
11 | f = open('demo.js', 'r')
12 | js_str = f.read()
13 | ctx = execjs.compile(''.join(js_str))
14 |
15 | headers = {
16 | "authority": "api.weibotop.cn",
17 | "accept": "application/json, text/javascript, */*; q=0.01",
18 | "accept-language": "zh-CN,zh;q=0.9",
19 | "user-agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/115.0.0.0 Safari/537.36"
20 | }
21 |
22 |
23 | def get_timeid_dec_data(timeid, encrypt_data):
24 | if timeid:
25 | return ctx.call('l', timeid)
26 | return ctx.call('h', encrypt_data)
27 |
28 |
29 | def get_latest_date():
30 | '''
31 | 获取最新一次的热搜日期
32 | :return:
33 | '''
34 | url = "https://api.weibotop.cn/getlatest"
35 | response = requests.get(url, headers=headers)
36 | return response.json()
37 |
38 |
39 | def get_data(timeid):
40 | url = "https://api.weibotop.cn/currentitems"
41 | enc_timeid = get_timeid_dec_data(timeid, encrypt_data=None)
42 | logger.info(f'timeid: {enc_timeid}')
43 | params = {
44 | "timeid": enc_timeid
45 | }
46 | response = requests.get(url, headers=headers, params=params)
47 | return response.text
48 |
49 |
50 | def main():
51 | latest_res = get_latest_date()
52 | timeid = latest_res[0]
53 | latest_date = latest_res[1]
54 | logger.info(f'最近一次更新日期为: {latest_date}')
55 | encrypt_data = get_data(timeid)
56 | decrypt_data = get_timeid_dec_data(timeid=None, encrypt_data=encrypt_data)
57 | for data in decrypt_data:
58 | title = data[0]
59 | rank_list_date = data[1]
60 | last_rank_list = data[2]
61 | heat = data[3]
62 | print(f'热搜名称: {title}\n上榜时间: {rank_list_date}\n最后在榜: {last_rank_list}\n热度: {heat}')
63 | print('***' * 20)
64 |
65 |
66 | if __name__ == '__main__':
67 | main()
68 |
--------------------------------------------------------------------------------
/xhpfmapi/__init__.py:
--------------------------------------------------------------------------------
1 | # _*_ coding: utf-8 _*_
2 | # @Date: 4:48 下午
3 | # @File: __init__.py.py
4 | # @Author: liyf
5 |
--------------------------------------------------------------------------------
/xhpfmapi/demo.js:
--------------------------------------------------------------------------------
1 | var CryptoJS = require('crypto-js'),
2 | v = CryptoJS.enc.Utf8.parse(CryptoJS.MD5("Xinhuamm@2018").toString());
3 |
4 | function decrypt(t) {
5 | var data = CryptoJS.TripleDES.decrypt({
6 | ciphertext: CryptoJS.enc.Base64.parse(t.data)
7 | }, v, {
8 | mode: CryptoJS.mode.ECB,
9 | padding: CryptoJS.pad.Pkcs7
10 | });
11 | return data.toString(CryptoJS.enc.Utf8);
12 | }
13 |
14 | function get_encrypt_params(params) {
15 | var n = JSON.stringify(params),
16 | s = CryptoJS.TripleDES.encrypt(n, v, {
17 | mode: CryptoJS.mode.ECB,
18 | padding: CryptoJS.pad.Pkcs7
19 | });
20 | return CryptoJS.enc.Base64.stringify(s.ciphertext);
21 | }
22 |
--------------------------------------------------------------------------------
/xhpfmapi/demo.py:
--------------------------------------------------------------------------------
1 | # _*_ coding: utf-8 _*_
2 | # @Date: 5:06 下午
3 | # @File: demo.py
4 | # @Author: liyf
5 |
6 | '''
7 |
8 | 全局搜索关键字 'decrypt(' 即可定位到关键代码
9 |
10 | des加密
11 |
12 | 'Xinhuamm@2018' 进行md5加密得到的结果就是des的key
13 | '''
14 |
15 | import requests
16 | import json
17 | import datetime
18 |
19 | from utils import *
20 |
21 | headers = {
22 | "authority": "xhpfmapi.zhongguowangshi.com",
23 | "accept": "application/json, text/plain, */*",
24 | "content-type": "application/json;charset=UTF-8", # 必须携带该请求头
25 | "user-agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.0.0 Safari/537.36"
26 | }
27 |
28 | ctx = Utils(js_file_name='demo.js').read_js_file()
29 |
30 | url = "https://xhpfmapi.zhongguowangshi.com/v600/core/columnnewslist"
31 |
32 |
33 | def get_js_results(params, response_data):
34 | if params:
35 | results = ctx.call('get_encrypt_params', params)
36 | else:
37 | results = ctx.call('decrypt', response_data)
38 | return results
39 |
40 |
41 | def get_results(page):
42 | params = {"cid": "25295", "pn": page, "clientVer": "8.8.2", "clientLable": "h5", "source": 0, "userID": ""}
43 | param = get_js_results(params, response_data=None)
44 | logger.info(f'第 {page} 页参数: {param}')
45 | data = {
46 | "param": param
47 | }
48 | data = json.dumps(data, separators=(',', ':'))
49 | response = requests.post(url, headers=headers, data=data)
50 | encrypt_data = response.json()
51 | decrypt_data = get_js_results(params=None, response_data=encrypt_data)
52 | return json.loads(decrypt_data)
53 |
54 |
55 | def trans_ts(ts):
56 | timestamp = ts / 1000 # 将毫秒转换为秒
57 | dt = datetime.datetime.fromtimestamp(timestamp)
58 | return dt
59 |
60 |
61 | def main():
62 | for page in range(1, 10):
63 | results = get_results(page)
64 | news_list = results['newsList']
65 | for news in news_list:
66 | title = news['topic']
67 | comment_count = news['commentCount']
68 | detail_url = news['detailurl']
69 | ts = news['relaseDateTimeStamp']
70 | update_date = trans_ts(ts)
71 | print(f'标题: {title}\n评论数量: {comment_count}\n发布时间: {update_date}\n详情链接: {detail_url}')
72 | print('===' * 30)
73 |
74 |
75 | if __name__ == '__main__':
76 | main()
77 |
--------------------------------------------------------------------------------
/xiniu/__init__.py:
--------------------------------------------------------------------------------
1 | # _*_ coding: utf-8 _*_
2 | # @Date: 5:48 下午
3 | # @File: __init__.py.py
4 | # @Author: liyf
5 |
--------------------------------------------------------------------------------
/xiniu/demo.js:
--------------------------------------------------------------------------------
1 | var _keyStr = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/="
2 | , _p = "W5D80NFZHAYB8EUI2T649RT2MNRMVE2O";
3 |
4 | // c.c
5 | function e1(t) {
6 | if (null == t)
7 | return null;
8 | for (var e, n, r, o, i, a, c, u = "", s = 0; s < t.length;)
9 | o = (e = t.charCodeAt(s++)) >> 2,
10 | i = (3 & e) << 4 | (n = t.charCodeAt(s++)) >> 4,
11 | a = (15 & n) << 2 | (r = t.charCodeAt(s++)) >> 6,
12 | c = 63 & r,
13 | isNaN(n) ? a = c = 64 : isNaN(r) && (c = 64),
14 | u = u + _keyStr.charAt(o) + _keyStr.charAt(i) + _keyStr.charAt(a) + _keyStr.charAt(c);
15 | return u
16 | }
17 |
18 | // c.d
19 | function e2(t) {
20 | if (null == (t = _u_e(t)))
21 | return null;
22 | for (var e = "", n = 0; n < t.length; n++) {
23 | var r = _p.charCodeAt(n % _p.length);
24 | e += String.fromCharCode(t.charCodeAt(n) ^ r)
25 | }
26 | return e
27 | }
28 |
29 | function _u_e(t) {
30 | if (null == t)
31 | return null;
32 | t = t.replace(/\r\n/g, "\n");
33 | for (var e = "", n = 0; n < t.length; n++) {
34 | var r = t.charCodeAt(n);
35 | r < 128 ? e += String.fromCharCode(r) : r > 127 && r < 2048 ? (e += String.fromCharCode(r >> 6 | 192),
36 | e += String.fromCharCode(63 & r | 128)) : (e += String.fromCharCode(r >> 12 | 224),
37 | e += String.fromCharCode(r >> 6 & 63 | 128),
38 | e += String.fromCharCode(63 & r | 128))
39 | }
40 | return e
41 | }
42 |
43 | function get_payload(start) {
44 | var l = {
45 | payload: {
46 | limit: 20,
47 | sort: 1,
48 | start: start
49 | }
50 | }
51 | return e1(e2(JSON.stringify(l.payload)))
52 | }
53 |
54 | function d1(t) {
55 | var e, n, r, o, i, a, c = "", u = 0;
56 | for (t = t.replace(/[^A-Za-z0-9\+\/\=]/g, ""); u < t.length;)
57 | e = _keyStr.indexOf(t.charAt(u++)) << 2 | (o = _keyStr.indexOf(t.charAt(u++))) >> 4,
58 | n = (15 & o) << 4 | (i = _keyStr.indexOf(t.charAt(u++))) >> 2,
59 | r = (3 & i) << 6 | (a = _keyStr.indexOf(t.charAt(u++))),
60 | c += String.fromCharCode(e),
61 | 64 != i && (c += String.fromCharCode(n)),
62 | 64 != a && (c += String.fromCharCode(r));
63 | return c
64 | }
65 |
66 | function d2(t) {
67 | for (var e = "", n = 0; n < t.length; n++) {
68 | var r = _p.charCodeAt(n % _p.length);
69 | e += String.fromCharCode(t.charCodeAt(n) ^ r)
70 | }
71 | return _u_d(e)
72 | }
73 |
74 | function _u_d(t) {
75 | for (var e = "", n = 0, r = 0, o = 0, i = 0; n < t.length;)
76 | (r = t.charCodeAt(n)) < 128 ? (e += String.fromCharCode(r),
77 | n++) : r > 191 && r < 224 ? (o = t.charCodeAt(n + 1),
78 | e += String.fromCharCode((31 & r) << 6 | 63 & o),
79 | n += 2) : (o = t.charCodeAt(n + 1),
80 | i = t.charCodeAt(n + 2),
81 | e += String.fromCharCode((15 & r) << 12 | (63 & o) << 6 | 63 & i),
82 | n += 3);
83 | return e
84 | }
85 |
86 | function get_decrypt_data(encrypt_data) {
87 | var d = d1(encrypt_data),
88 | y = d2(d)
89 | return y;
90 | }
91 |
--------------------------------------------------------------------------------
/xiniu/demo.py:
--------------------------------------------------------------------------------
1 | # _*_ coding: utf-8 _*_
2 | # @Date: 6:03 下午
3 | # @File: demo.py
4 | # @Author: liyf
5 |
6 | """
7 | todo:
8 | - 网站: https://www.xiniudata.com/industry/newest?from=data
9 | - 数据接口: https://www.xiniudata.com/api2/service/x_service/person_industry_list/list_industries_by_sort ,post请求,请求参数 payload, sig
10 |
11 | changelog 20220819
12 | 该网站有两处需要进行破解
13 | 1. 请求参数 payload 和 sig
14 | - 定位参数加密位置。使用常规的全局搜索这两个参数,搜索到的结果太多,不太好分析。此时我们采用 XHR 断点进行分析。
15 | - '/person_industry_list/list_industries_by_sort',下拉刷新数据,xhr断点生效。
16 | - 此时在断点生效的这个js文件中,第19090到19093行,会发现以下代码
17 | todo
18 | '''
19 | var f = Object(c.c)(Object(c.d)(JSON.stringify(l.payload)))
20 | , p = Object(c.e)(f);
21 | l.payload = f,
22 | l.sig = p
23 | '''
24 | - 该地方就是请求参数的加密位置
25 | - 扣js代码,缺啥补啥,此时生成的是payload参数
26 | - sig参数的加密逻辑
27 | - 对 `payload + W5D80NFZHAYB8EUI2T649RT2MNRMVE2O` 组成的字符串进行md5加密,取大写
28 | - 经过测试,大写和小写都行,无所谓
29 | - 不过为了和接口里边的请求参数形式一致,还是取大写
30 | 2. 接口返回的数据是加密后的,需要解密
31 | - 还是在xhr断点生效的这个js文件中,第19113和19115行发现以下代码
32 | todo
33 | '''
34 | var d = Object(c.a)(l)
35 | , y = Object(c.b)(d)
36 | , v = JSON.parse(y);
37 | '''
38 | - 此时,v 就是解密后的数据
39 | """
40 |
41 | import json
42 | import execjs
43 | import hashlib
44 | import requests
45 |
46 | from utils import *
47 |
48 |
49 | def get_data(start, encrypt_data):
50 | """
51 | 解析js文件,当 encrypt_data 不存在时,说明start存在,此时解析请求参数payload;
52 | 当 start 不存在时,说明encrypt_data存在,此时对返回数据解密进行解析
53 | :param start: 解析参数payload时,需要的参数
54 | :param encrypt_data: 返回结果解密,需要的参数
55 | :return: result
56 | """
57 | ctx = Utils(js_file_name='demo.js').read_js_file()
58 | if not encrypt_data:
59 | callback = 'get_payload'
60 | params = start
61 | else:
62 | callback = 'get_decrypt_data'
63 | params = encrypt_data
64 | return ctx.call(str(callback), params)
65 |
66 |
67 | def get_results(page, start):
68 | headers = {
69 | 'authority': 'www.xiniudata.com',
70 | 'accept': 'application/json',
71 | 'accept-language': 'zh-CN,zh;q=0.9',
72 | 'origin': 'https://www.xiniudata.com',
73 | 'referer': 'https://www.xiniudata.com/industry/newest?from=data',
74 | 'user-agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/104.0.0.0 Safari/537.36',
75 | }
76 | payload = get_data(start=start, encrypt_data=None)
77 | sig = Utils(origin_md5_str=f'{payload}W5D80NFZHAYB8EUI2T649RT2MNRMVE2O').encrypt_md5()
78 | params_dict = {'payload': payload, 'sig': sig}
79 | logger.info(f'第 {page + 1} 页: {params_dict}')
80 | # 请求参数,缺一不可
81 | json_data = {
82 | 'payload': payload,
83 | 'sig': sig.upper(),
84 | 'v': 1,
85 | }
86 |
87 | response = requests.post(
88 | 'https://www.xiniudata.com/api2/service/x_service/person_industry_list/list_industries_by_sort',
89 | headers=headers, json=json_data)
90 | return response.json()
91 |
92 |
93 | def parse():
94 | for page in range(0, 10):
95 | start = page * 20
96 | results = get_results(page, start)
97 | decrypt_data = get_data(start=None, encrypt_data=results['d'])
98 | encrypt_data_json = json.loads(decrypt_data)
99 | data_list = encrypt_data_json['list']
100 | for data in data_list:
101 | name = data['name']
102 | compant_count = data['countCompany']
103 | event = data['event']
104 | companyVOs = ', '.join([item['name'] for item in data['companyVOs']])
105 | update_time = data['updateTime']
106 | print(f'赛道(数量): {name}({compant_count}) || {event}\n最近获投: {companyVOs}\n最近更新: {update_time}')
107 | print('===' * 35)
108 |
109 |
110 | if __name__ == '__main__':
111 | parse()
112 |
--------------------------------------------------------------------------------
/xmly_login/__init__.py:
--------------------------------------------------------------------------------
1 | # _*_ coding: utf-8 _*_
2 | # @Date: 4:30 下午
3 | # @File: __init__.py.py
4 | # @Author: liyf
5 |
--------------------------------------------------------------------------------
/xmly_login/demo.py:
--------------------------------------------------------------------------------
1 | # _*_ coding: utf-8 _*_
2 | # @Date: 4:30 下午
3 | # @File: demo.py
4 | # @Author: liyf
5 |
6 | import requests
7 |
8 | from utils import *
9 |
10 |
11 | def get_nonce():
12 | headers = {
13 | 'Accept': '*/*',
14 | 'Accept-Language': 'zh-CN,zh;q=0.9',
15 | 'Content-Type': 'application/x-www-form-urlencoded;charset=UTF-8',
16 | 'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/108.0.0.0 Safari/537.36',
17 | }
18 | response = requests.get('https://passport.ximalaya.com/web/nonce/1673423703373', headers=headers)
19 | results = response.json()
20 | return results['nonce']
21 |
22 |
23 | def get_pwd(pwd):
24 | ctx = Utils(js_file_name='get_pwd.js').read_js_file()
25 | return ctx.call('get_pwd', pwd)
26 |
27 |
28 | def get_signature(req_data):
29 | ctx = Utils(js_file_name='get_signature.js').read_js_file()
30 | return ctx.call('F', req_data)
31 |
32 |
33 | def get_results(password):
34 | nonce = get_nonce()
35 | logger.info(f'nonce: {nonce}')
36 | pwd = get_pwd(password) # password:明文密码
37 | logger.info(f'\n明文密码: {password}\n密文密码: {pwd}')
38 | json_data = {
39 | "account": "111111", # 账号
40 | "password": pwd,
41 | "nonce": nonce
42 | }
43 | signature = get_signature(json_data)
44 | logger.info(f'signature: {signature}')
45 | json_data['signature'] = signature
46 | json_data['rememberMe'] = True
47 | headers = {
48 | 'Accept': '*/*',
49 | 'Accept-Language': 'zh-CN,zh;q=0.9',
50 | 'Cache-Control': 'no-cache',
51 | 'Connection': 'keep-alive',
52 | 'Content-Type': 'application/json',
53 | 'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/108.0.0.0 Safari/537.36',
54 | }
55 | response = requests.post('https://passport.ximalaya.com/web/login/pwd/v1', headers=headers,
56 | json=json_data)
57 | return response.json()
58 |
59 |
60 | results = get_results('123456')
61 | msg = results['msg']
62 | logger.info(f'登录结果: {msg}') # 登录结果: 账号或密码错误
63 |
--------------------------------------------------------------------------------
/ybdzpz/__init__.py:
--------------------------------------------------------------------------------
1 | # _*_ coding: utf-8 _*_
2 | # @Date: 5:21 下午
3 | # @File: __init__.py.py
4 | # @Author: liyf
5 |
--------------------------------------------------------------------------------
/ybdzpz/demo.py:
--------------------------------------------------------------------------------
1 | # _*_ coding: utf-8 _*_
2 | # @Date: 6:21 下午
3 | # @File: demo.py
4 | # @Author: liyf
5 |
6 | '''
7 | - 全局搜索关键字 `decrypt(` 可定位到如下关键代码:
8 | var r = i.decrypt(n, e)
9 | , s = r[r.length - 1];
10 | return r = r.slice(0, r.length - s),
11 | t.from(r).toString("utf-8")
12 | - 在该处打断点,点击下一页之后,断点会生效。
13 |
14 | - 往前跟栈,可定位到如下代码:
15 | var e = Object(p["a"])(t.data);
16 | - 在该处再打一个断点,点击下一页,断点生效。
17 | - 在控制台输出 t.data,为加密数据
18 | - 在控制台输出 Object(p["a"])(t.data), 为解密后的数据
19 |
20 | - webpack加密,入口为 p = e("7d92")。
21 | - 其中e为分发器, 7d92 为模块名称
22 | - 在该处打断点,重新刷新页面,不要点击下一页,否则断点不会生效。
23 | - 接下来就是扣js代码了,没啥难度
24 |
25 | '''
26 |
27 | import requests
28 | import json
29 |
30 | from utils import *
31 |
32 | headers = {
33 | "Accept": "application/json, text/plain, */*",
34 | "Accept-Language": "zh-CN,zh;q=0.9",
35 | "Cache-Control": "no-cache",
36 | "Connection": "keep-alive",
37 | "Content-Type": "application/json",
38 | "Origin": "https://ybdzpz.ylbz.gansu.gov.cn",
39 | "Pragma": "no-cache",
40 | "Referer": "https://ybdzpz.ylbz.gansu.gov.cn/hsa-local-prod/web/hallEnter/",
41 | "Sec-Fetch-Dest": "empty",
42 | "Sec-Fetch-Mode": "cors",
43 | "Sec-Fetch-Site": "same-origin",
44 | "User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.0.0 Safari/537.36",
45 | }
46 |
47 | ctx = Utils(js_file_name='demo.js').read_js_file()
48 |
49 |
50 | def get_decrypt_data(data):
51 | decrypt_data = ctx.call('decrypt', data)
52 | return decrypt_data
53 |
54 |
55 | def get_results(page):
56 | url = "https://ybdzpz.ylbz.gansu.gov.cn/hsa-pss-pw/web/pw/base/queryRtalPhacBInfo"
57 | data = {
58 | "rtalPhacName": "",
59 | "rtalPhacCode": "",
60 | "uscc": "",
61 | "admdvs": "",
62 | "pageNo": page,
63 | "pageSize": 10
64 | }
65 | data = json.dumps(data, separators=(',', ':'))
66 | response = requests.post(url, headers=headers, data=data)
67 | return response.json()
68 |
69 |
70 | def main():
71 | for page in range(1, 10):
72 | results = get_results(page)
73 | decrypt_data = get_decrypt_data(results['data'])
74 | data_list = decrypt_data['data']
75 | for data in data_list:
76 | shop_name = data['rtalPhacName']
77 | addr = data['addr']
78 | social_code = data['uscc']
79 | scope = data['drugBizScp']
80 | licence_code = data['phacPmtno']
81 | shop_code = data['rtalPhacCode']
82 | print(
83 | f'药店名称: {shop_name}\n药店地址: {addr}\n统一社会信用代码: {social_code}\n药店经营范围: {scope}\n药店经营企业许可证号: {licence_code}\n药店代码: {shop_code}')
84 | print('===' * 30)
85 |
86 |
87 | if __name__ == '__main__':
88 | main()
89 |
--------------------------------------------------------------------------------
/yiche/__init__.py:
--------------------------------------------------------------------------------
1 | # _*_ coding: utf-8 _*_
2 | # @Date: 10:37 上午
3 | # @File: __init__.py.py
4 | # @Author: liyf
5 |
--------------------------------------------------------------------------------
/yiche/demo.py:
--------------------------------------------------------------------------------
1 | # _*_ coding: utf-8 _*_
2 | # @Date: 1:55 下午
3 | # @File: demo.py
4 | # @Author: liyf
5 |
6 | """
7 | 获取易车网汽车配置信息
8 | 根据cid获取value,用来拼接字符串,最终进行加密计算得到x-sign
9 | todo:{name: 'pc', value: '19DDD1FBDFF065D3A4DA777D2D7A81EC', cid: '508'},
10 | {name: 'phone', value: 'DB2560A6EBC65F37A0484295CD4EDD25', cid: '601'},
11 | {name: 'h5', value: '745DFB2027E8418384A1F2EF1B54C9F5', cid: '601'},
12 | {name: 'business_applet', value: '64A1071F6C3C3CC68DABBF5A90669C0A', cid: '601'},
13 | {name: 'wechat', value: 'AF23B0A6EBC65F37A0484395CE4EDD2K', cid: '601'},
14 | {name: 'tencent', value: '1615A9BDB0374D16AE9EBB3BBEE5353C', cid: '750'}
15 |
16 | 通过搜索关键字 x-sign 定位到代码
17 | 关键代码: r = "cid=" + t.cid + "¶m=" + n + o + t.timestamp,
18 | u = (0, x.md5)(r);
19 | 计算出来的u就是x-sign的值,经测试,r经过md5加密就是u的值
20 | """
21 |
22 | import json
23 | import time
24 | import hashlib
25 | import requests
26 |
27 |
28 | def get_s_sign(params) -> str:
29 | md5 = hashlib.md5()
30 | md5.update(params.encode('utf8'))
31 | return md5.hexdigest()
32 |
33 |
34 | def get_results(cid, para):
35 | t_str = str(int(time.time() * 1000))
36 | # 根据cid的不同,val的值不同
37 | val = '19DDD1FBDFF065D3A4DA777D2D7A81EC'
38 | params = 'cid=%s¶m=%s%s%s' % (cid, para, val, t_str)
39 | x_sign = get_s_sign(params)
40 | headers = {
41 | 'Accept': '*/*',
42 | 'Referer': 'https://car.yiche.com/yunqueq1/peizhi/',
43 | 'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/104.0.0.0 Safari/537.36',
44 | 'content-type': 'application/json;charset=UTF-8',
45 | # 以下四个请求头缺一不可
46 | 'x-city-id': '2401', # 城市标识
47 | 'x-platform': 'pc',
48 | 'x-sign': x_sign, # 经过加密得到的值
49 | 'x-timestamp': t_str, # 13位的时间戳
50 | }
51 | params = {
52 | 'cid': cid,
53 | 'param': para,
54 | }
55 | response = requests.get('https://mapi.yiche.com/web_api/car_model_api/api/v1/car/config_new_param', params=params,
56 | headers=headers)
57 | return response.json()
58 |
59 |
60 | def parse():
61 | para = {"cityId": "2401", "serialId": "5485"}
62 | cid = 508
63 | results = get_results(cid, json.dumps(para))
64 | print(results)
65 |
66 |
67 | if __name__ == '__main__':
68 | parse()
69 |
--------------------------------------------------------------------------------
/ypwk/__init__.py:
--------------------------------------------------------------------------------
1 | # _*_ coding: utf-8 _*_
2 | # @Date: 3:35 下午
3 | # @File: __init__.py.py
4 | # @Author: liyf
5 |
--------------------------------------------------------------------------------
/ypwk/demo.js:
--------------------------------------------------------------------------------
1 | /*
2 | * 一品威客(https://www.epwk.com/login.html)登录破解
3 | * 接口:https://www.epwk.com/api/epwk/v1/user/login
4 | - post请求
5 | - 参数以明文的形式传递
6 | - data = {
7 | 'username': '账号',
8 | 'password': '明文密码',
9 | 'code': '',
10 | 'hdn_refer': '',
11 | }
12 | * 破解参数:请求头中的Signature的值
13 | * todo 思路如下:
14 | * 全局搜索 `Signature`,很容易定位到加密位置
15 | * 下断点,重新请求,然后跟进去代码,可以定位到关键的加密函数,如下
16 | ```
17 | var data = arguments.length > 1 && void 0 !== arguments[1] ? arguments[1] : {}
18 | , e = arguments.length > 2 && void 0 !== arguments[2] ? arguments[2] : "a75846eb4ac490420ac63db46d2a03bf"
19 | , r = e + d(data) + d(t) + e;
20 | return r = f(r),
21 | r = m(r)
22 | ```
23 |
24 | * 经过两次加密,首先经过md5加密,r = f(r),其中f函数实现对参数r进行md5加密
25 | * 其次经过 `AES-CBC-Pkcs7` 模式加密,k和iv都能获取到。
26 | ```
27 | return function(data) {
28 | return c.a.AES.encrypt(data, l.key, {
29 | iv: l.iv,
30 | mode: c.a.mode.CBC,
31 | padding: c.a.pad.Pkcs7
32 | }).toString()
33 | }(data)
34 | ```
35 | * 最终得到Signature的值
36 | */
37 |
38 | var CryptoJS = require('crypto-js');
39 |
40 | var d = function (t) {
41 | var e = "";
42 | return Object.keys(t).sort().forEach((function (r) {
43 | e += r + ("object" === n_a(t[r]) ? JSON.stringify(t[r], (function (t, e) {
44 | return "number" == typeof e && (e = String(e)),
45 | e
46 | }
47 | )).replace(/\//g, "\\/") : t[r])
48 | }
49 | )),
50 | e
51 | },
52 | f = function (data) {
53 | return CryptoJS.MD5(data).toString()
54 | },
55 | l_t = {
56 | key: CryptoJS.enc.Utf8.parse("fX@VyCQVvpdj8RCa"),
57 | iv: CryptoJS.enc.Utf8.parse(function (t) {
58 | for (var e = "", i = 0; i < t.length - 1; i += 2) {
59 | var r = parseInt(t[i] + "" + t[i + 1], 16);
60 | e += String.fromCharCode(r)
61 | }
62 | return e
63 | }("00000000000000000000000000000000"))
64 | },
65 | m = function (data) {
66 | return function (data) {
67 | return CryptoJS.AES.encrypt(data, l_t.key, {
68 | iv: l_t.iv,
69 | mode: CryptoJS.mode.CBC,
70 | padding: CryptoJS.pad.Pkcs7
71 | }).toString()
72 | }(data)
73 | };
74 |
75 | function n_a(e) {
76 | return typeof e
77 | }
78 |
79 | function h_e() {
80 | var e = arguments.length > 0 && void 0 !== arguments[0] ? arguments[0] : 5;
81 | return Math.random().toString(36).substring(3, 3 + e)
82 | }
83 |
84 | function get_signature(ts) {
85 | var l = {
86 | "i": false,
87 | "j": false,
88 | "h": true,
89 | "d": "prod",
90 | "a": "https://s1.weikeimg.com/_nuxt/",
91 | "e": "https://im2.epwitkey.com",
92 | "b": "4ac490420ac63db4",
93 | "c": "a75846eb4ac490420ac63db46d2a03bf",
94 | "f": "af9f93d4530c6167",
95 | "g": "c93ce713af9f93d4530c6167b78a3871"
96 | },
97 | t = {
98 | "App-Ver": "",
99 | "Os-Ver": "",
100 | "Device-Ver": "",
101 | Imei: "",
102 | "Access-Token": "",
103 | Timestemp: ts,
104 | NonceStr: "".concat(ts).concat(h_e()),
105 | "App-Id": l.j ? l.f : l.b,
106 | "Device-Os": "web"
107 | };
108 | var data = arguments.length > 1 && void 0 !== arguments[1] ? arguments[1] : {}
109 | , e = arguments.length > 2 && void 0 !== arguments[2] ? arguments[2] : "a75846eb4ac490420ac63db46d2a03bf"
110 | , r = e + d(data) + d(t) + e
111 | , r = f(r),
112 | r = m(r);
113 | return {signature: r, params: t}
114 | }
115 |
116 | var ts = parseInt((new Date).getTime() / 1e3);
117 | console.log(get_signature(ts))
--------------------------------------------------------------------------------
/yuanrenxue/__init__.py:
--------------------------------------------------------------------------------
1 | # _*_ coding: utf-8 _*_
2 | # @Date: 11:22 上午
3 | # @File: __init__.py.py
4 | # @Author: liyf
5 |
--------------------------------------------------------------------------------
/yuanrenxue/readme.md:
--------------------------------------------------------------------------------
1 | ## 关于题目
2 |
3 | - 以 `topic` 开头的文件夹,来源于猿人学逆向练习网站 [猿人学Python - 内部学员练习平台 正式版](https://www.python-spider.com/challenge/)
4 |
5 | - 以 `scrape` 开头的文件夹,来源于崔佬搭建的逆向网站 [Scrape Center - 案例列表](https://scrape.center/)
6 |
7 | - 以 `wangluozhe` 开头的文件夹,来源于K哥搭建的网站 [网络者 - 反反爬虫练习平台](https://wangluozhe.com/challenge/)
8 |
--------------------------------------------------------------------------------
/yuanrenxue/scrape_login1/__init__.py:
--------------------------------------------------------------------------------
1 | # _*_ coding: utf-8 _*_
2 | # @Date: 11:28 上午
3 | # @File: __init__.py.py
4 | # @Author: liyf
5 |
--------------------------------------------------------------------------------
/yuanrenxue/scrape_login1/demo.py:
--------------------------------------------------------------------------------
1 | # _*_ coding: utf-8 _*_
2 | # @Date: 10:52 上午
3 | # @File: demo.py
4 | # @Author: liyf
5 | import requests
6 | import json
7 | import execjs
8 |
9 | from loguru import logger
10 |
11 | headers = {
12 | "Accept": "application/json, text/plain, */*",
13 | "Accept-Language": "zh-CN,zh;q=0.9",
14 | "Cache-Control": "no-cache",
15 | "Connection": "keep-alive",
16 | "Content-Type": "application/json;charset=UTF-8",
17 | "Origin": "https://login1.scrape.center",
18 | "Pragma": "no-cache",
19 | "Referer": "https://login1.scrape.center/",
20 | "Sec-Fetch-Dest": "empty",
21 | "Sec-Fetch-Mode": "cors",
22 | "Sec-Fetch-Site": "same-origin",
23 | "User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.0.0 Safari/537.36",
24 | }
25 |
26 |
27 | def get_token(params):
28 | js_str = '''
29 | // 补atob 和btoa 环境
30 | // ============================================================
31 | global.Buffer = global.Buffer || require('buffer').Buffer;
32 | if (typeof btoa === 'undefined') {
33 | global.btoa = function (str) {
34 | return new Buffer.from(str).toString('base64');
35 | };
36 | }
37 |
38 | if (typeof atob === 'undefined') {
39 | global.atob = function (b64Encoded) {
40 | return new Buffer.from(b64Encoded, 'base64').toString();
41 | };
42 | }
43 | var self = global
44 | // ============================================================
45 | var re_utob = /[\\uD800-\\uDBFF][\\uDC00-\\uDFFFF]|[^\\x00-\\x7F]/g,
46 | utob = function (e) {
47 | return e.replace(re_utob, cb_utob)
48 | },
49 | _encode = function (e) {
50 | return self.btoa(utob(e))
51 | },
52 | cb_utob = function (e) {
53 | if (e.length < 2) {
54 | var r = e.charCodeAt(0);
55 | return r < 128 ? e : r < 2048 ? fromCharCode(192 | r >>> 6) + fromCharCode(128 | 63 & r) : fromCharCode(224 | r >>> 12 & 15) + fromCharCode(128 | r >>> 6 & 63) + fromCharCode(128 | 63 & r)
56 | }
57 | r = 65536 + 1024 * (e.charCodeAt(0) - 55296) + (e.charCodeAt(1) - 56320);
58 | return fromCharCode(240 | r >>> 18 & 7) + fromCharCode(128 | r >>> 12 & 63) + fromCharCode(128 | r >>> 6 & 63) + fromCharCode(128 | 63 & r)
59 | };
60 |
61 | var c = {
62 | encode: function (e, r) {
63 | return r ? _encode(String(e)).replace(/[+\/]/g, (function (e) {
64 | return "+" == e ? "-" : "_"
65 | }
66 | )).replace(/=/g, "") : _encode(String(e))
67 | }
68 | }
69 |
70 | function get_token(e) {
71 | var token = c.encode(JSON.stringify(e));
72 | return token
73 | }
74 | '''
75 | ctx = execjs.compile(''.join(js_str))
76 | token = ctx.call('get_token', params)
77 | return token
78 |
79 |
80 | def get_login_res():
81 | url = "https://login1.scrape.center/"
82 | params = {
83 | 'username': 'admin',
84 | 'password': 'admin'
85 | }
86 | token = get_token(params)
87 | logger.info(f'token: {token}')
88 | data = {
89 | "token": token
90 | }
91 | data = json.dumps(data, separators=(',', ':'))
92 | response = requests.post(url, headers=headers, data=data)
93 | logger.info(f'请求状态码: {response.status_code}')
94 |
95 |
96 | if __name__ == '__main__':
97 | get_login_res()
98 |
--------------------------------------------------------------------------------
/yuanrenxue/scrape_spa2/__init__.py:
--------------------------------------------------------------------------------
1 | # _*_ coding: utf-8 _*_
2 | # @Date: 5:47 下午
3 | # @File: __init__.py.py
4 | # @Author: liyf
5 |
--------------------------------------------------------------------------------
/yuanrenxue/scrape_spa2/demo.py:
--------------------------------------------------------------------------------
1 | # _*_ coding: utf-8 _*_
2 | # @Date: 6:20 下午
3 | # @File: demo.py
4 | # @Author: liyf
5 |
6 | import requests
7 |
8 | from utils import *
9 |
10 |
11 | def get_token(page):
12 | ctx = Utils(js_file_name='demo.js').read_js_file()
13 | return ctx.call('get_token', page)
14 |
15 |
16 | def get_results(page):
17 | headers = {
18 | 'Accept': 'application/json, text/plain, */*',
19 | 'Accept-Language': 'zh-CN,zh;q=0.9',
20 | 'Cache-Control': 'no-cache',
21 | 'Connection': 'keep-alive',
22 | 'Pragma': 'no-cache',
23 | 'Referer': 'https://spa2.scrape.center/page/9',
24 | 'Sec-Fetch-Dest': 'empty',
25 | 'Sec-Fetch-Mode': 'cors',
26 | 'Sec-Fetch-Site': 'same-origin',
27 | 'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/105.0.0.0 Safari/537.36',
28 | 'sec-ch-ua': '"Google Chrome";v="105", "Not)A;Brand";v="8", "Chromium";v="105"',
29 | 'sec-ch-ua-mobile': '?0',
30 | 'sec-ch-ua-platform': '"macOS"',
31 | }
32 | token = get_token(page)
33 | logger.info(f'当前页码: {page}, token: {token}')
34 | params = {
35 | 'limit': '10',
36 | 'offset': str((page - 1) * 10),
37 | 'token': token,
38 | }
39 | response = requests.get('https://spa2.scrape.center/api/movie/', params=params, headers=headers)
40 | return response.json()
41 |
42 |
43 | def parse():
44 | for page in range(1, 12):
45 | results = get_results(page)
46 | data_list = results['results']
47 | for data in data_list:
48 | name = data['name']
49 | tag = data['categories']
50 | regions = data['regions']
51 | score = data['score']
52 | minute = data['minute']
53 | published_at = data['published_at']
54 | alias = data['alias']
55 | print(
56 | f'电影名称: {name}\n别名: {alias}\n类型: {tag}\n国家: {regions}\n评分: {score}\n时长: {minute}\n上映时间: {published_at}')
57 | print('***' * 15)
58 |
59 |
60 | if __name__ == '__main__':
61 | parse()
62 |
--------------------------------------------------------------------------------
/yuanrenxue/scrape_spa6/__init__.py:
--------------------------------------------------------------------------------
1 | # _*_ coding: utf-8 _*_
2 | # @Date: 3:20 下午
3 | # @File: __init__.py.py
4 | # @Author: liyf
5 |
--------------------------------------------------------------------------------
/yuanrenxue/scrape_spa6/demo.py:
--------------------------------------------------------------------------------
1 | # _*_ coding: utf-8 _*_
2 | # @Date: 6:20 下午
3 | # @File: demo.py
4 | # @Author: liyf
5 | import requests
6 |
7 | from utils import *
8 |
9 |
10 | def get_token(page):
11 | ctx = Utils(js_file_name='demo.js').read_js_file()
12 | return ctx.call('get_token', page)
13 |
14 |
15 | def get_results(page):
16 | headers = {
17 | 'Accept': 'application/json, text/plain, */*',
18 | 'Accept-Language': 'zh-CN,zh;q=0.9',
19 | 'Cache-Control': 'no-cache',
20 | 'Connection': 'keep-alive',
21 | 'Pragma': 'no-cache',
22 | 'Referer': 'https://spa2.scrape.center/page/9',
23 | 'Sec-Fetch-Dest': 'empty',
24 | 'Sec-Fetch-Mode': 'cors',
25 | 'Sec-Fetch-Site': 'same-origin',
26 | 'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/105.0.0.0 Safari/537.36',
27 | 'sec-ch-ua': '"Google Chrome";v="105", "Not)A;Brand";v="8", "Chromium";v="105"',
28 | 'sec-ch-ua-mobile': '?0',
29 | 'sec-ch-ua-platform': '"macOS"',
30 | }
31 | token = get_token(page)
32 | logger.info(f'当前页码: {page}, token: {token}')
33 | params = {
34 | 'limit': '10',
35 | 'offset': str((page - 1) * 10),
36 | 'token': token,
37 | }
38 | response = requests.get('https://spa6.scrape.center/api/movie/', params=params, headers=headers)
39 | return response.json()
40 |
41 |
42 | def parse():
43 | for page in range(1, 12):
44 | results = get_results(page)
45 | data_list = results['results']
46 | for data in data_list:
47 | name = data['name']
48 | tag = data['categories']
49 | regions = data['regions']
50 | score = data['score']
51 | minute = data['minute']
52 | published_at = data['published_at']
53 | alias = data['alias']
54 | print(
55 | f'电影名称: {name}\n别名: {alias}\n类型: {tag}\n国家: {regions}\n评分: {score}\n时长: {minute}\n上映时间: {published_at}')
56 | print('***' * 15)
57 |
58 |
59 | if __name__ == '__main__':
60 | parse()
61 |
--------------------------------------------------------------------------------
/yuanrenxue/topic13/__init__.py:
--------------------------------------------------------------------------------
1 | # _*_ coding: utf-8 _*_
2 | # @Date: 1:31 下午
3 | # @File: __init__.py.py
4 | # @Author: liyf
5 |
--------------------------------------------------------------------------------
/yuanrenxue/topic13/demo.py:
--------------------------------------------------------------------------------
1 | # _*_ coding: utf-8 _*_
2 | # @Date: 1:31 下午
3 | # @File: demo.py
4 | # @Author: liyf
5 | import os
6 |
7 | import base64
8 | import requests
9 |
10 | from loguru import logger
11 | from fontTools.ttLib import TTFont
12 |
13 |
14 | def get_results(page):
15 | headers = {
16 | 'authority': 'www.python-spider.com',
17 | 'accept': 'application/json, text/javascript, */*; q=0.01',
18 | 'accept-language': 'zh-CN,zh;q=0.9',
19 | 'user-agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/103.0.0.0 Safari/537.36',
20 | 'x-requested-with': 'XMLHttpRequest',
21 | }
22 |
23 | data = {
24 | 'page': page,
25 | }
26 |
27 | response = requests.post('https://www.python-spider.com/api/challenge13', headers=headers, data=data)
28 | return response.json()
29 |
30 |
31 | def parse_woff(page, woff):
32 | # base64解码,并保存为tff文件格式
33 | b = base64.b64decode(woff)
34 | woff_name = f'topic13_{page}.woff'
35 | xml_name = f'topic13_{page}.xml'
36 | with open(woff_name, 'wb') as f:
37 | f.write(b)
38 | f.close()
39 | font = TTFont(woff_name)
40 | font.saveXML(xml_name)
41 | extraNames = font.get('post').__dict__['extraNames']
42 | woff_dict = {
43 | val.replace('uni', ''): 0 if index >= 9 else index + 1
44 | for index, val in enumerate(extraNames)
45 | }
46 | os.remove(woff_name)
47 | os.remove(xml_name)
48 | logger.info(f'已删除文件: {woff_name} 和 {xml_name}')
49 | return woff_dict
50 |
51 |
52 | def parse():
53 | count = 0
54 | for page in range(1, 101):
55 | results = get_results(page)
56 | woff = results['woff']
57 | woff_dict = parse_woff(page, woff)
58 | datas = results['data']
59 | for data in datas:
60 | count += int(''.join([f'{woff_dict[key]}' for key in data['value'].strip().split(' ')]))
61 | logger.info(f'前 {page} 页之和为: {count}')
62 | logger.info('***' * 20)
63 |
64 |
65 | if __name__ == '__main__':
66 | # 答案: 4943577
67 | parse()
68 |
--------------------------------------------------------------------------------
/yuanrenxue/topic14/__init__.py:
--------------------------------------------------------------------------------
1 | # _*_ coding: utf-8 _*_
2 | # @Date: 2:19 下午
3 | # @File: __init__.py.py
4 | # @Author: liyf
5 |
--------------------------------------------------------------------------------
/yuanrenxue/topic14/demo.js:
--------------------------------------------------------------------------------
1 | var CryptoJS = require('crypto-js')
2 |
3 | var window = {}
4 |
5 |
6 | function aes_encrypt(word) {
7 | var k = 'wdf2ff*TG@*(F4)*YH)g430HWR(*)' + 'wse';
8 | var key = CryptoJS.enc.Utf8.parse(k);
9 | var srcs = CryptoJS.enc.Utf8.parse(word);
10 | var encrypted = CryptoJS.AES.encrypt(srcs, key, {
11 | mode: CryptoJS.mode.ECB,
12 | padding: CryptoJS.pad.Pkcs7
13 | });
14 | return encrypted.toString();
15 | }
16 |
17 | function get_uc(page){
18 | window.t = Date.parse(new Date()) / 1000;
19 | word = window.t + '|' + page
20 | uc = aes_encrypt(word)
21 | return uc
22 | }
23 |
--------------------------------------------------------------------------------
/yuanrenxue/topic14/demo.py:
--------------------------------------------------------------------------------
1 | # _*_ coding: utf-8 _*_
2 | # @Date: 2:27 下午
3 | # @File: demo.py
4 | # @Author: liyf
5 |
6 | """
7 | js_fuck
8 | """
9 |
10 | import requests
11 |
12 | from utils import *
13 |
14 |
15 | def get_uc(page):
16 | ctx = Utils(js_file_name='demo.js').read_js_file()
17 | return ctx.call('get_uc', page)
18 |
19 |
20 | def get_results(page):
21 | headers = {
22 | 'authority': 'www.python-spider.com',
23 | 'accept': 'application/json, text/javascript, */*; q=0.01',
24 | 'accept-language': 'zh-CN,zh;q=0.9',
25 | 'user-agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/103.0.0.0 Safari/537.36',
26 | 'x-requested-with': 'XMLHttpRequest',
27 | }
28 | uc = get_uc(page)
29 | logger.info(f'page: {page}, uc: {uc}')
30 | data = {
31 | 'page': page,
32 | 'uc': uc
33 | }
34 | response = requests.post('https://www.python-spider.com/api/challenge14', headers=headers, data=data)
35 | return response.json()
36 |
37 |
38 | if __name__ == '__main__':
39 | # 答案: 5175137
40 | count = 0
41 | for page in range(1, 101):
42 | results = get_results(page)
43 | data_List = results['data']
44 | for data in data_List:
45 | count += int(str(data['value']).strip())
46 | logger.info(f' 前 {page} 页数字相加之和为: {count}')
47 | logger.info('***' * 20)
48 |
--------------------------------------------------------------------------------
/yuanrenxue/topic25/__init__.py:
--------------------------------------------------------------------------------
1 | # _*_ coding: utf-8 _*_
2 | # @Date: 2:09 下午
3 | # @File: __init__.py.py
4 | # @Author: liyf
5 |
--------------------------------------------------------------------------------
/yuanrenxue/topic25/demo.py:
--------------------------------------------------------------------------------
1 | # _*_ coding: utf-8 _*_
2 | # @Date: 11:05 上午
3 | # @File: demo.py
4 | # @Author: liyf
5 |
6 | '''
7 | 主页接口:https://www.python-spider.com/challenge/25
8 |
9 | 刷新该页面出现以下两个接口:
10 | - challenge25 接口
11 | - 获取数据接口,从第一页开始
12 | - challenge25verify 接口
13 | - 这个是获取图片的接口,接口返回的图片格式是base64
14 |
15 | 滑动图片,出现第三个接口
16 | - challenge25CheckVerify 接口
17 | - 参数是识别出来的缺口距离
18 | - 返回值中有个 rate 值,当这个值大于95%时候,请求下一页才能成功,否则请求失败
19 |
20 |
21 | 该代码识别准确率不高,只能识别出来前几页。使用的ddddocr,如果有更好的识别方法,欢迎交流
22 | '''
23 |
24 | import os
25 | import base64
26 | import ddddocr
27 | import requests
28 |
29 | from loguru import logger
30 |
31 | path = 'images'
32 |
33 | if not os.path.exists(path):
34 | os.makedirs(path)
35 |
36 | bg_name, slide_name = 'bg', 'slide'
37 |
38 | headers = {
39 | 'authority': 'www.python-spider.com',
40 | 'accept': 'application/json, text/javascript, */*; q=0.01',
41 | 'accept-language': 'zh-CN,zh;q=0.9',
42 | 'cache-control': 'no-cache',
43 | 'content-type': 'application/x-www-form-urlencoded; charset=UTF-8',
44 | 'origin': 'https://www.python-spider.com',
45 | # cookie参数必须携带,为renponse header中set-cookie的值
46 | 'cookie': 'sessionid=svm5k9nf9z6ublc7qjbndn3n84q85f0k; expires=Fri, 14 Apr 2023 09:43:14 GMT; HttpOnly; Max-Age=21600; Path=/; SameSite=Lax',
47 | 'pragma': 'no-cache',
48 | 'referer': 'https://www.python-spider.com/challenge/25',
49 | 'sec-ch-ua': '"Chromium";v="112", "Google Chrome";v="112", "Not:A-Brand";v="99"',
50 | 'sec-ch-ua-mobile': '?0',
51 | 'sec-ch-ua-platform': '"macOS"',
52 | 'sec-fetch-dest': 'empty',
53 | 'sec-fetch-mode': 'cors',
54 | 'sec-fetch-site': 'same-origin',
55 | 'user-agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/112.0.0.0 Safari/537.36',
56 | 'x-requested-with': 'XMLHttpRequest',
57 | }
58 |
59 |
60 | def get_results(page, distant):
61 | if page:
62 | data = {'page': str(page)}
63 | url = 'https://www.python-spider.com/api/challenge25'
64 | response = requests.post(url, headers=headers, data=data)
65 | else:
66 | data = {'distant': str(distant)}
67 | url = 'https://www.python-spider.com/api/challenge25CheckVerify'
68 | response = requests.post(url, headers=headers, data=data)
69 | return response.json()
70 |
71 |
72 | def trans_image(name, b64_str):
73 | '''
74 | base64字符串还原成图片,并保存
75 | :return:
76 | '''
77 | imgdata = base64.b64decode(b64_str)
78 | f = open(f'{path}/{name}.png', 'wb')
79 | f.write(imgdata)
80 | f.close()
81 |
82 |
83 | def get_distance(path):
84 | '''
85 | 识别缺口距离
86 | :param path: 图片存放的位置
87 | :return:
88 | '''
89 | det = ddddocr.DdddOcr(det=False, ocr=False, show_ad=False)
90 | puzzle_path = f'{path}/{slide_name}.png'
91 | bg_path = f'{path}/{bg_name}.png'
92 | puzzle_bytes = open(puzzle_path, 'rb').read()
93 | bg_bytes = open(bg_path, 'rb').read()
94 | res = det.slide_match(puzzle_bytes, bg_bytes, simple_target=True)
95 | distance = res['target'][0]
96 | return distance
97 |
98 |
99 | def get_image():
100 | url = 'https://www.python-spider.com/api/challenge25verify'
101 | response = requests.get(url, headers=headers)
102 | results = response.json()
103 | for name, b64_str in results.items():
104 | trans_image(bg_name if name == 'img1' else slide_name, b64_str)
105 |
106 |
107 | def get_rate():
108 | get_image()
109 | distance = get_distance(path)
110 | rate_res = get_results(page=None, distant=distance)
111 | rate = rate_res["rate"]
112 | return distance, rate
113 |
114 |
115 | def main():
116 | count = 0
117 | for page in range(1, 101):
118 | results = get_results(page, distant=None)
119 | data_list = results['data']
120 | count += sum([int(data['value']) for data in data_list])
121 | logger.info(f'前 {page} 页的和为: {count}')
122 | distance, rate = get_rate()
123 | num = int(str(rate).split('.')[0])
124 | logger.info(f'缺口位置: {distance}, 成功率: {rate}')
125 | while num < 95:
126 | distance, rate = get_rate()
127 | num = int(str(rate).split('.')[0])
128 | logger.info(f'第 {page + 1} 页, distance: {distance}, rate: {rate}')
129 | else:
130 | continue
131 |
132 |
133 | if __name__ == '__main__':
134 | main()
135 |
--------------------------------------------------------------------------------
/yuanrenxue/topic55/__init__.py:
--------------------------------------------------------------------------------
1 | # _*_ coding: utf-8 _*_
2 | # @Date: 5:03 下午
3 | # @File: __init__.py.py
4 | # @Author: liyf
5 |
--------------------------------------------------------------------------------
/yuanrenxue/topic55/demo.js:
--------------------------------------------------------------------------------
1 | var CryptoJS = require('crypto-js')
2 |
3 | function decode(str) {
4 | var CryptoJS = require("crypto-js");
5 | var KEY = 'aiding6666666666';
6 | var key = CryptoJS.enc.Utf8.parse(KEY);
7 | var decrypted = CryptoJS.AES.decrypt(str, key, {
8 | // iv: iv,
9 | mode: CryptoJS.mode.ECB,
10 | padding: CryptoJS.pad.Pkcs7,
11 | });
12 | return decrypted.toString(CryptoJS.enc.Utf8)
13 | }
14 |
15 | function get_data_list(result) {
16 | return JSON.parse(decode(result)).data;
17 | }
18 |
--------------------------------------------------------------------------------
/yuanrenxue/topic55/demo.py:
--------------------------------------------------------------------------------
1 | # _*_ coding: utf-8 _*_
2 | # @Date: 5:05 下午
3 | # @File: demo.py
4 | # @Author: liyf
5 |
6 | """
7 | AES加密
8 | ECB模式,Pkcs7填充方式
9 | """
10 | import requests
11 |
12 | from utils import *
13 |
14 |
15 | def get_results(page):
16 | headers = {
17 | 'authority': 'www.python-spider.com',
18 | 'accept': 'application/json, text/javascript, */*; q=0.01',
19 | 'accept-language': 'zh-CN,zh;q=0.9',
20 | 'user-agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/103.0.0.0 Safari/537.36',
21 | 'x-requested-with': 'XMLHttpRequest',
22 | }
23 |
24 | data = {
25 | 'page': page,
26 | }
27 |
28 | response = requests.post('https://www.python-spider.com/api/challenge55', headers=headers, data=data)
29 | return response.json()
30 |
31 |
32 | def get_data_list(result):
33 | ctx = Utils(js_file_name='demo.js').read_js_file()
34 | return ctx.call('get_data_list', result)
35 |
36 |
37 | if __name__ == '__main__':
38 | # 答案: 5082763
39 | count = 0
40 | for page in range(1, 101):
41 | results = get_results(page)
42 | data_List = get_data_list(results['result'])
43 | for data in data_List:
44 | count += int(str(data['value']).strip())
45 | logger.info(f' 前 {page} 页数字相加之和为: {count}')
46 |
--------------------------------------------------------------------------------
/yuanrenxue/topic56/__init__.py:
--------------------------------------------------------------------------------
1 | # _*_ coding: utf-8 _*_
2 | # @Date: 2:39 下午
3 | # @File: __init__.py.py
4 | # @Author: liyf
5 |
--------------------------------------------------------------------------------
/yuanrenxue/topic56/demo.js:
--------------------------------------------------------------------------------
1 | window = global;
2 |
3 | var JSEncryt = require('jsencrypt')
4 | , PVA = '-----BEGIN RSA PRIVATE KEY-----\n' +
5 | 'MIIEpAIBAAKCAQEAy5R1R2yM5jPPvkO2F47qVqMkYj7o92DF8y1yMkCSxY1WwqG0\n' +
6 | 'dCdUZTnaoBuAz99wGt55oGLcdalV71nPUiGWs/b6GzVN5v72baz/Q2OxHtkrFKqL\n' +
7 | 'VX16LW31cW9hAntN84RCbvTeB0MNV+SHmXjIf17OQLCtDKHBZWZ5NKyqFstO+KOd\n' +
8 | 'u32d2jsw+DT5lOBzDUBk/wUw2KyFJVx7eK6sSXEyWqBk2nxMRDNYixIEN1V1EBSq\n' +
9 | 'f+OwKK5Mxi04r38+Qog8z03/t/u6CfAOWVmi+MdrD1VHXv/P7bnFlgRcLzKwK1QL\n' +
10 | 'TSLBE1PrMmNNj0oRjByhMoI9tY5X6mRBqLyDhwIDAQABAoIBAGO++RmGO6D9CNAJ\n' +
11 | '4Bm52eKaK5UBiubOIR8NiNLLZb5qinRxg3eX35d7Wb2xzBLNwOFBWSl21trFncfY\n' +
12 | '4qY0s+C4ZYHYQ7Om/7nsFeQAYAOj1yJYj01TXf4NTsGGF2t+W8qxZlV0H6dCOLL0\n' +
13 | 'U2YkUmRp4Le8eQVj6dyTcVaYNPxWQBnb9ZOEIEvEjeoO/DD7CCmt7LDCey9KrTQl\n' +
14 | 'Avuc2nN6uRV1Wfm0P8conKPJtVdgzMvJujNdpz+bBDqwsqgeCICjs/hSCNO81VH3\n' +
15 | 'DD7J0mG2OHqowOVqagoDHpBprHOUKxAeTs9I0KEL+hEI4zXCDL69+Xs6azuts733\n' +
16 | 'zSOmwxkCgYEA25czfPVxxcK685LhaAvwbmzWHqNp07ytRNGf+Aww6OdgWkdgPy0n\n' +
17 | '20Gkg0HAqsxGcgZJk6cAkOy5hBLNHpHlGbeWFi+62lVNYUv3hAxumtiPyBMu7avE\n' +
18 | 'ZQCTXND1H1f/2enRDJRxQsR8y/SX1ivmC5U6fx7hbpKxnXyRHnvSlk8CgYEA7VWp\n' +
19 | 'hLNkn4AEaPPW0TknwKG40At/hjecX2zWAyZVt4ydDSeKgMEOUdmvGGlSCrefAl0n\n' +
20 | 'PTfM9SdIDcO5OTa2wUayKLIsrb6TDnG6KXXN6z3HR3Q4qKJbG83eaMYDqqziPPV+\n' +
21 | 'xzRVWShI3EGwkLczASmiYy+sEAT0OkxP59xTKUkCgYBgaGjFkukJfy4fJDxsNtmv\n' +
22 | 'UX9MYkhjGrIjxbjq6UdL6dGGsVGTSxr1i0NUETkqg5bmFtaUybxY5GWqk6qUok8o\n' +
23 | 'VE7DnN73Xn4jmnun8OFagHvXxnxTApeuFGueU2tbAIKmxJ3wXPfA7Y0w6kkDUbCl\n' +
24 | 'IzZUe1VT+3mZgAgijxBsxwKBgQDNytiJ62/V6hBo3P6pPtEcdF6nb0DtpazfBaVw\n' +
25 | '572twaywqlermzsKeCIenbx49I1ZZGLQ72C2NpCA9vTWCn5fiyiSpyScp0ImZTDS\n' +
26 | 'IIckctYoPDug5d7wdgtjeEfXp78osopyuwtCmu7Kpd8vLNt6J5raPI0K+vC22FL1\n' +
27 | 'LpOhmQKBgQCFeU448fL87N1MjMyusi8wJ5MLcn+kHbLTtpskTpfQM2p3Cnp4oL+7\n' +
28 | 'BI4AlXlKItV37rJIjZxQgLWhGoTZPplZaW4ooJCFJbazce5ua5fnsFS0oXhDN7uw\n' +
29 | 'jaq+v5t8G6gFS09hEa4kz9O53t/7UGuQqh0Bxb0cJ9iNeAlhagvBDQ==\n' +
30 | '-----END RSA PRIVATE KEY-----\n';
31 |
32 | var A = new JSEncryt();
33 | A.setPrivateKey(PVA)
34 |
35 | function get_decrypt_data(encrypt_data) {
36 | return JSON.parse(A.decrypt(encrypt_data))
37 | }
--------------------------------------------------------------------------------
/yuanrenxue/topic56/demo.py:
--------------------------------------------------------------------------------
1 | # _*_ coding: utf-8 _*_
2 | # @Date: 2:52 下午
3 | # @File: demo.py
4 | # @Author: liyf
5 |
6 | import requests
7 |
8 | from utils import *
9 |
10 |
11 | def get_results(page):
12 | headers = {
13 | 'authority': 'www.python-spider.com',
14 | 'accept': 'application/json, text/javascript, */*; q=0.01',
15 | 'accept-language': 'zh-CN,zh;q=0.9',
16 | 'user-agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/103.0.0.0 Safari/537.36',
17 | 'x-requested-with': 'XMLHttpRequest',
18 | }
19 | data = {
20 | 'page': page,
21 | }
22 | response = requests.post('https://www.python-spider.com/api/challenge56', headers=headers, data=data)
23 | return response.json()
24 |
25 |
26 | def get_decrypt_data(result):
27 | ctx = Utils(js_file_name='demo.js').read_js_file()
28 | return ctx.call('get_decrypt_data', result)
29 |
30 |
31 | if __name__ == '__main__':
32 | # 答案: 4976861
33 | count = 0
34 | for page in range(1, 101):
35 | results = get_results(page)
36 | data_List = get_decrypt_data(results['result'])
37 | for data in data_List['data']:
38 | count += int(str(data['value']).strip())
39 | logger.info(f' 前 {page} 页数字相加之和为: {count}')
40 |
--------------------------------------------------------------------------------
/yuanrenxue/topic57/__init__.py:
--------------------------------------------------------------------------------
1 | # _*_ coding: utf-8 _*_
2 | # @Date: 1:37 下午
3 | # @File: __init__.py.py
4 | # @Author: liyf
5 |
--------------------------------------------------------------------------------
/yuanrenxue/topic57/demo.js:
--------------------------------------------------------------------------------
1 | var CryptoJS = require('crypto-js')
2 |
3 | function I(X, l) {
4 | var C = X
5 | , q = CryptoJS.enc.Utf8.parse(C)
6 | , v = CryptoJS.TripleDES.decrypt(l, q, {
7 | 'mode': CryptoJS.mode.ECB,
8 | 'padding': CryptoJS.pad.Pkcs7
9 | });
10 | return v.toString(CryptoJS.enc.Utf8);
11 | }
12 |
13 | function get_data_list(result) {
14 | var datas = JSON.parse(I(result.slice(0, 8), result.slice(8)))['data']
15 | return datas
16 | }
--------------------------------------------------------------------------------
/yuanrenxue/topic57/demo.py:
--------------------------------------------------------------------------------
1 | # _*_ coding: utf-8 _*_
2 | # @Date: 2:20 下午
3 | # @File: demo.py
4 | # @Author: liyf
5 |
6 | """
7 | AES加密
8 | CBC模式,Pkcs7填充方式
9 | """
10 | import requests
11 |
12 | from utils import *
13 |
14 |
15 | def get_results(page):
16 | headers = {
17 | 'authority': 'www.python-spider.com',
18 | 'accept': 'application/json, text/javascript, */*; q=0.01',
19 | 'accept-language': 'zh-CN,zh;q=0.9',
20 | 'user-agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/103.0.0.0 Safari/537.36',
21 | 'x-requested-with': 'XMLHttpRequest',
22 | }
23 | data = {
24 | 'page': page,
25 | }
26 | response = requests.post('https://www.python-spider.com/api/challenge57', headers=headers, data=data)
27 | return response.json()
28 |
29 |
30 | def get_data_list(result):
31 | ctx = Utils(js_file_name='demo.js').read_js_file()
32 | return ctx.call('get_data_list', result)
33 |
34 |
35 | if __name__ == '__main__':
36 | # 答案: 5153708
37 | count = 0
38 | for page in range(1, 101):
39 | results = get_results(page)
40 | data_List = get_data_list(results['result'])
41 | for data in data_List:
42 | count += int(str(data['value']).strip())
43 | logger.info(f' 前 {page} 页数字相加之和为: {count}')
44 |
--------------------------------------------------------------------------------
/yuanrenxue/topic58/__init__.py:
--------------------------------------------------------------------------------
1 | # _*_ coding: utf-8 _*_
2 | # @Date: 11:22 上午
3 | # @File: __init__.py.py
4 | # @Author: liyf
5 |
--------------------------------------------------------------------------------
/yuanrenxue/topic58/demo.py:
--------------------------------------------------------------------------------
1 | # _*_ coding: utf-8 _*_
2 | # @Date: 11:23 上午
3 | # @File: demo.py
4 | # @Author: liyf
5 |
6 | """
7 | post请求中的 token 参数破解
8 | 对 页码 进行md5加密,并取16位
9 | """
10 | import hashlib
11 | import requests
12 |
13 | from loguru import logger
14 |
15 |
16 | def get_page_md5(page: str):
17 | md5 = hashlib.md5()
18 | md5.update(page.encode('utf8'))
19 | return md5.hexdigest()[8:-8].lower()
20 |
21 |
22 | def get_html(page):
23 | headers = {
24 | 'authority': 'www.python-spider.com',
25 | 'accept': 'application/json, text/javascript, */*; q=0.01',
26 | 'accept-language': 'zh-CN,zh;q=0.9',
27 | 'origin': 'https://www.python-spider.com',
28 | 'referer': 'https://www.python-spider.com/challenge/58',
29 | 'user-agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/103.0.0.0 Safari/537.36',
30 | 'x-requested-with': 'XMLHttpRequest',
31 | }
32 | data = {
33 | 'page': page,
34 | 'token': get_page_md5(str(page)),
35 | }
36 | response = requests.post('https://www.python-spider.com/api/challenge58', headers=headers, data=data)
37 | return response.json()
38 |
39 |
40 | def get_total_res_sum():
41 | count = 0
42 | for page in range(1, 101):
43 | results = get_html(page)
44 | for res in results['data']:
45 | count += int(str(res['value']).strip())
46 | logger.info(f'前 {page} 页之和为: {count}')
47 |
48 |
49 | if __name__ == '__main__':
50 | # 答案: 4994898
51 | get_total_res_sum()
52 |
--------------------------------------------------------------------------------
/yuanrenxue/topic60/__init__.py:
--------------------------------------------------------------------------------
1 | # _*_ coding: utf-8 _*_
2 | # @Date: 2:17 下午
3 | # @File: __init__.py.py
4 | # @Author: liyf
5 |
--------------------------------------------------------------------------------
/yuanrenxue/topic60/demo.js:
--------------------------------------------------------------------------------
1 | var CryptoJS = require('crypto-js')
2 |
3 | // 3DES加密,page必须为字符串
4 | function get_data(page) {
5 | var d = CryptoJS.enc.Utf8.parse('aiding88'),
6 | D = CryptoJS.TripleDES.encrypt(page, d, {
7 | 'mode': CryptoJS.mode.ECB,
8 | 'padding': CryptoJS.pad.Pkcs7
9 | })
10 | return D.toString()
11 | }
12 |
--------------------------------------------------------------------------------
/yuanrenxue/topic60/demo.py:
--------------------------------------------------------------------------------
1 | # _*_ coding: utf-8 _*_
2 | # @Date: 2:42 下午
3 | # @File: demo.py
4 | # @Author: liyf
5 |
6 | """
7 | 3DES加密
8 | ECB模式,Pkcs7填充方式
9 | """
10 | import requests
11 |
12 | from utils import *
13 |
14 |
15 | def get_results(page):
16 | headers = {
17 | 'authority': 'www.python-spider.com',
18 | 'accept': 'application/json, text/javascript, */*; q=0.01',
19 | 'accept-language': 'zh-CN,zh;q=0.9',
20 | 'user-agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/103.0.0.0 Safari/537.36',
21 | 'x-requested-with': 'XMLHttpRequest',
22 | }
23 | data = {
24 | 'page': page,
25 | }
26 | des_data = get_jiami(page)
27 | url = f'https://www.python-spider.com/api/challenge60/{des_data}'
28 | response = requests.post(url, headers=headers, data=data)
29 | return response.json()
30 |
31 |
32 | def get_jiami(page):
33 | ctx = Utils(js_file_name='demo.js').read_js_file()
34 | return ctx.call('get_data', page)
35 |
36 |
37 | def parse():
38 | count = 0
39 | for page in range(1, 101):
40 | results = get_results(str(page))
41 | data_list = results['data']
42 | for data in data_list:
43 | count += int(str(data['value']).strip())
44 | logger.info(f'前 {page} 页之和为: {count}')
45 | logger.info(f'本题答案为: {count}') # 本题答案为: 5004204
46 |
47 |
48 | if __name__ == '__main__':
49 | parse()
50 |
--------------------------------------------------------------------------------
/yuanrenxue/wangluozhe2/__init__.py:
--------------------------------------------------------------------------------
1 | # _*_ coding: utf-8 _*_
2 | # @Date: 10:44 上午
3 | # @File: __init__.py.py
4 | # @Author: liyf
5 |
--------------------------------------------------------------------------------
/yuanrenxue/wangluozhe2/demo.js:
--------------------------------------------------------------------------------
1 | var hexcase = 0;
2 |
3 | function hex_sha1(s) {
4 | return binb2hex(core_sha1(AlignSHA1(s)));
5 | }
6 |
7 | function core_sha1(blockArray) {
8 | var x = blockArray;
9 | var w = Array(80);
10 | var a = 1732584173;
11 | var b = -271733877;
12 | var c = -1752584194;
13 | var d = 271733878;
14 | var e = -1009589776;
15 | for (var i = 0; i < x.length; i += 16) {
16 | var olda = a;
17 | var oldb = b;
18 | var oldc = c;
19 | var oldd = d;
20 | var olde = e;
21 | for (var j = 0; j < 80; j++) {
22 | if (j < 16)
23 | w[j] = x[i + j];
24 | else
25 | w[j] = rol(w[j - 3] ^ w[j - 8] ^ w[j - 14] ^ w[j - 16], 1);
26 | var t = safe_add(safe_add(rol(a, 5), sha1_ft(j, b, c, d)), safe_add(safe_add(e, w[j]), sha1_kt(j)));
27 | e = d;
28 | d = c;
29 | c = rol(b, 30);
30 | b = a;
31 | a = t;
32 | }
33 | a = safe_add(a, olda);
34 | b = safe_add(b, oldb);
35 | c = safe_add(c, oldc);
36 | d = safe_add(d, oldd);
37 | e = safe_add(e, olde);
38 | }
39 | return new Array(a, b, c, d, e);
40 | }
41 |
42 | function sha1_ft(t, b, c, d) {
43 | if (t < 20) {
44 | return (b & c) | ((~b) & d);
45 | }
46 | if (t < 40) {
47 | return b ^ c ^ d;
48 | }
49 | if (t < 60) {
50 | return (b & c) | (b & d) | (c & d);
51 | }
52 | return b ^ c ^ d;
53 | }
54 |
55 | function sha1_kt(t) {
56 | return (t < 20) ? 1518500249 : (t < 40) ? 1859775393 : (t < 60) ? -1894007588 : -899497514;
57 | }
58 |
59 | function safe_add(x, y) {
60 | var lsw = (x & 0xFFFF) + (y & 0xFFFF);
61 | var msw = (x >> 16) + (y >> 16) + (lsw >> 16);
62 | return (msw << 16) | (lsw & 0xFFFF);
63 | }
64 |
65 | function rol(num, cnt) {
66 | return (num << cnt) | (num >>> (32 - cnt));
67 | }
68 |
69 | function AlignSHA1(str) {
70 | var nblk = ((str.length + 8) >> 6) + 1;
71 | var blks = new Array(nblk * 16);
72 | for (var i = 0; i < nblk * 16; i++) {
73 | blks[i] = 0;
74 | }
75 | for (i = 0; i < str.length; i++) {
76 | blks[i >> 2] |= str.charCodeAt(i) << (24 - (i & 3) * 8);
77 | }
78 | blks[i >> 2] |= 0x80 << (24 - (i & 3) * 8);
79 | blks[nblk * 16 - 1] = str.length * 8;
80 | return blks;
81 | }
82 |
83 | function binb2hex(binarray) {
84 | var hex_tab = hexcase ? "0123456789ABCDEF" : "0123456789abcdef";
85 | var str = "";
86 | for (var i = 0; i < binarray.length * 4; i++) {
87 | str += hex_tab.charAt((binarray[i >> 2] >> ((3 - i % 4) * 8 + 4)) & 0xF) + hex_tab.charAt((binarray[i >> 2] >> ((3 - i % 4) * 8)) & 0xF);
88 | }
89 | return str;
90 | }
91 |
92 | function get_signature() {
93 | var sign = hex_sha1(Date.parse(new Date).toString());
94 | return sign
95 | }
96 |
--------------------------------------------------------------------------------
/yuanrenxue/wangluozhe2/demo.py:
--------------------------------------------------------------------------------
1 | # _*_ coding: utf-8 _*_
2 | # @Date: 10:55 上午
3 | # @File: demo.py
4 | # @Author: liyf
5 |
6 | import requests
7 |
8 | from utils import *
9 |
10 | ctx = Utils(js_file_name='demo.js').read_js_file()
11 | headers = {
12 | "authority": "wangluozhe.com",
13 | "accept": "application/json, text/javascript, */*; q=0.01",
14 | "accept-language": "zh-CN,zh;q=0.9",
15 | "content-type": "application/x-www-form-urlencoded; charset=UTF-8",
16 | "user-agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.0.0 Safari/537.36",
17 | "x-requested-with": "XMLHttpRequest"
18 | }
19 | cookies = {
20 | "session": "21ccbbfc-d378-446a-9ab3-335d00344df0.08Ft_EA-0fD2Ae6LYWysllGyZTA",
21 | }
22 |
23 |
24 | def get_signature():
25 | signature = ctx.call('get_signature')
26 | return signature
27 |
28 |
29 | def get_results(page):
30 | url = "https://wangluozhe.com/challenge/api/2"
31 | signature = get_signature()
32 | logger.info(f'第{page}页, signature: {signature}')
33 | data = {
34 | "page": str(page),
35 | "count": "10",
36 | "_signature": signature
37 | }
38 | response = requests.post(url, headers=headers, cookies=cookies, data=data)
39 | return response.json()
40 |
41 |
42 | def main():
43 | count = 0
44 | for page in range(1, 101):
45 | results = get_results(page)
46 | page_count = sum(res['value'] for res in results['data'])
47 | count += page_count
48 | logger.info(f'前{page}页之和为: {count}') # 答案为: 5186861
49 |
50 |
51 | if __name__ == '__main__':
52 | main()
53 |
--------------------------------------------------------------------------------
/yuanrenxue/wangluozhe3/__init__.py:
--------------------------------------------------------------------------------
1 | # _*_ coding: utf-8 _*_
2 | # @Date: 11:06 上午
3 | # @File: __init__.py.py
4 | # @Author: liyf
5 |
--------------------------------------------------------------------------------
/yuanrenxue/wangluozhe3/demo.js:
--------------------------------------------------------------------------------
1 | var CryptoJS = require('crypto-js');
2 |
3 | function encryptByDES(message, key) {
4 | var keyHex = CryptoJS.enc.Utf8.parse(key);
5 | var encrypted = CryptoJS.DES.encrypt(message, keyHex, {
6 | mode: CryptoJS.mode.ECB,
7 | padding: CryptoJS.pad.Pkcs7
8 | });
9 | return encrypted.ciphertext.toString();
10 | }
11 |
12 | function get_signature() {
13 | var message = 'https://wangluozhe.com/challenge/3';
14 | message = message + '|' + Date.parse(new Date()).toString();
15 | var key = Date.parse(new Date()).toString(),
16 | sign = encryptByDES(message, key);
17 | return sign
18 | }
--------------------------------------------------------------------------------
/yuanrenxue/wangluozhe3/demo.py:
--------------------------------------------------------------------------------
1 | # _*_ coding: utf-8 _*_
2 | # @Date: 11:12 上午
3 | # @File: demo.py
4 | # @Author: liyf
5 | import requests
6 |
7 | from utils import *
8 |
9 | ctx = Utils(js_file_name='demo.js').read_js_file()
10 |
11 | headers = {
12 | "authority": "wangluozhe.com",
13 | "accept": "application/json, text/javascript, */*; q=0.01",
14 | "accept-language": "zh-CN,zh;q=0.9",
15 | "content-type": "application/x-www-form-urlencoded; charset=UTF-8",
16 | "user-agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.0.0 Safari/537.36",
17 | "x-requested-with": "XMLHttpRequest"
18 | }
19 | cookies = {
20 | "session": "21ccbbfc-d378-446a-9ab3-335d00344df0.08Ft_EA-0fD2Ae6LYWysllGyZTA",
21 | }
22 |
23 |
24 | def get_signature():
25 | signature = ctx.call('get_signature')
26 | return signature
27 |
28 |
29 | def get_results(page):
30 | url = "https://wangluozhe.com/challenge/api/3"
31 | signature = get_signature()
32 | logger.info(f'第{page}页, signature: {signature}')
33 | data = {
34 | "page": str(page),
35 | "count": "10",
36 | "_signature": signature
37 | }
38 | response = requests.post(url, headers=headers, cookies=cookies, data=data)
39 | return response.json()
40 |
41 |
42 | def main():
43 | count = 0
44 | for page in range(1, 101):
45 | results = get_results(page)
46 | page_count = sum(res['value'] for res in results['data'])
47 | count += page_count
48 | logger.info(f'前{page}页之和为: {count}') # 答案为: 5022790
49 |
50 |
51 | if __name__ == '__main__':
52 | main()
53 |
--------------------------------------------------------------------------------
/yuanrenxue/wangluozhe4/__init__.py:
--------------------------------------------------------------------------------
1 | # _*_ coding: utf-8 _*_
2 | # @Date: 11:15 上午
3 | # @File: __init__.py.py
4 | # @Author: liyf
5 |
--------------------------------------------------------------------------------
/yuanrenxue/wangluozhe4/demo.js:
--------------------------------------------------------------------------------
1 | window = global;
2 |
3 | var CryptoJS = require('crypto-js');
4 | let date = Date.parse(new Date()),
5 | key_tmp = date * 1234,
6 | iv_tmp = date * 4321,
7 | key = CryptoJS.enc.Utf8.parse(key_tmp),
8 | iv = CryptoJS.enc.Utf8.parse(iv_tmp);
9 | (function tmp(date, key, iv) {
10 | function Encrypt(word) {
11 | let srcs = CryptoJS.enc.Utf8.parse(word);
12 | let encrypted = CryptoJS.AES.encrypt(srcs, key, {
13 | iv: iv,
14 | mode: CryptoJS.mode.CBC,
15 | padding: CryptoJS.pad.Pkcs7
16 | });
17 | return encrypted.ciphertext.toString().toUpperCase();
18 | }
19 |
20 | window.sign = Encrypt(date);
21 | })(date, key, iv);
22 |
23 | function get_signature(){
24 | return window.sign
25 | }
--------------------------------------------------------------------------------
/yuanrenxue/wangluozhe4/demo.py:
--------------------------------------------------------------------------------
1 | # _*_ coding: utf-8 _*_
2 | # @Date: 11:23 上午
3 | # @File: demo.py
4 | # @Author: liyf
5 | import requests
6 |
7 | from utils import *
8 |
9 | ctx = Utils(js_file_name='demo.js').read_js_file()
10 |
11 | headers = {
12 | "authority": "wangluozhe.com",
13 | "accept": "application/json, text/javascript, */*; q=0.01",
14 | "accept-language": "zh-CN,zh;q=0.9",
15 | "content-type": "application/x-www-form-urlencoded; charset=UTF-8",
16 | "user-agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.0.0 Safari/537.36",
17 | "x-requested-with": "XMLHttpRequest"
18 | }
19 | cookies = {
20 | "session": "21ccbbfc-d378-446a-9ab3-335d00344df0.08Ft_EA-0fD2Ae6LYWysllGyZTA",
21 | }
22 |
23 |
24 | def get_signature():
25 | signature = ctx.call('get_signature')
26 | return signature
27 |
28 |
29 | def get_results(page):
30 | url = "https://wangluozhe.com/challenge/api/4"
31 | signature = get_signature()
32 | logger.info(f'第{page}页, signature: {signature}')
33 | data = {
34 | "page": str(page),
35 | "count": "10",
36 | "_signature": signature
37 | }
38 | response = requests.post(url, headers=headers, cookies=cookies, data=data)
39 | return response.json()
40 |
41 |
42 | def main():
43 | count = 0
44 | for page in range(1, 101):
45 | results = get_results(page)
46 | page_count = sum(res['value'] for res in results['data'])
47 | count += page_count
48 | logger.info(f'前{page}页之和为: {count}') # 答案为: 5042028
49 |
50 |
51 | if __name__ == '__main__':
52 | main()
53 |
--------------------------------------------------------------------------------
/zbcg_sznsyy/__init__.py:
--------------------------------------------------------------------------------
1 | # _*_ coding: utf-8 _*_
2 | # @Date: 10:16 上午
3 | # @File: __init__.py.py
4 | # @Author: liyf
5 |
6 |
--------------------------------------------------------------------------------
/zyfuw/__init__.py:
--------------------------------------------------------------------------------
1 | # _*_ coding: utf-8 _*_
2 | # @Date: 5:36 下午
3 | # @File: __init__.py.py
4 | # @Author: liyf
5 |
--------------------------------------------------------------------------------
/zyfuw/demo.js:
--------------------------------------------------------------------------------
1 | var CryptoJS = require('crypto-js')
2 |
3 | function get_detail_url(hh) {
4 | var s = 'qnbyzzwmdgghmcnm';
5 | var aa = hh.split("/");
6 | var aaa = aa.length;
7 | var bbb = aa[aaa - 1].split('.');
8 | var ccc = bbb[0];
9 | var cccc = bbb[1];
10 | var r = /^\+?[1-9][0-9]*$/;
11 | if (r.test(ccc) && cccc.indexOf('jhtml') != -1) {
12 | var srcs = CryptoJS.enc.Utf8.parse(ccc);
13 | var k = CryptoJS.enc.Utf8.parse(s);
14 | var en = CryptoJS.AES.encrypt(srcs, k, {
15 | mode: CryptoJS.mode.ECB,
16 | padding: CryptoJS.pad.Pkcs7
17 | });
18 | var ddd = en.toString();
19 | ddd = ddd.replace(/\//g, "^");
20 | ddd = ddd.substring(0, ddd.length - 2);
21 | var bbbb = ddd + '.' + bbb[1];
22 | aa[aaa - 1] = bbbb;
23 | var uuu = '';
24 | for (i = 0; i < aaa; i++) {
25 | uuu += aa[i] + '/'
26 | }
27 | uuu = uuu.substring(0, uuu.length - 1);
28 | console.log(uuu)
29 | return uuu
30 | }
31 | }
32 |
33 | get_detail_url('http://ggzy.zwfwb.tj.gov.cn:80/jyxxcgjg/992535.jhtml')
34 |
--------------------------------------------------------------------------------
/zyfuw/demo.py:
--------------------------------------------------------------------------------
1 | # _*_ coding: utf-8 _*_
2 | # @Date: 5:38 下午
3 | # @File: demo.py
4 | # @Author: liyf
5 | import requests
6 |
7 | from lxml import etree
8 |
9 | from utils import *
10 |
11 |
12 | def get_html(url):
13 | headers = {
14 | 'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9',
15 | 'Accept-Language': 'zh-CN,zh;q=0.9',
16 | 'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/106.0.0.0 Safari/537.36',
17 | 'Host': 'ggzy.zwfwb.tj.gov.cn',
18 | 'Accept-Encoding': 'gzip, deflate',
19 | 'Cookie': 'clientlanguage=zh_CN; JSESSIONID=B2C036872F09FB3066BC1E1D71CF6D69'
20 | }
21 |
22 | response = requests.get(url, headers=headers, verify=False)
23 | return response
24 |
25 |
26 | def get_index_url(url):
27 | response = get_html(url)
28 | if response.status_code != 200:
29 | print(f'状态码: {response.status_code}, 重新请求: {url}')
30 | get_index_url(url)
31 | html = response.text
32 | response = etree.HTML(html)
33 | li_list = response.xpath('//ul[@class="article-list2"]/li')
34 | for li in li_list:
35 | index_url = li.xpath('div/a/@url')[0]
36 | span_list = li.xpath('div/a//text()')
37 | title = ''.join(span_list).strip()
38 | get_detail_url(index_url, title)
39 |
40 |
41 | def get_detail_url(index_url, title):
42 | ctx = Utils(js_file_name='demo.js').read_js_file()
43 | detail_url = ctx.call('get_detail_url', index_url)
44 | item = {
45 | 'url': detail_url,
46 | 'title': title
47 | }
48 | print(item)
49 |
50 |
51 | if __name__ == '__main__':
52 | for page in range(1, 10):
53 | # http://ggzy.zwfwb.tj.gov.cn/jyxx/index_1.jhtml
54 | url = f'http://ggzy.zwfwb.tj.gov.cn/jyxx/index_{page}.jhtml'
55 | get_index_url(url)
56 | # break
57 |
--------------------------------------------------------------------------------