├── .gitignore ├── README.md └── demo.py /.gitignore: -------------------------------------------------------------------------------- 1 | # Created by .ignore support plugin (hsz.mobi) 2 | ### JetBrains template 3 | # Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio and WebStorm 4 | # Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839 5 | 6 | # User-specific stuff 7 | .idea/**/workspace.xml 8 | .idea/**/tasks.xml 9 | .idea/**/usage.statistics.xml 10 | .idea/**/dictionaries 11 | .idea/**/shelf 12 | 13 | # Generated files 14 | .idea/**/contentModel.xml 15 | 16 | # Sensitive or high-churn files 17 | .idea/**/dataSources/ 18 | .idea/**/dataSources.ids 19 | .idea/**/dataSources.local.xml 20 | .idea/**/sqlDataSources.xml 21 | .idea/**/dynamic.xml 22 | .idea/**/uiDesigner.xml 23 | .idea/**/dbnavigator.xml 24 | 25 | # Gradle 26 | .idea/**/gradle.xml 27 | .idea/**/libraries 28 | 29 | # Gradle and Maven with auto-import 30 | # When using Gradle or Maven with auto-import, you should exclude module files, 31 | # since they will be recreated, and may cause churn. Uncomment if using 32 | # auto-import. 33 | # .idea/artifacts 34 | # .idea/compiler.xml 35 | # .idea/modules.xml 36 | # .idea/*.iml 37 | # .idea/modules 38 | # *.iml 39 | # *.ipr 40 | 41 | # CMake 42 | cmake-build-*/ 43 | 44 | # Mongo Explorer plugin 45 | .idea/**/mongoSettings.xml 46 | 47 | # File-based project format 48 | *.iws 49 | 50 | # IntelliJ 51 | out/ 52 | 53 | # mpeltonen/sbt-idea plugin 54 | .idea_modules/ 55 | 56 | # JIRA plugin 57 | atlassian-ide-plugin.xml 58 | 59 | # Cursive Clojure plugin 60 | .idea/replstate.xml 61 | 62 | # Crashlytics plugin (for Android Studio and IntelliJ) 63 | com_crashlytics_export_strings.xml 64 | crashlytics.properties 65 | crashlytics-build.properties 66 | fabric.properties 67 | 68 | # Editor-based Rest Client 69 | .idea/httpRequests 70 | 71 | # Android studio 3.1+ serialized cache file 72 | .idea/caches/build_file_checksums.ser 73 | 74 | ### Python template 75 | # Byte-compiled / optimized / DLL files 76 | __pycache__/ 77 | *.py[cod] 78 | *$py.class 79 | 80 | # C extensions 81 | *.so 82 | 83 | # Distribution / packaging 84 | .Python 85 | build/ 86 | develop-eggs/ 87 | dist/ 88 | downloads/ 89 | eggs/ 90 | .eggs/ 91 | lib/ 92 | lib64/ 93 | parts/ 94 | sdist/ 95 | var/ 96 | wheels/ 97 | pip-wheel-metadata/ 98 | share/python-wheels/ 99 | *.egg-info/ 100 | .installed.cfg 101 | *.egg 102 | MANIFEST 103 | 104 | # PyInstaller 105 | # Usually these files are written by a python script from a template 106 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 107 | *.manifest 108 | *.spec 109 | 110 | # Installer logs 111 | pip-log.txt 112 | pip-delete-this-directory.txt 113 | 114 | # Unit test / coverage reports 115 | htmlcov/ 116 | .tox/ 117 | .nox/ 118 | .coverage 119 | .coverage.* 120 | .cache 121 | nosetests.xml 122 | coverage.xml 123 | *.cover 124 | *.py,cover 125 | .hypothesis/ 126 | .pytest_cache/ 127 | 128 | # Translations 129 | *.mo 130 | *.pot 131 | 132 | # Django stuff: 133 | *.log 134 | local_settings.py 135 | db.sqlite3 136 | db.sqlite3-journal 137 | 138 | # Flask stuff: 139 | instance/ 140 | .webassets-cache 141 | 142 | # Scrapy stuff: 143 | .scrapy 144 | 145 | # Sphinx documentation 146 | docs/_build/ 147 | 148 | # PyBuilder 149 | target/ 150 | 151 | # Jupyter Notebook 152 | .ipynb_checkpoints 153 | 154 | # IPython 155 | profile_default/ 156 | ipython_config.py 157 | 158 | # pyenv 159 | .python-version 160 | 161 | # pipenv 162 | # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. 163 | # However, in case of collaboration, if having platform-specific dependencies or dependencies 164 | # having no cross-platform support, pipenv may install dependencies that don't work, or not 165 | # install all needed dependencies. 166 | #Pipfile.lock 167 | 168 | # PEP 582; used by e.g. github.com/David-OConnor/pyflow 169 | __pypackages__/ 170 | 171 | # Celery stuff 172 | celerybeat-schedule 173 | celerybeat.pid 174 | 175 | # SageMath parsed files 176 | *.sage.py 177 | 178 | # Environments 179 | .env 180 | .venv 181 | env/ 182 | venv/ 183 | ENV/ 184 | env.bak/ 185 | venv.bak/ 186 | 187 | # Spyder project settings 188 | .spyderproject 189 | .spyproject 190 | 191 | # Rope project settings 192 | .ropeproject 193 | 194 | # mkdocs documentation 195 | /site 196 | 197 | # mypy 198 | .mypy_cache/ 199 | .dmypy.json 200 | dmypy.json 201 | 202 | # Pyre type checker 203 | .pyre/ 204 | 205 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ### 2020-04-23更新 2 | ciphertext加密,result解密。 3 | 为防止滥用,HM4hUBT0dDOn80T生成代码暂不公开,考虑后续适时公开。 4 | 现有接口仅供测试,不可用于非法目的。 5 | -------------------------------------------------------------------------------- /demo.py: -------------------------------------------------------------------------------- 1 | # coding:utf-8 2 | import json 3 | import time 4 | import random 5 | import base64 6 | import datetime 7 | 8 | 9 | import requests 10 | from lxml import etree 11 | from Crypto.Cipher import DES3 12 | from Crypto.Util.Padding import pad, unpad 13 | 14 | 15 | class Des(object): 16 | 17 | @staticmethod 18 | def encrypt(text, key): 19 | text = pad(text.encode(), DES3.block_size) 20 | iv = datetime.datetime.now().strftime('%Y%m%d').encode() 21 | cryptor = DES3.new(key, DES3.MODE_CBC, iv) 22 | x = len(text) % 8 23 | ciphertext = cryptor.encrypt(text) 24 | return base64.b64encode(ciphertext).decode("utf-8") 25 | 26 | @staticmethod 27 | def decrypt(text, key): 28 | iv = datetime.datetime.now().strftime('%Y%m%d').encode() 29 | cryptor = DES3.new(key, DES3.MODE_CBC, iv) 30 | de_text = base64.b64decode(text) 31 | plain_text = cryptor.decrypt(de_text) 32 | out = unpad(plain_text, DES3.block_size) 33 | return out.decode() 34 | 35 | 36 | class Demo(object): 37 | 38 | def __init__(self, api, cookie=''): 39 | self.api = api 40 | self.cookie = cookie 41 | 42 | def make_ciphertext(self): 43 | timestamp = str(int(time.time() * 1000)) 44 | salt = ''.join([random.choice('0123456789qwertyuiopasdfghjklzxcvbnm') for _ in range(24)]) 45 | iv = datetime.datetime.now().strftime('%Y%m%d') 46 | des = Des() 47 | enc = des.encrypt(timestamp, salt) 48 | strs = salt + iv + enc 49 | result = [] 50 | for i in strs: 51 | result.append(bin(ord(i))[2:]) 52 | result.append(' ') 53 | return ''.join(result[:-1]) 54 | 55 | def start_page(self): 56 | headers = { 57 | "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.149 Safari/537.36", 58 | } 59 | url = 'http://wenshu.court.gov.cn/website/wenshu/181217BMTKHNT2W0/index.html' 60 | with requests.get(url, headers=headers) as req: 61 | req.raise_for_status() 62 | cookie_80s = req.cookies.get('HM4hUBT0dDOn80S') 63 | assert cookie_80s, '文书网异常,80s获取失败' 64 | html = req.text 65 | root = etree.HTML(html) 66 | meta = root.xpath('//meta[last()]/@content')[0] 67 | js_txt = root.xpath('//script[@r="m"]/text()')[0] 68 | with requests.post(self.api, json={'meta': meta, 'js_txt': js_txt}) as req: 69 | req.raise_for_status() 70 | cookie_80t = req.json()['cookie'] 71 | assert cookie_80t, '80t生成失败' 72 | print(cookie_80t) 73 | self.cookie = f'HM4hUBT0dDOn80S={cookie_80s};HM4hUBT0dDOn80T={cookie_80t};HM4hUBT0dDOnenable=true' 74 | 75 | def get_list(self): 76 | assert self.cookie, '没有正确生成cookie' 77 | headers = { 78 | 'Cookie': self.cookie, 79 | "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.132 Safari/537.36", 80 | } 81 | 82 | token = ''.join([random.choice('0123456789qwertyuiopasdfghjklzxcvbnm') for _ in range(24)]) 83 | post_data = { 84 | 'sortFields': 's50:desc', 85 | 'ciphertext': self.make_ciphertext(), 86 | 'pageNum': 1, 87 | 'pageSize': 5, 88 | 'queryCondition': '[{"key":"s42","value":"2020"}]', 89 | 'cfg': 'com.lawyee.judge.dc.parse.dto.SearchDataDsoDTO@queryDoc', 90 | '__RequestVerificationToken': token, 91 | } 92 | url = 'http://wenshu.court.gov.cn/website/parse/rest.q4w' 93 | with requests.post(url, headers=headers, data=post_data) as req: 94 | req.raise_for_status() 95 | assert req.text, "文书网接口异常" 96 | result = Des.decrypt(req.json()['result'], req.json()['secretKey']) 97 | print(result) 98 | first_doc_id = json.loads(result)['queryResult']['resultList'][0]['rowkey'] 99 | self.get_info(first_doc_id) 100 | 101 | def get_info(self, doc_id): 102 | print('-------详情页-------') 103 | headers = { 104 | 'Cookie': self.cookie, 105 | "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.132 Safari/537.36", 106 | } 107 | 108 | token = ''.join([random.choice('0123456789qwertyuiopasdfghjklzxcvbnm') for _ in range(24)]) 109 | post_data = { 110 | 'docId': doc_id, 111 | 'ciphertext': self.make_ciphertext(), 112 | 'cfg': 'com.lawyee.judge.dc.parse.dto.SearchDataDsoDTO@docInfoSearch', 113 | '__RequestVerificationToken': token, 114 | } 115 | url = 'http://wenshu.court.gov.cn/website/parse/rest.q4w' 116 | with requests.post(url, headers=headers, data=post_data) as req: 117 | req.raise_for_status() 118 | assert req.text, "文书网接口异常" 119 | print(req.text) 120 | result = Des.decrypt(req.json()['result'], req.json()['secretKey']) 121 | print(result) 122 | 123 | 124 | if __name__ == '__main__': 125 | api = 'http://118.24.27.218:8012/wenshu' 126 | sss = Demo(api=api) 127 | sss.start_page() 128 | sss.get_list() 129 | --------------------------------------------------------------------------------