├── .gitignore ├── LICENSE ├── README.md ├── composer.json ├── demo ├── 0_simpleAutoLogin.php ├── 10_zhihulogin.php ├── 11_cnblogLogin │ ├── 11_cnbloglogin.php │ ├── jsencrypt.min.js │ └── nodeServer.cnblogLogin.js ├── 12_zuocheWithCaptcha.php ├── 14_360doc.php ├── 15_downloadWizNote.php ├── 16_commonCurl │ ├── code.png │ ├── curlPage.cookie.txt │ └── curlPage.php ├── 17_dev.360.cn_STDINCaptcha.php ├── 19_www.tianyancha.com.php ├── 1_simpleAutoLogin.php ├── 20_u.mumayi.com_OnlineCaptcha.php ├── 22_tools.cnforex.com-phantomjs-parse-js.php ├── 26_publish.haodanku.com.php ├── 2_wxqq.php ├── 34_www.aliwx.com.cn │ ├── 34_www.aliwx.com.cn.js │ ├── 34_www.aliwx.com.cn.php │ └── books │ │ └── .gitignore ├── 38_upload.otar.im_image_upload.php ├── 3_preloadCookieAndVisit.php ├── 41_cli.im.php ├── 48_request_repeat.php ├── 49_format_cookie.php ├── 61_tophub.today.php ├── 62_curlmulti │ ├── .gitignore │ ├── 62_wiz.cn.php │ ├── cache │ │ └── .gitignore │ └── composer.json ├── 7_cnki.net.php ├── 8_webqq.php ├── parseCurlCode │ └── .gitignore └── parseCurlGetPhpCode.php ├── images ├── get-curl-text.png └── php-curl-qrcode.png ├── logs └── .htaccess ├── phpunit.xml └── src └── CurlAutoLogin.php /.gitignore: -------------------------------------------------------------------------------- 1 | vendor/ 2 | logs/*.log 3 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "{}" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright {yyyy} {name of copyright owner} 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # php-curl 2 | PHP利用cURL实现模拟登录与采集,提供大量示例。(关键词:php curl login) 3 | 4 | 了解PHP cURL使用请参考:《[PHP cURL实现模拟登录与采集使用方法详解](http://www.zjmainstay.cn/php-curl)》 5 | 6 | 基于浏览器cURL命令快速生成PHP代码:[基于cURL命令解析获得PHP代码](http://demo.zjmainstay.cn/php/github/php-curl/demo/parseCurlGetPhpCode.php) 7 | 8 | 自动模拟登录+批量请求示例:[模拟登录后批量下载笔记](https://github.com/Zjmainstay/php-curl/blob/master/demo/62_curlmulti/62_wiz.cn.php) 9 | 10 | ## 依赖 11 | 12 | PHP: >=5.4 13 | 14 | ## 单独使用 15 | 16 | ```php 17 | git clone https://github.com/Zjmainstay/php-curl.git 18 | cd php-curl 19 | composer install 20 | #测试 21 | php demo/1_simpleAutoLogin.php 22 | ``` 23 | 24 | ## composer引入 25 | 26 | ```php 27 | composer require zjmainstay/php-curl 28 | 29 | #测试 30 | cd vendor/zjmainstay/php-curl 31 | composer install 32 | php demo/1_simpleAutoLogin.php 33 | ``` 34 | 35 | ## 直接引入类 36 | 37 | ```php 38 | require_once __DIR__.'/../src/CurlAutoLogin.php'; # 使用时注意路径 39 | $autologin = new PHPCurl\CurlAutoLogin(); 40 | 41 | # 参考demo/0_simpleAutoLogin.php 42 | ``` 43 | 44 | 45 | 46 | ## CurlAutoLogin 介绍 47 | 48 | ### 属性 49 | 50 | ```php 51 | //最后一次cookie存储文件 52 | protected $lastCookieFile = ''; 53 | //登录成功后,锁定cookie的更新 54 | protected $lockedLastCookieFile = false; 55 | //日志路径 56 | protected $logPath = ''; 57 | //全局opt,方便使用代理之类的请求 58 | protected $globalOpts = []; 59 | //最后一次请求参数,用于重放请求 60 | protected $lastExecParams = []; 61 | ``` 62 | 63 | ### 方法 64 | 65 | ```php 66 | // ================== 1.常用方法 ================== 67 | //根据curl信息执行并解析结果,核心方法常用方法之一 68 | public function execCurl($curlContent, $callbackBefore = false, $callbackAfter = false, $storeParams = true) 69 | 70 | //携带cookie执行curl命令,核心方法常用方法之一,直接利用curl命令里的header头cookie参数 71 | public function execCurlWithCookie($curlContent, $callbackBefore = false, $callbackAfter = false) 72 | 73 | // ================== 2.普通公用方法 ================== 74 | //设置全局请求opt(方便使用代理之类的请求) 75 | public function setGlobalOpts($opts = []) 76 | 77 | //重放请求,依赖登录的场景出现登录失败的情况,重新登录后,调用此方法重试上一次的请求 78 | public function repeatRequest() 79 | 80 | //获取最后一次请求参数,用于重放请求 81 | public function getLastExecParams() 82 | 83 | //主动销毁最后一次请求参数 84 | public function unsetLastExecParams() 85 | 86 | //解析curl信息,返回结果包含url/header/post/opt/cookie,post是post提交的数据,opt是curl备用扩展 87 | public function parseCurl($curlContent) 88 | 89 | //设置日志路径 90 | public function setLogPath($logPath) 91 | 92 | //获取上一次存储cookie的文件 93 | public function getLastCookieFile() 94 | 95 | //获取最后一次存储的cookie内容 96 | public function getLastCookieContent() 97 | 98 | //手动追加cookie内容到最后一次存储的cookie文件 99 | public function appendCookieContent($content) 100 | 101 | //设置上一次存储cookie的文件 102 | public function setLastCookieFile($cookieFile) 103 | 104 | //清空上次存储的cookie 105 | public function removeLastCookie() 106 | 107 | //登录成功后,锁定上一次存储cookie的文件,避免覆盖 108 | public function lockLastCookieFile() 109 | 110 | //解锁上一次存储cookie的文件 111 | public function unlockLastCookieFile() 112 | 113 | //登录成功后,锁定cookie,可以基于get方式获取url信息 114 | public function getUrl($url, $header = false) 115 | 116 | //登录成功后,锁定cookie,可以基于post方式获取url信息 117 | public function postUrl($url, $postData = false, $header = false) 118 | 119 | //断言内容中包含某个字符(判断登录信息,如“退出”字眼) 120 | public function assertContainStr($content, $substr) 121 | 122 | //获取换行符,用于输出信息显示换行 123 | public function getLineBreak() 124 | 125 | //格式化header头cookie成文件存储格式 126 | public function formatHeaderCookieToFileContent($headerCookie, $domain) 127 | 128 | //从curl内容解析cookie内容并追加保存到cookie文件 129 | public function addCookieFromCurl($curlContent, $domain) 130 | 131 | // ================== 3.底层方法 ================== 132 | //执行curl请求,底层核心方法,内置了请求的cookie存储与跟踪上一次请求的cookie,实现模拟登录cookie依赖 133 | protected function _execCurl($parseCurlResult) 134 | 135 | //记录日志,底层方法,出现异常时记录日志 136 | protected function _log($msg) 137 | ``` 138 | 139 | 140 | 141 | ## demo介绍 142 | 143 | ```php 144 | //简易模拟登录示例,直接引用CurlAutoLogin类进行调用 145 | 0_simpleAutoLogin.php 146 | 147 | //简易模拟登录示例,基于composer引用CurlAutoLogin类进行调用 148 | //简介:包含execCurl回调$callbackBefore实现curl请求前替换用户名 149 | 1_simpleAutoLogin.php 150 | 151 | //浏览器登录微信,利用登录后cookie进行后续访问 152 | //简介:【代码已不可用,参考思路】 153 | //方法一:利用execCurl前置回调添加cookie到header中 154 | //方法二:直接调用parseCurl对curl命令进行解析,并组装包含cookie的header头进行请求 155 | //方法三:直接调用execCurlWithCookie调用 156 | 2_wxqq.php 157 | 158 | //预加载cookie,然后访问其他页面 159 | //简介:模拟登录有时候依赖首页或者其他页面的cookie,所以需要调用execCurl先请求一次,存下该页面的cookie,再做后续的请求 160 | 3_preloadCookieAndVisit.php 161 | 162 | //中国知网下载 163 | //简介:增加CURLOPT_HEADER属性返回请求头信息,然后解析下载地址进行下载请求 164 | 7_cnki.net.php 165 | 166 | //webqq发送消息 167 | //简介:【功能已不可用】基于web2 qq 发送群消息和个人消息(注:频繁发送会导致账号锁定,慎用!!!) 168 | 8_webqq.php 169 | 170 | //博客园模拟登录 171 | //简介:【网站改版,功能已不可用】 172 | //基于nodejs提供js加密处理,返回结果给php请求登录使用 173 | 11_cnblogLogin 174 | 175 | //(验证码)坐车网登录 176 | //简介:坐车网网页显示验证码,用户手动录入后提交给程序,实现模拟登录 177 | 12_zuocheWithCaptcha.php 178 | 179 | //模拟登录360doc 180 | //简介:360doc登录,中间有一层cookie依赖,类似demo 3_preloadCookieAndVisit.php 181 | 14_360doc.php 182 | 183 | //为知笔记内容下载 184 | //简介:利用js在控制台运行获取所有笔记采集链接,然后下载对应笔记 185 | 15_downloadWizNote.php 186 | 187 | //页面采集通用方法 188 | //简介:日常使用curl请求可用 189 | 16_commonCurl/curlPage.php 190 | 191 | //(验证码)命令行下输入验证码登录dev.360.cn 192 | //简介:命令行执行获取验证码,写入到文件,命令行等待录入验证码,录入后提交给程序,实现模拟登录 193 | 17_dev.360.cn_STDINCaptcha.php 194 | 195 | //天眼查关键词搜索 196 | //简介:【功能已不可用】天眼查关键词搜索,最终数据页有token依赖,提取后通过$callbackBefore传入 197 | 19_www.tianyancha.com.php 198 | 199 | //(验证码)木蚂蚁用户登录 200 | //简介:木蚂蚁用户登录,网页显示验证码,用户手动录入后提交给程序,实现模拟登录 201 | 20_u.mumayi.com_OnlineCaptcha.php 202 | 203 | //环球外汇网即时行情数据采集 204 | //简介:【页面改版已不需要这么复杂】 205 | //加载页面,解析出js,调用phantomjs执行js获取cookie加密结果,交给php模拟程序调用 206 | 22_tools.cnforex.com-phantomjs-parse-js.php 207 | 208 | //(验证码)好单库登录 209 | //简介:命令行执行获取验证码,写入到文件,命令行等待录入验证码,录入后提交给程序,实现模拟登录 210 | 26_publish.haodanku.com.php 211 | 212 | //阿里文学js解密 213 | //简介:阿里文学网小说解析,基于phantomjs执行js进行内容解析 214 | 34_www.aliwx.com.cn 215 | 216 | //图床图片上传 217 | //简介:【网站502功能已不可用】访问初始页获取x-csrf-token,解析后通过$callbackBefore传入,实现模拟请求上传图片到图床网站 218 | 38_upload.otar.im_image_upload.php 219 | 220 | //草料图片上传二维码解析 221 | //简介:上传图片到草料,然后利用上传结果调用解析接口,获得解析结果 222 | 41_cli.im.php 223 | 224 | //重放请求 225 | //简介:首先模拟无登录态请求,异常后模拟登录,然后重放请求得到正常结果 226 | 48_request_repeat.php 227 | 228 | //tophub.today抓取demo 229 | //简介:知乎热榜网站抓取 230 | 61_tophub.today.php 231 | 232 | //【精华推荐】为知笔记模拟登录后,批量下载笔记 233 | //简介:本示例实现模拟登录与ares333/php-curl批量执行类库结合,演示如何模拟登录后,基于登录态进行批量下载笔记 234 | 62_curlmulti/62_wiz.cn.php 235 | 236 | //基于curl解析得到PHP代码 237 | parseCurlGetPhpCode.php 238 | 239 | ``` 240 | 241 | -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "zjmainstay/php-curl", 3 | "description": "PHP利用cURL实现模拟登录与采集", 4 | "type": "library", 5 | "keywords": [ 6 | "php", 7 | "php curl", 8 | "php curl login", 9 | "php 模拟登录", 10 | "php 模拟登录采集" 11 | ], 12 | "homepage": "http://www.zjmainstay.cn", 13 | "license": "Apache-2.0", 14 | "authors": [ 15 | { 16 | "name": "Zjmainstay", 17 | "email": "zjmainstay@163.com", 18 | "role": "lead" 19 | } 20 | ], 21 | "autoload": { 22 | "psr-4" : { 23 | "PHPCurl\\" : "src/" 24 | } 25 | }, 26 | "require": { 27 | "php": ">=5.4.0" 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /demo/0_simpleAutoLogin.php: -------------------------------------------------------------------------------- 1 | getLineBreak(); 17 | 18 | //0. 未登录 19 | $getDataUrl = 'http://demo.zjmainstay.cn/js/simpleAjax/loginResult.php'; 20 | echo 'Before Login: ' . $autologin->getUrl($getDataUrl) . $lineBreak; 21 | 22 | //1. 初始化登录页 23 | $curl1 = "curl 'http://demo.zjmainstay.cn/js/simpleAjax/' -H 'Host: demo.zjmainstay.cn' -H 'User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.10; rv:47.0) Gecko/20100101 Firefox/47.0' -H 'Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8' -H 'Accept-Language: zh-CN,zh;q=0.8,en-US;q=0.5,en;q=0.3' -H 'Accept-Encoding: gzip, deflate' -H 'Cookie: Hm_lvt_1526d5aecf5561ef9401f7c7b7842a97=1468327822,1468327904,1468341636,1468411918; Hm_lpvt_1526d5aecf5561ef9401f7c7b7842a97=1468421526' -H 'Connection: keep-alive' -H 'If-Modified-Since: Mon, 27 Oct 2014 08:31:18 GMT' -H 'If-None-Match: \"32e-453-506635ac5e180\"' -H 'Cache-Control: max-age=0'"; 24 | $content = $autologin->execCurl($curl1); 25 | 26 | //2. 提交登录表单 27 | $curl2 = "curl 'http://demo.zjmainstay.cn/js/simpleAjax/doPost.php' -H 'Host: demo.zjmainstay.cn' -H 'User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.10; rv:47.0) Gecko/20100101 Firefox/47.0' -H 'Accept: application/json, text/javascript, */*; q=0.01' -H 'Accept-Language: zh-CN,zh;q=0.8,en-US;q=0.5,en;q=0.3' -H 'Accept-Encoding: gzip, deflate' -H 'Content-Type: application/x-www-form-urlencoded; charset=UTF-8' -H 'X-Requested-With: XMLHttpRequest' -H 'Referer: http://demo.zjmainstay.cn/js/simpleAjax/' -H 'Cookie: Hm_lvt_1526d5aecf5561ef9401f7c7b7842a97=1468327822,1468327904,1468341636,1468411918; Hm_lpvt_1526d5aecf5561ef9401f7c7b7842a97=1468421526' -H 'Connection: keep-alive' --data 'username=demousername'"; 28 | $realUsername = 'Zjmainstay'; 29 | //前置处理,替换错误的用户名(也可以在上面填充curl的时候,使用变量替换对应内容) 30 | $content = $autologin->execCurl($curl2, function($parseCurlResult) use ($realUsername) { 31 | $parseCurlResult['post'] = str_replace('=demousername', "={$realUsername}", $parseCurlResult['post']); 32 | return $parseCurlResult; 33 | }); 34 | 35 | //3. 登录成功,锁定cookie的更新,直接访问已登录页面内容(类似采集内容),演示cookie锁定多次采集效果与cookie失效效果 36 | $autologin->lockLastCookieFile(); 37 | echo 'After Login 1(with_cookie): ' . $autologin->getUrl($getDataUrl) . $lineBreak; 38 | echo 'After Login 2(with_cookie): ' . $autologin->getUrl($getDataUrl) . $lineBreak; 39 | $autologin->removeLastCookie(); 40 | echo 'After Login 3(without_cookie): ' . $autologin->getUrl($getDataUrl) . $lineBreak; 41 | -------------------------------------------------------------------------------- /demo/10_zhihulogin.php: -------------------------------------------------------------------------------- 1 | execCurl($curl1); 29 | 30 | //偶然发现csrf没有用,所以直接赋值了useless 31 | $email = urlencode($email); 32 | $curl2 = "curl 'https://www.zhihu.com/login/email' -H 'Accept: */*' -H 'Accept-Encoding: gzip, deflate, br' -H 'Accept-Language: zh-CN,zh;q=0.8,en-US;q=0.5,en;q=0.3' -H 'Connection: keep-alive' -H 'Content-Type: application/x-www-form-urlencoded; charset=UTF-8' -H 'Cookie: q_c1=0daf021c52de4ef3b6a529ff4f1a6811|1470651590000|1470651590000; _xsrf=4e599680f57fee89a4dd1aebe0e38128; l_cap_id=\"NzFlNjRmZGE3ODJhNDJkMGI1NDc2YzQxYjliZDkwZTE=|1470651590|9d2ff3f78f14a0e32c7938f1d86023736b25a5bd\"; cap_id=\"OWFjNDkzYWYxNmZhNDBjN2JlZWJjNDhiNGUxYTJjNWI=|1470651590|652577038670a9b544e91d6cbcb5a355dfc29eee\"; n_c=1; d_c0=\"ABCAsUV-WgqPTnNCtsTsgzk-RdfrxZVFb8g=|1470651591\"; __utma=51854390.248018333.1470651592.1470651592.1470651592.1; __utmb=51854390.2.10.1470651592; __utmc=51854390; __utmz=51854390.1470651592.1.1.utmcsr=(direct)|utmccn=(direct)|utmcmd=(none); __utmv=51854390.000--|3=entry_date=20160808=1; __utmt=1; _za=ee1a9bde-d629-4f05-b670-7adb1ee17a5f; _zap=64a770d4-5a33-4744-9602-4608f0f6f551' -H 'Host: www.zhihu.com' -H 'Referer: https://www.zhihu.com/' -H 'User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.10; rv:47.0) Gecko/20100101 Firefox/47.0' -H 'X-Requested-With: XMLHttpRequest' -H 'X-Xsrftoken: 4e599680f57fee89a4dd1aebe0e38128' --data '_xsrf=useless&password={$password}&captcha_type=cn&remember_me=true&email={$email}'"; 33 | $content = $autologin->execCurl($curl2); 34 | 35 | $autologin->lockLastCookieFile(); 36 | 37 | $homeUrl = 'https://www.zhihu.com/'; 38 | $isLogin = $autologin->assertContainStr($autologin->getUrl($homeUrl), '退出'); 39 | 40 | if($isLogin) { 41 | echo "已登录"; 42 | } else { 43 | exit('未登录,请检查账号密码'); 44 | } 45 | 46 | file_put_contents($loginCookieFile, $autologin->getLastCookieContent()); 47 | } 48 | 49 | $autologin->setLastCookieFile($loginCookieFile); 50 | 51 | //获取我的收藏(未做登录缓存过期判断处理) 52 | $url = 'https://www.zhihu.com/collections'; 53 | $content = $autologin->getUrl($url); 54 | 55 | $pattern = '#]*?zm-item-title[^>]*?>\s*(.*?)#is'; 56 | 57 | if( preg_match_all($pattern, $content, $matches) ) { 58 | foreach($matches[0] as $key => $val) { 59 | echo "{$matches[2][$key]}({$matches[1][$key]})\n"; 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /demo/11_cnblogLogin/11_cnbloglogin.php: -------------------------------------------------------------------------------- 1 | execCurl($curl1); 28 | 29 | //获取VerificationToken 30 | $pattern = "#'VerificationToken': '([^']+)'#is"; 31 | if(!preg_match($pattern, $content, $match)) { 32 | exit('无法解析获得登录页VerificationToken'); 33 | //throw new Exception('无法解析获得登录页VerificationToken'); 34 | } 35 | 36 | $verificationToken = $match[1]; 37 | 38 | //基于node.js获取登录加密结果 39 | $content = file_get_contents("http://localhost:8111?input1={$username}&input2={$password}"); 40 | $encryptInfo = json_decode($content, true); 41 | $postData = sprintf('{"input1":"%s","input2":"%s","remember":false}', $encryptInfo['input1'], $encryptInfo['input2']); 42 | $contentLength = strlen($postData); 43 | 44 | //提交登录信息 45 | $curl2 = "curl 'https://passport.cnblogs.com/user/signin' -X POST -H 'Host: passport.cnblogs.com' -H 'User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.10; rv:48.0) Gecko/20100101 Firefox/48.0' -H 'Accept: application/json, text/javascript, */*; q=0.01' -H 'Accept-Language: zh-CN,zh;q=0.8,en-US;q=0.5,en;q=0.3' -H 'Accept-Encoding: gzip, deflate, br' -H 'Content-Type: application/json; charset=utf-8' -H 'VerificationToken: {$verificationToken}' -H 'X-Requested-With: XMLHttpRequest' -H 'Referer: https://passport.cnblogs.com/user/signin?ReturnUrl=http%3A%2F%2Fwww.cnblogs.com%2F&AspxAutoDetectCookieSupport=1' -H 'Content-Length: {$contentLength}' -H 'Cookie: AspxAutoDetectCookieSupport=1; SERVERID=d0849c852e6ab8cf0cebe3fa386ea513|1476439733|1476438874' -H 'Connection: keep-alive'"; 46 | $content = $autologin->execCurl($curl2, function($parseCurlResult) use ($postData) { 47 | $parseCurlResult['post'] = $postData; 48 | return $parseCurlResult; 49 | }); 50 | 51 | $autologin->lockLastCookieFile(); 52 | 53 | $homeUrl = 'http://i.cnblogs.com/'; 54 | $isLogin = $autologin->assertContainStr($autologin->getUrl($homeUrl), '修改密码'); 55 | 56 | if($isLogin) { 57 | echo "已登录\n"; 58 | } else { 59 | exit("未登录,请检查账号密码\n"); 60 | } 61 | 62 | file_put_contents($loginCookieFile, $autologin->getLastCookieContent()); 63 | } 64 | 65 | $autologin->setLastCookieFile($loginCookieFile); 66 | 67 | //获取我的随笔 68 | $url = 'https://i.cnblogs.com/'; 69 | $content = $autologin->getUrl($url); 70 | 71 | $pattern = '#\s*]*>(.*?)#is'; 72 | 73 | if( preg_match_all($pattern, $content, $matches) ) { 74 | foreach($matches[0] as $key => $val) { 75 | echo "{$matches[2][$key]}({$matches[1][$key]})\n"; 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /demo/11_cnblogLogin/jsencrypt.min.js: -------------------------------------------------------------------------------- 1 | var JSEncryptExports = {}; 2 | (function(exports) { 3 | function BigInteger(a,b,c){null!=a&&("number"==typeof a?this.fromNumber(a,b,c):null==b&&"string"!=typeof a?this.fromString(a,256):this.fromString(a,b))}function nbi(){return new BigInteger(null)}function am1(a,b,c,d,e,f){for(;--f>=0;){var g=b*this[a++]+c[d]+e;e=Math.floor(g/67108864),c[d++]=67108863&g}return e}function am2(a,b,c,d,e,f){for(var g=32767&b,h=b>>15;--f>=0;){var i=32767&this[a],j=this[a++]>>15,k=h*i+j*g;i=g*i+((32767&k)<<15)+c[d]+(1073741823&e),e=(i>>>30)+(k>>>15)+h*j+(e>>>30),c[d++]=1073741823&i}return e}function am3(a,b,c,d,e,f){for(var g=16383&b,h=b>>14;--f>=0;){var i=16383&this[a],j=this[a++]>>14,k=h*i+j*g;i=g*i+((16383&k)<<14)+c[d]+e,e=(i>>28)+(k>>14)+h*j,c[d++]=268435455&i}return e}function int2char(a){return BI_RM.charAt(a)}function intAt(a,b){var c=BI_RC[a.charCodeAt(b)];return null==c?-1:c}function bnpCopyTo(a){for(var b=this.t-1;b>=0;--b)a[b]=this[b];a.t=this.t,a.s=this.s}function bnpFromInt(a){this.t=1,this.s=0>a?-1:0,a>0?this[0]=a:-1>a?this[0]=a+DV:this.t=0}function nbv(a){var b=nbi();return b.fromInt(a),b}function bnpFromString(a,b){var c;if(16==b)c=4;else if(8==b)c=3;else if(256==b)c=8;else if(2==b)c=1;else if(32==b)c=5;else{if(4!=b)return void this.fromRadix(a,b);c=2}this.t=0,this.s=0;for(var d=a.length,e=!1,f=0;--d>=0;){var g=8==c?255&a[d]:intAt(a,d);0>g?"-"==a.charAt(d)&&(e=!0):(e=!1,0==f?this[this.t++]=g:f+c>this.DB?(this[this.t-1]|=(g&(1<>this.DB-f):this[this.t-1]|=g<=this.DB&&(f-=this.DB))}8==c&&0!=(128&a[0])&&(this.s=-1,f>0&&(this[this.t-1]|=(1<0&&this[this.t-1]==a;)--this.t}function bnToString(a){if(this.s<0)return"-"+this.negate().toString(a);var b;if(16==a)b=4;else if(8==a)b=3;else if(2==a)b=1;else if(32==a)b=5;else{if(4!=a)return this.toRadix(a);b=2}var c,d=(1<0)for(h>h)>0&&(e=!0,f=int2char(c));g>=0;)b>h?(c=(this[g]&(1<>(h+=this.DB-b)):(c=this[g]>>(h-=b)&d,0>=h&&(h+=this.DB,--g)),c>0&&(e=!0),e&&(f+=int2char(c));return e?f:"0"}function bnNegate(){var a=nbi();return BigInteger.ZERO.subTo(this,a),a}function bnAbs(){return this.s<0?this.negate():this}function bnCompareTo(a){var b=this.s-a.s;if(0!=b)return b;var c=this.t;if(b=c-a.t,0!=b)return this.s<0?-b:b;for(;--c>=0;)if(0!=(b=this[c]-a[c]))return b;return 0}function nbits(a){var b,c=1;return 0!=(b=a>>>16)&&(a=b,c+=16),0!=(b=a>>8)&&(a=b,c+=8),0!=(b=a>>4)&&(a=b,c+=4),0!=(b=a>>2)&&(a=b,c+=2),0!=(b=a>>1)&&(a=b,c+=1),c}function bnBitLength(){return this.t<=0?0:this.DB*(this.t-1)+nbits(this[this.t-1]^this.s&this.DM)}function bnpDLShiftTo(a,b){var c;for(c=this.t-1;c>=0;--c)b[c+a]=this[c];for(c=a-1;c>=0;--c)b[c]=0;b.t=this.t+a,b.s=this.s}function bnpDRShiftTo(a,b){for(var c=a;c=0;--c)b[c+g+1]=this[c]>>e|h,h=(this[c]&f)<=0;--c)b[c]=0;b[g]=h,b.t=this.t+g+1,b.s=this.s,b.clamp()}function bnpRShiftTo(a,b){b.s=this.s;var c=Math.floor(a/this.DB);if(c>=this.t)return void(b.t=0);var d=a%this.DB,e=this.DB-d,f=(1<>d;for(var g=c+1;g>d;d>0&&(b[this.t-c-1]|=(this.s&f)<c;)d+=this[c]-a[c],b[c++]=d&this.DM,d>>=this.DB;if(a.t>=this.DB;d+=this.s}else{for(d+=this.s;c>=this.DB;d-=a.s}b.s=0>d?-1:0,-1>d?b[c++]=this.DV+d:d>0&&(b[c++]=d),b.t=c,b.clamp()}function bnpMultiplyTo(a,b){var c=this.abs(),d=a.abs(),e=c.t;for(b.t=e+d.t;--e>=0;)b[e]=0;for(e=0;e=0;)a[c]=0;for(c=0;c=b.DV&&(a[c+b.t]-=b.DV,a[c+b.t+1]=1)}a.t>0&&(a[a.t-1]+=b.am(c,b[c],a,2*c,0,1)),a.s=0,a.clamp()}function bnpDivRemTo(a,b,c){var d=a.abs();if(!(d.t<=0)){var e=this.abs();if(e.t0?(d.lShiftTo(i,f),e.lShiftTo(i,c)):(d.copyTo(f),e.copyTo(c));var j=f.t,k=f[j-1];if(0!=k){var l=k*(1<1?f[j-2]>>this.F2:0),m=this.FV/l,n=(1<=0&&(c[c.t++]=1,c.subTo(r,c)),BigInteger.ONE.dlShiftTo(j,r),r.subTo(f,f);f.t=0;){var s=c[--p]==k?this.DM:Math.floor(c[p]*m+(c[p-1]+o)*n);if((c[p]+=f.am(0,s,c,q,0,j))0&&c.rShiftTo(i,c),0>g&&BigInteger.ZERO.subTo(c,c)}}}function bnMod(a){var b=nbi();return this.abs().divRemTo(a,null,b),this.s<0&&b.compareTo(BigInteger.ZERO)>0&&a.subTo(b,b),b}function Classic(a){this.m=a}function cConvert(a){return a.s<0||a.compareTo(this.m)>=0?a.mod(this.m):a}function cRevert(a){return a}function cReduce(a){a.divRemTo(this.m,null,a)}function cMulTo(a,b,c){a.multiplyTo(b,c),this.reduce(c)}function cSqrTo(a,b){a.squareTo(b),this.reduce(b)}function bnpInvDigit(){if(this.t<1)return 0;var a=this[0];if(0==(1&a))return 0;var b=3&a;return b=b*(2-(15&a)*b)&15,b=b*(2-(255&a)*b)&255,b=b*(2-((65535&a)*b&65535))&65535,b=b*(2-a*b%this.DV)%this.DV,b>0?this.DV-b:-b}function Montgomery(a){this.m=a,this.mp=a.invDigit(),this.mpl=32767&this.mp,this.mph=this.mp>>15,this.um=(1<0&&this.m.subTo(b,b),b}function montRevert(a){var b=nbi();return a.copyTo(b),this.reduce(b),b}function montReduce(a){for(;a.t<=this.mt2;)a[a.t++]=0;for(var b=0;b>15)*this.mpl&this.um)<<15)&a.DM;for(c=b+this.m.t,a[c]+=this.m.am(0,d,a,b,0,this.m.t);a[c]>=a.DV;)a[c]-=a.DV,a[++c]++}a.clamp(),a.drShiftTo(this.m.t,a),a.compareTo(this.m)>=0&&a.subTo(this.m,a)}function montSqrTo(a,b){a.squareTo(b),this.reduce(b)}function montMulTo(a,b,c){a.multiplyTo(b,c),this.reduce(c)}function bnpIsEven(){return 0==(this.t>0?1&this[0]:this.s)}function bnpExp(a,b){if(a>4294967295||1>a)return BigInteger.ONE;var c=nbi(),d=nbi(),e=b.convert(this),f=nbits(a)-1;for(e.copyTo(c);--f>=0;)if(b.sqrTo(c,d),(a&1<0)b.mulTo(d,e,c);else{var g=c;c=d,d=g}return b.revert(c)}function bnModPowInt(a,b){var c;return c=256>a||b.isEven()?new Classic(b):new Montgomery(b),this.exp(a,c)}function bnClone(){var a=nbi();return this.copyTo(a),a}function bnIntValue(){if(this.s<0){if(1==this.t)return this[0]-this.DV;if(0==this.t)return-1}else{if(1==this.t)return this[0];if(0==this.t)return 0}return(this[1]&(1<<32-this.DB)-1)<>24}function bnShortValue(){return 0==this.t?this.s:this[0]<<16>>16}function bnpChunkSize(a){return Math.floor(Math.LN2*this.DB/Math.log(a))}function bnSigNum(){return this.s<0?-1:this.t<=0||1==this.t&&this[0]<=0?0:1}function bnpToRadix(a){if(null==a&&(a=10),0==this.signum()||2>a||a>36)return"0";var b=this.chunkSize(a),c=Math.pow(a,b),d=nbv(c),e=nbi(),f=nbi(),g="";for(this.divRemTo(d,e,f);e.signum()>0;)g=(c+f.intValue()).toString(a).substr(1)+g,e.divRemTo(d,e,f);return f.intValue().toString(a)+g}function bnpFromRadix(a,b){this.fromInt(0),null==b&&(b=10);for(var c=this.chunkSize(b),d=Math.pow(b,c),e=!1,f=0,g=0,h=0;hi?"-"==a.charAt(h)&&0==this.signum()&&(e=!0):(g=b*g+i,++f>=c&&(this.dMultiply(d),this.dAddOffset(g,0),f=0,g=0))}f>0&&(this.dMultiply(Math.pow(b,f)),this.dAddOffset(g,0)),e&&BigInteger.ZERO.subTo(this,this)}function bnpFromNumber(a,b,c){if("number"==typeof b)if(2>a)this.fromInt(1);else for(this.fromNumber(a,c),this.testBit(a-1)||this.bitwiseTo(BigInteger.ONE.shiftLeft(a-1),op_or,this),this.isEven()&&this.dAddOffset(1,0);!this.isProbablePrime(b);)this.dAddOffset(2,0),this.bitLength()>a&&this.subTo(BigInteger.ONE.shiftLeft(a-1),this);else{var d=new Array,e=7&a;d.length=(a>>3)+1,b.nextBytes(d),e>0?d[0]&=(1<0)for(d>d)!=(this.s&this.DM)>>d&&(b[e++]=c|this.s<=0;)8>d?(c=(this[a]&(1<>(d+=this.DB-8)):(c=this[a]>>(d-=8)&255,0>=d&&(d+=this.DB,--a)),0!=(128&c)&&(c|=-256),0==e&&(128&this.s)!=(128&c)&&++e,(e>0||c!=this.s)&&(b[e++]=c);return b}function bnEquals(a){return 0==this.compareTo(a)}function bnMin(a){return this.compareTo(a)<0?this:a}function bnMax(a){return this.compareTo(a)>0?this:a}function bnpBitwiseTo(a,b,c){var d,e,f=Math.min(a.t,this.t);for(d=0;f>d;++d)c[d]=b(this[d],a[d]);if(a.ta?this.rShiftTo(-a,b):this.lShiftTo(a,b),b}function bnShiftRight(a){var b=nbi();return 0>a?this.lShiftTo(-a,b):this.rShiftTo(a,b),b}function lbit(a){if(0==a)return-1;var b=0;return 0==(65535&a)&&(a>>=16,b+=16),0==(255&a)&&(a>>=8,b+=8),0==(15&a)&&(a>>=4,b+=4),0==(3&a)&&(a>>=2,b+=2),0==(1&a)&&++b,b}function bnGetLowestSetBit(){for(var a=0;a=this.t?0!=this.s:0!=(this[b]&1<c;)d+=this[c]+a[c],b[c++]=d&this.DM,d>>=this.DB;if(a.t>=this.DB;d+=this.s}else{for(d+=this.s;c>=this.DB;d+=a.s}b.s=0>d?-1:0,d>0?b[c++]=d:-1>d&&(b[c++]=this.DV+d),b.t=c,b.clamp()}function bnAdd(a){var b=nbi();return this.addTo(a,b),b}function bnSubtract(a){var b=nbi();return this.subTo(a,b),b}function bnMultiply(a){var b=nbi();return this.multiplyTo(a,b),b}function bnSquare(){var a=nbi();return this.squareTo(a),a}function bnDivide(a){var b=nbi();return this.divRemTo(a,b,null),b}function bnRemainder(a){var b=nbi();return this.divRemTo(a,null,b),b}function bnDivideAndRemainder(a){var b=nbi(),c=nbi();return this.divRemTo(a,b,c),new Array(b,c)}function bnpDMultiply(a){this[this.t]=this.am(0,a-1,this,0,0,this.t),++this.t,this.clamp()}function bnpDAddOffset(a,b){if(0!=a){for(;this.t<=b;)this[this.t++]=0;for(this[b]+=a;this[b]>=this.DV;)this[b]-=this.DV,++b>=this.t&&(this[this.t++]=0),++this[b]}}function NullExp(){}function nNop(a){return a}function nMulTo(a,b,c){a.multiplyTo(b,c)}function nSqrTo(a,b){a.squareTo(b)}function bnPow(a){return this.exp(a,new NullExp)}function bnpMultiplyLowerTo(a,b,c){var d=Math.min(this.t+a.t,b);for(c.s=0,c.t=d;d>0;)c[--d]=0;var e;for(e=c.t-this.t;e>d;++d)c[d+this.t]=this.am(0,a[d],c,d,0,this.t);for(e=Math.min(a.t,b);e>d;++d)this.am(0,a[d],c,d,0,b-d);c.clamp()}function bnpMultiplyUpperTo(a,b,c){--b;var d=c.t=this.t+a.t-b;for(c.s=0;--d>=0;)c[d]=0;for(d=Math.max(b-this.t,0);d2*this.m.t)return a.mod(this.m);if(a.compareTo(this.m)<0)return a;var b=nbi();return a.copyTo(b),this.reduce(b),b}function barrettRevert(a){return a}function barrettReduce(a){for(a.drShiftTo(this.m.t-1,this.r2),a.t>this.m.t+1&&(a.t=this.m.t+1,a.clamp()),this.mu.multiplyUpperTo(this.r2,this.m.t+1,this.q3),this.m.multiplyLowerTo(this.q3,this.m.t+1,this.r2);a.compareTo(this.r2)<0;)a.dAddOffset(1,this.m.t+1);for(a.subTo(this.r2,a);a.compareTo(this.m)>=0;)a.subTo(this.m,a)}function barrettSqrTo(a,b){a.squareTo(b),this.reduce(b)}function barrettMulTo(a,b,c){a.multiplyTo(b,c),this.reduce(c)}function bnModPow(a,b){var c,d,e=a.bitLength(),f=nbv(1);if(0>=e)return f;c=18>e?1:48>e?3:144>e?4:768>e?5:6,d=8>e?new Classic(b):b.isEven()?new Barrett(b):new Montgomery(b);var g=new Array,h=3,i=c-1,j=(1<1){var k=nbi();for(d.sqrTo(g[1],k);j>=h;)g[h]=nbi(),d.mulTo(k,g[h-2],g[h]),h+=2}var l,m,n=a.t-1,o=!0,p=nbi();for(e=nbits(a[n])-1;n>=0;){for(e>=i?l=a[n]>>e-i&j:(l=(a[n]&(1<0&&(l|=a[n-1]>>this.DB+e-i)),h=c;0==(1&l);)l>>=1,--h;if((e-=h)<0&&(e+=this.DB,--n),o)g[l].copyTo(f),o=!1;else{for(;h>1;)d.sqrTo(f,p),d.sqrTo(p,f),h-=2;h>0?d.sqrTo(f,p):(m=f,f=p,p=m),d.mulTo(p,g[l],f)}for(;n>=0&&0==(a[n]&1<f)return b;for(f>e&&(f=e),f>0&&(b.rShiftTo(f,b),c.rShiftTo(f,c));b.signum()>0;)(e=b.getLowestSetBit())>0&&b.rShiftTo(e,b),(e=c.getLowestSetBit())>0&&c.rShiftTo(e,c),b.compareTo(c)>=0?(b.subTo(c,b),b.rShiftTo(1,b)):(c.subTo(b,c),c.rShiftTo(1,c));return f>0&&c.lShiftTo(f,c),c}function bnpModInt(a){if(0>=a)return 0;var b=this.DV%a,c=this.s<0?a-1:0;if(this.t>0)if(0==b)c=this[0]%a;else for(var d=this.t-1;d>=0;--d)c=(b*c+this[d])%a;return c}function bnModInverse(a){var b=a.isEven();if(this.isEven()&&b||0==a.signum())return BigInteger.ZERO;for(var c=a.clone(),d=this.clone(),e=nbv(1),f=nbv(0),g=nbv(0),h=nbv(1);0!=c.signum();){for(;c.isEven();)c.rShiftTo(1,c),b?(e.isEven()&&f.isEven()||(e.addTo(this,e),f.subTo(a,f)),e.rShiftTo(1,e)):f.isEven()||f.subTo(a,f),f.rShiftTo(1,f);for(;d.isEven();)d.rShiftTo(1,d),b?(g.isEven()&&h.isEven()||(g.addTo(this,g),h.subTo(a,h)),g.rShiftTo(1,g)):h.isEven()||h.subTo(a,h),h.rShiftTo(1,h);c.compareTo(d)>=0?(c.subTo(d,c),b&&e.subTo(g,e),f.subTo(h,f)):(d.subTo(c,d),b&&g.subTo(e,g),h.subTo(f,h))}return 0!=d.compareTo(BigInteger.ONE)?BigInteger.ZERO:h.compareTo(a)>=0?h.subtract(a):h.signum()<0?(h.addTo(a,h),h.signum()<0?h.add(a):h):h}function bnIsProbablePrime(a){var b,c=this.abs();if(1==c.t&&c[0]<=lowprimes[lowprimes.length-1]){for(b=0;bd;)d*=lowprimes[e++];for(d=c.modInt(d);e>b;)if(d%lowprimes[b++]==0)return!1}return c.millerRabin(a)}function bnpMillerRabin(a){var b=this.subtract(BigInteger.ONE),c=b.getLowestSetBit();if(0>=c)return!1;var d=b.shiftRight(c);a=a+1>>1,a>lowprimes.length&&(a=lowprimes.length);for(var e=nbi(),f=0;a>f;++f){e.fromInt(lowprimes[Math.floor(Math.random()*lowprimes.length)]);var g=e.modPow(d,this);if(0!=g.compareTo(BigInteger.ONE)&&0!=g.compareTo(b)){for(var h=1;h++b;++b)this.S[b]=b;for(c=0,b=0;256>b;++b)c=c+this.S[b]+a[b%a.length]&255,d=this.S[b],this.S[b]=this.S[c],this.S[c]=d;this.i=0,this.j=0}function ARC4next(){var a;return this.i=this.i+1&255,this.j=this.j+this.S[this.i]&255,a=this.S[this.i],this.S[this.i]=this.S[this.j],this.S[this.j]=a,this.S[a+this.S[this.i]&255]}function prng_newstate(){return new Arcfour}function rng_get_byte(){if(null==rng_state){for(rng_state=prng_newstate();rng_psize>rng_pptr;){var a=Math.floor(65536*Math.random());rng_pool[rng_pptr++]=255&a}for(rng_state.init(rng_pool),rng_pptr=0;rng_pptra?"0"+a.toString(16):a.toString(16)}function pkcs1pad2(a,b){if(b=0&&b>0;){var e=a.charCodeAt(d--);128>e?c[--b]=e:e>127&&2048>e?(c[--b]=63&e|128,c[--b]=e>>6|192):(c[--b]=63&e|128,c[--b]=e>>6&63|128,c[--b]=e>>12|224)}c[--b]=0;for(var f=new SecureRandom,g=new Array;b>2;){for(g[0]=0;0==g[0];)f.nextBytes(g);c[--b]=g[0]}return c[--b]=2,c[--b]=0,new BigInteger(c)}function RSAKey(){this.n=null,this.e=0,this.d=null,this.p=null,this.q=null,this.dmp1=null,this.dmq1=null,this.coeff=null}function RSASetPublic(a,b){null!=a&&null!=b&&a.length>0&&b.length>0?(this.n=parseBigInt(a,16),this.e=parseInt(b,16)):console.error("Invalid RSA public key")}function RSADoPublic(a){return a.modPowInt(this.e,this.n)}function RSAEncrypt(a){var b=pkcs1pad2(a,this.n.bitLength()+7>>3);if(null==b)return null;var c=this.doPublic(b);if(null==c)return null;var d=c.toString(16);return 0==(1&d.length)?d:"0"+d}function pkcs1unpad2(a,b){for(var c=a.toByteArray(),d=0;d=c.length)return null;for(var e="";++df?e+=String.fromCharCode(f):f>191&&224>f?(e+=String.fromCharCode((31&f)<<6|63&c[d+1]),++d):(e+=String.fromCharCode((15&f)<<12|(63&c[d+1])<<6|63&c[d+2]),d+=2)}return e}function RSASetPrivate(a,b,c){null!=a&&null!=b&&a.length>0&&b.length>0?(this.n=parseBigInt(a,16),this.e=parseInt(b,16),this.d=parseBigInt(c,16)):console.error("Invalid RSA private key")}function RSASetPrivateEx(a,b,c,d,e,f,g,h){null!=a&&null!=b&&a.length>0&&b.length>0?(this.n=parseBigInt(a,16),this.e=parseInt(b,16),this.d=parseBigInt(c,16),this.p=parseBigInt(d,16),this.q=parseBigInt(e,16),this.dmp1=parseBigInt(f,16),this.dmq1=parseBigInt(g,16),this.coeff=parseBigInt(h,16)):console.error("Invalid RSA private key")}function RSAGenerate(a,b){var c=new SecureRandom,d=a>>1;this.e=parseInt(b,16);for(var e=new BigInteger(b,16);;){for(;this.p=new BigInteger(a-d,1,c),0!=this.p.subtract(BigInteger.ONE).gcd(e).compareTo(BigInteger.ONE)||!this.p.isProbablePrime(10););for(;this.q=new BigInteger(d,1,c),0!=this.q.subtract(BigInteger.ONE).gcd(e).compareTo(BigInteger.ONE)||!this.q.isProbablePrime(10););if(this.p.compareTo(this.q)<=0){var f=this.p;this.p=this.q,this.q=f}var g=this.p.subtract(BigInteger.ONE),h=this.q.subtract(BigInteger.ONE),i=g.multiply(h);if(0==i.gcd(e).compareTo(BigInteger.ONE)){this.n=this.p.multiply(this.q),this.d=e.modInverse(i),this.dmp1=this.d.mod(g),this.dmq1=this.d.mod(h),this.coeff=this.q.modInverse(this.p);break}}}function RSADoPrivate(a){if(null==this.p||null==this.q)return a.modPow(this.d,this.n);for(var b=a.mod(this.p).modPow(this.dmp1,this.p),c=a.mod(this.q).modPow(this.dmq1,this.q);b.compareTo(c)<0;)b=b.add(this.p);return b.subtract(c).multiply(this.coeff).mod(this.p).multiply(this.q).add(c)}function RSADecrypt(a){var b=parseBigInt(a,16),c=this.doPrivate(b);return null==c?null:pkcs1unpad2(c,this.n.bitLength()+7>>3)}function hex2b64(a){var b,c,d="";for(b=0;b+3<=a.length;b+=3)c=parseInt(a.substring(b,b+3),16),d+=b64map.charAt(c>>6)+b64map.charAt(63&c);for(b+1==a.length?(c=parseInt(a.substring(b,b+1),16),d+=b64map.charAt(c<<2)):b+2==a.length&&(c=parseInt(a.substring(b,b+2),16),d+=b64map.charAt(c>>2)+b64map.charAt((3&c)<<4));(3&d.length)>0;)d+=b64pad;return d}function b64tohex(a){var b,c,d="",e=0;for(b=0;b>2),c=3&v,e=1):1==e?(d+=int2char(c<<2|v>>4),c=15&v,e=2):2==e?(d+=int2char(c),d+=int2char(v>>2),c=3&v,e=3):(d+=int2char(c<<2|v>>4),d+=int2char(15&v),e=0));return 1==e&&(d+=int2char(c<<2)),d}function b64toBA(a){var b,c=b64tohex(a),d=new Array;for(b=0;2*b=vv;++vv)BI_RC[rr++]=vv;for(rr="a".charCodeAt(0),vv=10;36>vv;++vv)BI_RC[rr++]=vv;for(rr="A".charCodeAt(0),vv=10;36>vv;++vv)BI_RC[rr++]=vv;Classic.prototype.convert=cConvert,Classic.prototype.revert=cRevert,Classic.prototype.reduce=cReduce,Classic.prototype.mulTo=cMulTo,Classic.prototype.sqrTo=cSqrTo,Montgomery.prototype.convert=montConvert,Montgomery.prototype.revert=montRevert,Montgomery.prototype.reduce=montReduce,Montgomery.prototype.mulTo=montMulTo,Montgomery.prototype.sqrTo=montSqrTo,BigInteger.prototype.copyTo=bnpCopyTo,BigInteger.prototype.fromInt=bnpFromInt,BigInteger.prototype.fromString=bnpFromString,BigInteger.prototype.clamp=bnpClamp,BigInteger.prototype.dlShiftTo=bnpDLShiftTo,BigInteger.prototype.drShiftTo=bnpDRShiftTo,BigInteger.prototype.lShiftTo=bnpLShiftTo,BigInteger.prototype.rShiftTo=bnpRShiftTo,BigInteger.prototype.subTo=bnpSubTo,BigInteger.prototype.multiplyTo=bnpMultiplyTo,BigInteger.prototype.squareTo=bnpSquareTo,BigInteger.prototype.divRemTo=bnpDivRemTo,BigInteger.prototype.invDigit=bnpInvDigit,BigInteger.prototype.isEven=bnpIsEven,BigInteger.prototype.exp=bnpExp,BigInteger.prototype.toString=bnToString,BigInteger.prototype.negate=bnNegate,BigInteger.prototype.abs=bnAbs,BigInteger.prototype.compareTo=bnCompareTo,BigInteger.prototype.bitLength=bnBitLength,BigInteger.prototype.mod=bnMod,BigInteger.prototype.modPowInt=bnModPowInt,BigInteger.ZERO=nbv(0),BigInteger.ONE=nbv(1),NullExp.prototype.convert=nNop,NullExp.prototype.revert=nNop,NullExp.prototype.mulTo=nMulTo,NullExp.prototype.sqrTo=nSqrTo,Barrett.prototype.convert=barrettConvert,Barrett.prototype.revert=barrettRevert,Barrett.prototype.reduce=barrettReduce,Barrett.prototype.mulTo=barrettMulTo,Barrett.prototype.sqrTo=barrettSqrTo;var lowprimes=[2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,53,59,61,67,71,73,79,83,89,97,101,103,107,109,113,127,131,137,139,149,151,157,163,167,173,179,181,191,193,197,199,211,223,227,229,233,239,241,251,257,263,269,271,277,281,283,293,307,311,313,317,331,337,347,349,353,359,367,373,379,383,389,397,401,409,419,421,431,433,439,443,449,457,461,463,467,479,487,491,499,503,509,521,523,541,547,557,563,569,571,577,587,593,599,601,607,613,617,619,631,641,643,647,653,659,661,673,677,683,691,701,709,719,727,733,739,743,751,757,761,769,773,787,797,809,811,821,823,827,829,839,853,857,859,863,877,881,883,887,907,911,919,929,937,941,947,953,967,971,977,983,991,997],lplim=(1<<26)/lowprimes[lowprimes.length-1];BigInteger.prototype.chunkSize=bnpChunkSize,BigInteger.prototype.toRadix=bnpToRadix,BigInteger.prototype.fromRadix=bnpFromRadix,BigInteger.prototype.fromNumber=bnpFromNumber,BigInteger.prototype.bitwiseTo=bnpBitwiseTo,BigInteger.prototype.changeBit=bnpChangeBit,BigInteger.prototype.addTo=bnpAddTo,BigInteger.prototype.dMultiply=bnpDMultiply,BigInteger.prototype.dAddOffset=bnpDAddOffset,BigInteger.prototype.multiplyLowerTo=bnpMultiplyLowerTo,BigInteger.prototype.multiplyUpperTo=bnpMultiplyUpperTo,BigInteger.prototype.modInt=bnpModInt,BigInteger.prototype.millerRabin=bnpMillerRabin,BigInteger.prototype.clone=bnClone,BigInteger.prototype.intValue=bnIntValue,BigInteger.prototype.byteValue=bnByteValue,BigInteger.prototype.shortValue=bnShortValue,BigInteger.prototype.signum=bnSigNum,BigInteger.prototype.toByteArray=bnToByteArray,BigInteger.prototype.equals=bnEquals,BigInteger.prototype.min=bnMin,BigInteger.prototype.max=bnMax,BigInteger.prototype.and=bnAnd,BigInteger.prototype.or=bnOr,BigInteger.prototype.xor=bnXor,BigInteger.prototype.andNot=bnAndNot,BigInteger.prototype.not=bnNot,BigInteger.prototype.shiftLeft=bnShiftLeft,BigInteger.prototype.shiftRight=bnShiftRight,BigInteger.prototype.getLowestSetBit=bnGetLowestSetBit,BigInteger.prototype.bitCount=bnBitCount,BigInteger.prototype.testBit=bnTestBit,BigInteger.prototype.setBit=bnSetBit,BigInteger.prototype.clearBit=bnClearBit,BigInteger.prototype.flipBit=bnFlipBit,BigInteger.prototype.add=bnAdd,BigInteger.prototype.subtract=bnSubtract,BigInteger.prototype.multiply=bnMultiply,BigInteger.prototype.divide=bnDivide,BigInteger.prototype.remainder=bnRemainder,BigInteger.prototype.divideAndRemainder=bnDivideAndRemainder,BigInteger.prototype.modPow=bnModPow,BigInteger.prototype.modInverse=bnModInverse,BigInteger.prototype.pow=bnPow,BigInteger.prototype.gcd=bnGCD,BigInteger.prototype.isProbablePrime=bnIsProbablePrime,BigInteger.prototype.square=bnSquare,Arcfour.prototype.init=ARC4init,Arcfour.prototype.next=ARC4next;var rng_psize=256,rng_state,rng_pool,rng_pptr;if(null==rng_pool){rng_pool=new Array,rng_pptr=0;var t;if(window.crypto&&window.crypto.getRandomValues){var z=new Uint32Array(256);for(window.crypto.getRandomValues(z),t=0;t=256||rng_pptr>=rng_psize)return void(window.removeEventListener?window.removeEventListener("mousemove",onMouseMoveListener):window.detachEvent&&window.detachEvent("onmousemove",onMouseMoveListener));this.count+=1;var b=a.x+a.y;rng_pool[rng_pptr++]=255&b};window.addEventListener?window.addEventListener("mousemove",onMouseMoveListener):window.attachEvent&&window.attachEvent("onmousemove",onMouseMoveListener)}SecureRandom.prototype.nextBytes=rng_get_bytes,RSAKey.prototype.doPublic=RSADoPublic,RSAKey.prototype.setPublic=RSASetPublic,RSAKey.prototype.encrypt=RSAEncrypt,RSAKey.prototype.doPrivate=RSADoPrivate,RSAKey.prototype.setPrivate=RSASetPrivate,RSAKey.prototype.setPrivateEx=RSASetPrivateEx,RSAKey.prototype.generate=RSAGenerate,RSAKey.prototype.decrypt=RSADecrypt,function(){var a=function(a,b,c){var d=new SecureRandom,e=a>>1;this.e=parseInt(b,16);var f=new BigInteger(b,16),g=this,h=function(){var b=function(){if(g.p.compareTo(g.q)<=0){var a=g.p;g.p=g.q,g.q=a}var b=g.p.subtract(BigInteger.ONE),d=g.q.subtract(BigInteger.ONE),e=b.multiply(d);0==e.gcd(f).compareTo(BigInteger.ONE)?(g.n=g.p.multiply(g.q),g.d=f.modInverse(e),g.dmp1=g.d.mod(b),g.dmq1=g.d.mod(d),g.coeff=g.q.modInverse(g.p),setTimeout(function(){c()},0)):setTimeout(h,0)},i=function(){g.q=nbi(),g.q.fromNumberAsync(e,1,d,function(){g.q.subtract(BigInteger.ONE).gcda(f,function(a){0==a.compareTo(BigInteger.ONE)&&g.q.isProbablePrime(10)?setTimeout(b,0):setTimeout(i,0)})})},j=function(){g.p=nbi(),g.p.fromNumberAsync(a-e,1,d,function(){g.p.subtract(BigInteger.ONE).gcda(f,function(a){0==a.compareTo(BigInteger.ONE)&&g.p.isProbablePrime(10)?setTimeout(i,0):setTimeout(j,0)})})};setTimeout(j,0)};setTimeout(h,0)};RSAKey.prototype.generateAsync=a;var b=function(a,b){var c=this.s<0?this.negate():this.clone(),d=a.s<0?a.negate():a.clone();if(c.compareTo(d)<0){var e=c;c=d,d=e}var f=c.getLowestSetBit(),g=d.getLowestSetBit();if(0>g)return void b(c);g>f&&(g=f),g>0&&(c.rShiftTo(g,c),d.rShiftTo(g,d));var h=function(){(f=c.getLowestSetBit())>0&&c.rShiftTo(f,c),(f=d.getLowestSetBit())>0&&d.rShiftTo(f,d),c.compareTo(d)>=0?(c.subTo(d,c),c.rShiftTo(1,c)):(d.subTo(c,d),d.rShiftTo(1,d)),c.signum()>0?setTimeout(h,0):(g>0&&d.lShiftTo(g,d),setTimeout(function(){b(d)},0))};setTimeout(h,10)};BigInteger.prototype.gcda=b;var c=function(a,b,c,d){if("number"==typeof b)if(2>a)this.fromInt(1);else{this.fromNumber(a,c),this.testBit(a-1)||this.bitwiseTo(BigInteger.ONE.shiftLeft(a-1),op_or,this),this.isEven()&&this.dAddOffset(1,0);var e=this,f=function(){e.dAddOffset(2,0),e.bitLength()>a&&e.subTo(BigInteger.ONE.shiftLeft(a-1),e),e.isProbablePrime(b)?setTimeout(function(){d()},0):setTimeout(f,0)};setTimeout(f,0)}else{var g=new Array,h=7&a;g.length=(a>>3)+1,b.nextBytes(g),h>0?g[0]&=(1<f;f++)e+="f";var g=new BigInteger(e,16),h=g.xor(a).add(BigInteger.ONE);b=h.toString(16).replace(/^-/,"")}return b},this.getPEMStringFromHex=function(a,b){var c=CryptoJS.enc.Hex.parse(a),d=CryptoJS.enc.Base64.stringify(c),e=d.replace(/(.{64})/g,"$1\r\n");return e=e.replace(/\r\n$/,""),"-----BEGIN "+b+"-----\r\n"+e+"\r\n-----END "+b+"-----\r\n"}},KJUR.asn1.ASN1Object=function(){var a="";this.getLengthHexFromValue=function(){if("undefined"==typeof this.hV||null==this.hV)throw"this.hV is null or undefined.";if(this.hV.length%2==1)throw"value hex must be even length: n="+a.length+",v="+this.hV;var b=this.hV.length/2,c=b.toString(16);if(c.length%2==1&&(c="0"+c),128>b)return c;var d=c.length/2;if(d>15)throw"ASN.1 length too long to represent by 8x: n = "+b.toString(16);var e=128+d;return e.toString(16)+c},this.getEncodedHex=function(){return(null==this.hTLV||this.isModified)&&(this.hV=this.getFreshValueHex(),this.hL=this.getLengthHexFromValue(),this.hTLV=this.hT+this.hL+this.hV,this.isModified=!1),this.hTLV},this.getValueHex=function(){return this.getEncodedHex(),this.hV},this.getFreshValueHex=function(){return""}},KJUR.asn1.DERAbstractString=function(a){KJUR.asn1.DERAbstractString.superclass.constructor.call(this);this.getString=function(){return this.s},this.setString=function(a){this.hTLV=null,this.isModified=!0,this.s=a,this.hV=stohex(this.s)},this.setStringHex=function(a){this.hTLV=null,this.isModified=!0,this.s=null,this.hV=a},this.getFreshValueHex=function(){return this.hV},"undefined"!=typeof a&&("undefined"!=typeof a.str?this.setString(a.str):"undefined"!=typeof a.hex&&this.setStringHex(a.hex))},JSX.extend(KJUR.asn1.DERAbstractString,KJUR.asn1.ASN1Object),KJUR.asn1.DERAbstractTime=function(){KJUR.asn1.DERAbstractTime.superclass.constructor.call(this);this.localDateToUTC=function(a){utc=a.getTime()+6e4*a.getTimezoneOffset();var b=new Date(utc);return b},this.formatDate=function(a,b){var c=this.zeroPadding,d=this.localDateToUTC(a),e=String(d.getFullYear());"utc"==b&&(e=e.substr(2,2));var f=c(String(d.getMonth()+1),2),g=c(String(d.getDate()),2),h=c(String(d.getHours()),2),i=c(String(d.getMinutes()),2),j=c(String(d.getSeconds()),2);return e+f+g+h+i+j+"Z"},this.zeroPadding=function(a,b){return a.length>=b?a:new Array(b-a.length+1).join("0")+a},this.getString=function(){return this.s},this.setString=function(a){this.hTLV=null,this.isModified=!0,this.s=a,this.hV=stohex(this.s)},this.setByDateValue=function(a,b,c,d,e,f){var g=new Date(Date.UTC(a,b-1,c,d,e,f,0));this.setByDate(g)},this.getFreshValueHex=function(){return this.hV}},JSX.extend(KJUR.asn1.DERAbstractTime,KJUR.asn1.ASN1Object),KJUR.asn1.DERAbstractStructured=function(a){KJUR.asn1.DERAbstractString.superclass.constructor.call(this);this.setByASN1ObjectArray=function(a){this.hTLV=null,this.isModified=!0,this.asn1Array=a},this.appendASN1Object=function(a){this.hTLV=null,this.isModified=!0,this.asn1Array.push(a)},this.asn1Array=new Array,"undefined"!=typeof a&&"undefined"!=typeof a.array&&(this.asn1Array=a.array)},JSX.extend(KJUR.asn1.DERAbstractStructured,KJUR.asn1.ASN1Object),KJUR.asn1.DERBoolean=function(){KJUR.asn1.DERBoolean.superclass.constructor.call(this),this.hT="01",this.hTLV="0101ff"},JSX.extend(KJUR.asn1.DERBoolean,KJUR.asn1.ASN1Object),KJUR.asn1.DERInteger=function(a){KJUR.asn1.DERInteger.superclass.constructor.call(this),this.hT="02",this.setByBigInteger=function(a){this.hTLV=null,this.isModified=!0,this.hV=KJUR.asn1.ASN1Util.bigIntToMinTwosComplementsHex(a)},this.setByInteger=function(a){var b=new BigInteger(String(a),10);this.setByBigInteger(b)},this.setValueHex=function(a){this.hV=a},this.getFreshValueHex=function(){return this.hV},"undefined"!=typeof a&&("undefined"!=typeof a.bigint?this.setByBigInteger(a.bigint):"undefined"!=typeof a["int"]?this.setByInteger(a["int"]):"undefined"!=typeof a.hex&&this.setValueHex(a.hex))},JSX.extend(KJUR.asn1.DERInteger,KJUR.asn1.ASN1Object),KJUR.asn1.DERBitString=function(a){KJUR.asn1.DERBitString.superclass.constructor.call(this),this.hT="03",this.setHexValueIncludingUnusedBits=function(a){this.hTLV=null,this.isModified=!0,this.hV=a},this.setUnusedBitsAndHexValue=function(a,b){if(0>a||a>7)throw"unused bits shall be from 0 to 7: u = "+a;var c="0"+a;this.hTLV=null,this.isModified=!0,this.hV=c+b},this.setByBinaryString=function(a){a=a.replace(/0+$/,"");var b=8-a.length%8;8==b&&(b=0);for(var c=0;b>=c;c++)a+="0";for(var d="",c=0;cc;c++)b[c]=!1;return b},this.getFreshValueHex=function(){return this.hV},"undefined"!=typeof a&&("undefined"!=typeof a.hex?this.setHexValueIncludingUnusedBits(a.hex):"undefined"!=typeof a.bin?this.setByBinaryString(a.bin):"undefined"!=typeof a.array&&this.setByBooleanArray(a.array))},JSX.extend(KJUR.asn1.DERBitString,KJUR.asn1.ASN1Object),KJUR.asn1.DEROctetString=function(a){KJUR.asn1.DEROctetString.superclass.constructor.call(this,a),this.hT="04"},JSX.extend(KJUR.asn1.DEROctetString,KJUR.asn1.DERAbstractString),KJUR.asn1.DERNull=function(){KJUR.asn1.DERNull.superclass.constructor.call(this),this.hT="05",this.hTLV="0500"},JSX.extend(KJUR.asn1.DERNull,KJUR.asn1.ASN1Object),KJUR.asn1.DERObjectIdentifier=function(a){var b=function(a){var b=a.toString(16);return 1==b.length&&(b="0"+b),b},c=function(a){var c="",d=new BigInteger(a,10),e=d.toString(2),f=7-e.length%7;7==f&&(f=0);for(var g="",h=0;f>h;h++)g+="0";e=g+e;for(var h=0;hd;++d)b[e.charAt(d)]=d;for(e=e.toLowerCase(),d=10;16>d;++d)b[e.charAt(d)]=d;for(d=0;d=2?(g[g.length]=h,h=0,i=0):h<<=4}}if(i)throw"Hex encoding incomplete: 4 bits missing";return g},window.Hex=c}(),function(a){"use strict";var b,c={};c.decode=function(c){var d;if(b===a){var e="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/",f="= \f\n\r  \u2028\u2029";for(b=[],d=0;64>d;++d)b[e.charAt(d)]=d;for(d=0;d=4?(g[g.length]=h>>16,g[g.length]=h>>8&255,g[g.length]=255&h,h=0,i=0):h<<=6}}switch(i){case 1:throw"Base64 encoding incomplete: at least 2 bits missing";case 2:g[g.length]=h>>10;break;case 3:g[g.length]=h>>16,g[g.length]=h>>8&255}return g},c.re=/-----BEGIN [^-]+-----([A-Za-z0-9+\/=\s]+)-----END [^-]+-----|begin-base64[^\n]+\n([A-Za-z0-9+\/=\s]+)====/,c.unarmor=function(a){var b=c.re.exec(a);if(b)if(b[1])a=b[1];else{if(!b[2])throw"RegExp out of sync";a=b[2]}return c.decode(a)},window.Base64=c}(),function(a){"use strict";function b(a,c){a instanceof b?(this.enc=a.enc,this.pos=a.pos):(this.enc=a,this.pos=c)}function c(a,b,c,d,e){this.stream=a,this.header=b,this.length=c,this.tag=d,this.sub=e}var d=100,e="…",f={tag:function(a,b){var c=document.createElement(a);return c.className=b,c},text:function(a){return document.createTextNode(a)}};b.prototype.get=function(b){if(b===a&&(b=this.pos++),b>=this.enc.length)throw"Requesting byte offset "+b+" on a stream of length "+this.enc.length;return this.enc[b]},b.prototype.hexDigits="0123456789ABCDEF",b.prototype.hexByte=function(a){return this.hexDigits.charAt(a>>4&15)+this.hexDigits.charAt(15&a)},b.prototype.hexDump=function(a,b,c){for(var d="",e=a;b>e;++e)if(d+=this.hexByte(this.get(e)),c!==!0)switch(15&e){case 7:d+=" ";break;case 15:d+="\n";break;default:d+=" "}return d},b.prototype.parseStringISO=function(a,b){for(var c="",d=a;b>d;++d)c+=String.fromCharCode(this.get(d));return c},b.prototype.parseStringUTF=function(a,b){for(var c="",d=a;b>d;){var e=this.get(d++);c+=String.fromCharCode(128>e?e:e>191&&224>e?(31&e)<<6|63&this.get(d++):(15&e)<<12|(63&this.get(d++))<<6|63&this.get(d++))}return c},b.prototype.parseStringBMP=function(a,b){for(var c="",d=a;b>d;d+=2){var e=this.get(d),f=this.get(d+1);c+=String.fromCharCode((e<<8)+f)}return c},b.prototype.reTime=/^((?:1[89]|2\d)?\d\d)(0[1-9]|1[0-2])(0[1-9]|[12]\d|3[01])([01]\d|2[0-3])(?:([0-5]\d)(?:([0-5]\d)(?:[.,](\d{1,3}))?)?)?(Z|[-+](?:[0]\d|1[0-2])([0-5]\d)?)?$/,b.prototype.parseTime=function(a,b){var c=this.parseStringISO(a,b),d=this.reTime.exec(c);return d?(c=d[1]+"-"+d[2]+"-"+d[3]+" "+d[4],d[5]&&(c+=":"+d[5],d[6]&&(c+=":"+d[6],d[7]&&(c+="."+d[7]))),d[8]&&(c+=" UTC","Z"!=d[8]&&(c+=d[8],d[9]&&(c+=":"+d[9]))),c):"Unrecognized time: "+c},b.prototype.parseInteger=function(a,b){var c=b-a;if(c>4){c<<=3;var d=this.get(a);if(0===d)c-=8;else for(;128>d;)d<<=1,--c;return"("+c+" bit)"}for(var e=0,f=a;b>f;++f)e=e<<8|this.get(f);return e},b.prototype.parseBitString=function(a,b){var c=this.get(a),d=(b-a-1<<3)-c,e="("+d+" bit)";if(20>=d){var f=c;e+=" ";for(var g=b-1;g>a;--g){for(var h=this.get(g),i=f;8>i;++i)e+=h>>i&1?"1":"0";f=0}}return e},b.prototype.parseOctetString=function(a,b){var c=b-a,f="("+c+" byte) ";c>d&&(b=a+d);for(var g=a;b>g;++g)f+=this.hexByte(this.get(g));return c>d&&(f+=e),f},b.prototype.parseOID=function(a,b){for(var c="",d=0,e=0,f=a;b>f;++f){var g=this.get(f);if(d=d<<7|127&g,e+=7,!(128&g)){if(""===c){var h=80>d?40>d?0:1:2;c=h+"."+(d-40*h)}else c+="."+(e>=31?"bigint":d);d=e=0}}return c},c.prototype.typeName=function(){if(this.tag===a)return"unknown";var b=this.tag>>6,c=(this.tag>>5&1,31&this.tag);switch(b){case 0:switch(c){case 0:return"EOC";case 1:return"BOOLEAN";case 2:return"INTEGER";case 3:return"BIT_STRING";case 4:return"OCTET_STRING";case 5:return"NULL";case 6:return"OBJECT_IDENTIFIER";case 7:return"ObjectDescriptor";case 8:return"EXTERNAL";case 9:return"REAL";case 10:return"ENUMERATED";case 11:return"EMBEDDED_PDV";case 12:return"UTF8String";case 16:return"SEQUENCE";case 17:return"SET";case 18:return"NumericString";case 19:return"PrintableString";case 20:return"TeletexString";case 21:return"VideotexString";case 22:return"IA5String";case 23:return"UTCTime";case 24:return"GeneralizedTime";case 25:return"GraphicString";case 26:return"VisibleString";case 27:return"GeneralString";case 28:return"UniversalString";case 30:return"BMPString";default:return"Universal_"+c.toString(16)}case 1:return"Application_"+c.toString(16);case 2:return"["+c+"]";case 3:return"Private_"+c.toString(16)}},c.prototype.reSeemsASCII=/^[ -~]+$/,c.prototype.content=function(){if(this.tag===a)return null;var b=this.tag>>6,c=31&this.tag,f=this.posContent(),g=Math.abs(this.length);if(0!==b){if(null!==this.sub)return"("+this.sub.length+" elem)";var h=this.stream.parseStringISO(f,f+Math.min(g,d));return this.reSeemsASCII.test(h)?h.substring(0,2*d)+(h.length>2*d?e:""):this.stream.parseOctetString(f,f+g)}switch(c){case 1:return 0===this.stream.get(f)?"false":"true";case 2:return this.stream.parseInteger(f,f+g);case 3:return this.sub?"("+this.sub.length+" elem)":this.stream.parseBitString(f,f+g);case 4:return this.sub?"("+this.sub.length+" elem)":this.stream.parseOctetString(f,f+g);case 6:return this.stream.parseOID(f,f+g);case 16:case 17:return"("+this.sub.length+" elem)";case 12:return this.stream.parseStringUTF(f,f+g);case 18:case 19:case 20:case 21:case 22:case 26:return this.stream.parseStringISO(f,f+g);case 30:return this.stream.parseStringBMP(f,f+g);case 23:case 24:return this.stream.parseTime(f,f+g)}return null},c.prototype.toString=function(){return this.typeName()+"@"+this.stream.pos+"[header:"+this.header+",length:"+this.length+",sub:"+(null===this.sub?"null":this.sub.length)+"]"},c.prototype.print=function(b){if(b===a&&(b=""),document.writeln(b+this),null!==this.sub){b+=" ";for(var c=0,d=this.sub.length;d>c;++c)this.sub[c].print(b)}},c.prototype.toPrettyString=function(b){b===a&&(b="");var c=b+this.typeName()+" @"+this.stream.pos;if(this.length>=0&&(c+="+"),c+=this.length,32&this.tag?c+=" (constructed)":3!=this.tag&&4!=this.tag||null===this.sub||(c+=" (encapsulates)"),c+="\n",null!==this.sub){b+=" ";for(var d=0,e=this.sub.length;e>d;++d)c+=this.sub[d].toPrettyString(b)}return c},c.prototype.toDOM=function(){var a=f.tag("div","node");a.asn1=this;var b=f.tag("div","head"),c=this.typeName().replace(/_/g," ");b.innerHTML=c;var d=this.content();if(null!==d){d=String(d).replace(/",c+="Length: "+this.header+"+",c+=this.length>=0?this.length:-this.length+" (undefined)",32&this.tag?c+="
(constructed)":3!=this.tag&&4!=this.tag||null===this.sub||(c+="
(encapsulates)"),null!==d&&(c+="
Value:
"+d+"","object"==typeof oids&&6==this.tag)){var h=oids[d];h&&(h.d&&(c+="
"+h.d),h.c&&(c+="
"+h.c),h.w&&(c+="
(warning!)"))}g.innerHTML=c,a.appendChild(g);var i=f.tag("div","sub");if(null!==this.sub)for(var j=0,k=this.sub.length;k>j;++j)i.appendChild(this.sub[j].toDOM());return a.appendChild(i),b.onclick=function(){a.className="node collapsed"==a.className?"node":"node collapsed"},a},c.prototype.posStart=function(){return this.stream.pos},c.prototype.posContent=function(){return this.stream.pos+this.header},c.prototype.posEnd=function(){return this.stream.pos+this.header+Math.abs(this.length)},c.prototype.fakeHover=function(a){this.node.className+=" hover",a&&(this.head.className+=" hover")},c.prototype.fakeOut=function(a){var b=/ ?hover/;this.node.className=this.node.className.replace(b,""),a&&(this.head.className=this.head.className.replace(b,""))},c.prototype.toHexDOM_sub=function(a,b,c,d,e){if(!(d>=e)){var g=f.tag("span",b);g.appendChild(f.text(c.hexDump(d,e))),a.appendChild(g)}},c.prototype.toHexDOM=function(b){var c=f.tag("span","hex");if(b===a&&(b=c),this.head.hexNode=c,this.head.onmouseover=function(){this.hexNode.className="hexCurrent"},this.head.onmouseout=function(){this.hexNode.className="hex"},c.asn1=this,c.onmouseover=function(){var a=!b.selected;a&&(b.selected=this.asn1,this.className="hexCurrent"),this.asn1.fakeHover(a)},c.onmouseout=function(){var a=b.selected==this.asn1;this.asn1.fakeOut(a),a&&(b.selected=null,this.className="hex")},this.toHexDOM_sub(c,"tag",this.stream,this.posStart(),this.posStart()+1),this.toHexDOM_sub(c,this.length>=0?"dlen":"ulen",this.stream,this.posStart()+1,this.posContent()),null===this.sub)c.appendChild(f.text(this.stream.hexDump(this.posContent(),this.posEnd())));else if(this.sub.length>0){var d=this.sub[0],e=this.sub[this.sub.length-1];this.toHexDOM_sub(c,"intro",this.stream,this.posContent(),d.posStart());for(var g=0,h=this.sub.length;h>g;++g)c.appendChild(this.sub[g].toHexDOM(b));this.toHexDOM_sub(c,"outro",this.stream,e.posEnd(),this.posEnd())}return c},c.prototype.toHexString=function(){return this.stream.hexDump(this.posStart(),this.posEnd(),!0)},c.decodeLength=function(a){var b=a.get(),c=127&b;if(c==b)return c;if(c>3)throw"Length over 24 bits not supported at position "+(a.pos-1);if(0===c)return-1;b=0;for(var d=0;c>d;++d)b=b<<8|a.get();return b},c.hasContent=function(a,d,e){if(32&a)return!0;if(3>a||a>4)return!1;var f=new b(e);3==a&&f.get();var g=f.get();if(g>>6&1)return!1;try{var h=c.decodeLength(f);return f.pos-e.pos+h==d}catch(i){return!1}},c.decode=function(a){a instanceof b||(a=new b(a,0));var d=new b(a),e=a.get(),f=c.decodeLength(a),g=a.pos-d.pos,h=null;if(c.hasContent(e,f,a)){var i=a.pos;if(3==e&&a.get(),h=[],f>=0){for(var j=i+f;a.posd;++d){var f=new b(a[d].value,0),g=c.decodeLength(f);g!=a[d].expected&&document.write("In test["+d+"] expected "+a[d].expected+" got "+g+"\n")}},window.ASN1=c}(),ASN1.prototype.getHexStringValue=function(){var a=this.toHexString(),b=2*this.header,c=2*this.length;return a.substr(b,c)},RSAKey.prototype.parseKey=function(a){try{var b=0,c=0,d=/^\s*(?:[0-9A-Fa-f][0-9A-Fa-f]\s*)+$/,e=d.test(a)?Hex.decode(a):Base64.unarmor(a),f=ASN1.decode(e);if(3===f.sub.length&&(f=f.sub[2].sub[0]),9===f.sub.length){b=f.sub[1].getHexStringValue(),this.n=parseBigInt(b,16),c=f.sub[2].getHexStringValue(),this.e=parseInt(c,16);var g=f.sub[3].getHexStringValue();this.d=parseBigInt(g,16);var h=f.sub[4].getHexStringValue();this.p=parseBigInt(h,16);var i=f.sub[5].getHexStringValue();this.q=parseBigInt(i,16);var j=f.sub[6].getHexStringValue();this.dmp1=parseBigInt(j,16);var k=f.sub[7].getHexStringValue();this.dmq1=parseBigInt(k,16);var l=f.sub[8].getHexStringValue();this.coeff=parseBigInt(l,16)}else{if(2!==f.sub.length)return!1;var m=f.sub[1],n=m.sub[0];b=n.sub[0].getHexStringValue(),this.n=parseBigInt(b,16),c=n.sub[1].getHexStringValue(),this.e=parseInt(c,16)}return!0}catch(o){return!1}},RSAKey.prototype.getPrivateBaseKey=function(){var a={array:[new KJUR.asn1.DERInteger({"int":0}),new KJUR.asn1.DERInteger({bigint:this.n}),new KJUR.asn1.DERInteger({"int":this.e}),new KJUR.asn1.DERInteger({bigint:this.d}),new KJUR.asn1.DERInteger({bigint:this.p}),new KJUR.asn1.DERInteger({bigint:this.q}),new KJUR.asn1.DERInteger({bigint:this.dmp1}),new KJUR.asn1.DERInteger({bigint:this.dmq1}),new KJUR.asn1.DERInteger({bigint:this.coeff})]},b=new KJUR.asn1.DERSequence(a);return b.getEncodedHex()},RSAKey.prototype.getPrivateBaseKeyB64=function(){return hex2b64(this.getPrivateBaseKey())},RSAKey.prototype.getPublicBaseKey=function(){var a={array:[new KJUR.asn1.DERObjectIdentifier({oid:"1.2.840.113549.1.1.1"}),new KJUR.asn1.DERNull]},b=new KJUR.asn1.DERSequence(a);a={array:[new KJUR.asn1.DERInteger({bigint:this.n}),new KJUR.asn1.DERInteger({"int":this.e})]};var c=new KJUR.asn1.DERSequence(a);a={hex:"00"+c.getEncodedHex()};var d=new KJUR.asn1.DERBitString(a);a={array:[b,d]};var e=new KJUR.asn1.DERSequence(a);return e.getEncodedHex()},RSAKey.prototype.getPublicBaseKeyB64=function(){return hex2b64(this.getPublicBaseKey())},RSAKey.prototype.wordwrap=function(a,b){if(b=b||64,!a)return a;var c="(.{1,"+b+"})( +|$\n?)|(.{1,"+b+"})";return a.match(RegExp(c,"g")).join("\n")},RSAKey.prototype.getPrivateKey=function(){var a="-----BEGIN RSA PRIVATE KEY-----\n";return a+=this.wordwrap(this.getPrivateBaseKeyB64())+"\n",a+="-----END RSA PRIVATE KEY-----"},RSAKey.prototype.getPublicKey=function(){var a="-----BEGIN PUBLIC KEY-----\n";return a+=this.wordwrap(this.getPublicBaseKeyB64())+"\n",a+="-----END PUBLIC KEY-----"},RSAKey.prototype.hasPublicKeyProperty=function(a){return a=a||{},a.hasOwnProperty("n")&&a.hasOwnProperty("e")},RSAKey.prototype.hasPrivateKeyProperty=function(a){return a=a||{},a.hasOwnProperty("n")&&a.hasOwnProperty("e")&&a.hasOwnProperty("d")&&a.hasOwnProperty("p")&&a.hasOwnProperty("q")&&a.hasOwnProperty("dmp1")&&a.hasOwnProperty("dmq1")&&a.hasOwnProperty("coeff")},RSAKey.prototype.parsePropertiesFrom=function(a){this.n=a.n,this.e=a.e,a.hasOwnProperty("d")&&(this.d=a.d,this.p=a.p,this.q=a.q,this.dmp1=a.dmp1,this.dmq1=a.dmq1,this.coeff=a.coeff)};var JSEncryptRSAKey=function(a){RSAKey.call(this),a&&("string"==typeof a?this.parseKey(a):(this.hasPrivateKeyProperty(a)||this.hasPublicKeyProperty(a))&&this.parsePropertiesFrom(a))};JSEncryptRSAKey.prototype=new RSAKey,JSEncryptRSAKey.prototype.constructor=JSEncryptRSAKey;var JSEncrypt=function(a){a=a||{},this.default_key_size=parseInt(a.default_key_size)||1024,this.default_public_exponent=a.default_public_exponent||"010001",this.log=a.log||!1,this.key=null};JSEncrypt.prototype.setKey=function(a){this.log&&this.key&&console.warn("A key was already set, overriding existing."),this.key=new JSEncryptRSAKey(a)},JSEncrypt.prototype.setPrivateKey=function(a){this.setKey(a)},JSEncrypt.prototype.setPublicKey=function(a){this.setKey(a)},JSEncrypt.prototype.decrypt=function(a){try{return this.getKey().decrypt(b64tohex(a))}catch(b){return!1}},JSEncrypt.prototype.encrypt=function(a){try{return hex2b64(this.getKey().encrypt(a))}catch(b){return!1}},JSEncrypt.prototype.getKey=function(a){if(!this.key){if(this.key=new JSEncryptRSAKey,a&&"[object Function]"==={}.toString.call(a))return void this.key.generateAsync(this.default_key_size,this.default_public_exponent,a);this.key.generate(this.default_key_size,this.default_public_exponent)}return this.key},JSEncrypt.prototype.getPrivateKey=function(){return this.getKey().getPrivateKey()},JSEncrypt.prototype.getPrivateKeyB64=function(){return this.getKey().getPrivateBaseKeyB64()},JSEncrypt.prototype.getPublicKey=function(){return this.getKey().getPublicKey()},JSEncrypt.prototype.getPublicKeyB64=function(){return this.getKey().getPublicBaseKeyB64()};exports.JSEncrypt = JSEncrypt; 5 | })(JSEncryptExports); 6 | var JSEncrypt = JSEncryptExports.JSEncrypt; 7 | -------------------------------------------------------------------------------- /demo/12_zuocheWithCaptcha.php: -------------------------------------------------------------------------------- 1 | getLineBreak(); 17 | 18 | //登录信息 19 | $username = urlencode('email@qq.com'); 20 | $password = "password"; 21 | 22 | //0. 未登录 23 | $getDataUrl = 'http://www.zuoche.com/welcome.jspx'; 24 | echo 'Before Login: ' . ($autologin->assertContainStr($autologin->getUrl($getDataUrl), '退出') ? '已登录' : '未登录' ) . $lineBreak; 25 | 26 | if(empty($_POST)) { 27 | //1. 初始化登录页 28 | $curl1 = "curl 'https://zuoche.com/login.jspx' -H 'Host: zuoche.com' -H 'User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.10; rv:49.0) Gecko/20100101 Firefox/49.0' -H 'Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8' -H 'Accept-Language: zh-CN,zh;q=0.8,en-US;q=0.5,en;q=0.3' -H 'Accept-Encoding: gzip, deflate, br' -H 'Cookie: z_tttt=01580fcb13570031; Hm_lvt_d91c090e9c1140131a8ac18e9cb36e23=1477733727; Hm_lpvt_d91c090e9c1140131a8ac18e9cb36e23=1477733727; login-check=ok' -H 'Connection: keep-alive' -H 'Upgrade-Insecure-Requests: 1' -H 'Cache-Control: max-age=0'"; 29 | $content = $autologin->execCurl($curl1); 30 | 31 | preg_match('#getverifyimage\.jspx\?verifykey=([^"]+)#is', $content, $match); 32 | 33 | $verifykey = $match[1]; 34 | $codeImgSrc = $match[0]; 35 | ?> 36 |
37 | 38 | 39 | 40 | 41 |
42 | execCurl($curl2); 50 | 51 | //3. 登录成功,锁定cookie的更新,直接访问已登录页面内容(类似采集内容),演示cookie锁定多次采集效果与cookie失效效果 52 | $autologin->lockLastCookieFile(); 53 | echo 'After Login: ' . ($autologin->assertContainStr($autologin->getUrl($getDataUrl), '退出') ? '已登录' : '未登录' ) . $lineBreak; 54 | echo $autologin->getUrl($getDataUrl) . $lineBreak; 55 | } 56 | -------------------------------------------------------------------------------- /demo/14_360doc.php: -------------------------------------------------------------------------------- 1 | execCurl($curl1); 19 | 20 | //2. 依赖cookie获取 21 | $curl2 = "curl 'http://www.360doc.com/clippertool/getnoteclipperASHX.ashx?type=10&jsoncallback=jsonp1480652930568' -H 'Host: www.360doc.com' -H 'User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.10; rv:50.0) Gecko/20100101 Firefox/50.0' -H 'Accept: */*' -H 'Accept-Language: zh-CN,zh;q=0.8,en-US;q=0.5,en;q=0.3' -H 'Accept-Encoding: gzip, deflate' -H 'Referer: http://www.360doc.com/' -H 'Connection: keep-alive' -H 'Pragma: no-cache' -H 'Cache-Control: no-cache'"; 22 | $autologin->execCurl($curl2); 23 | 24 | //3. 提交登录表单 25 | $curl3 = "curl 'http://www.360doc.com/ajax/login/login.ashx?email=100000000@qq.com&pws=2b6b12e433588471822eac2b6e8004b2&isr=0&login=1' -X POST -H 'Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8' -H 'Accept-Encoding: gzip, deflate' -H 'Accept-Language: zh-CN,zh;q=0.8,en-US;q=0.5,en;q=0.3' -H 'Connection: keep-alive' -H 'Content-Length: 0' -H 'Content-Type: text/xml' -H 'Cookie: 360docsn=Q8PM6PS1DGHCOHWL; Hm_lvt_d86954201130d615136257dde062a503=1479284689,1480563198,1480563274; Hm_lpvt_d86954201130d615136257dde062a503=1480644777' -H 'Host: www.360doc.com' -H 'Referer: http://www.360doc.com/' -H 'User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.10; rv:50.0) Gecko/20100101 Firefox/50.0'"; 26 | $content = $autologin->execCurl($curl3); 27 | 28 | $autologin->lockLastCookieFile(); 29 | echo $autologin->getUrl('http://www.360doc.com/mymsg.aspx'); 30 | -------------------------------------------------------------------------------- /demo/15_downloadWizNote.php: -------------------------------------------------------------------------------- 1 | getLineBreak(); 34 | 35 | // 步骤1:登录网页版为知笔记 https://note.wiz.cn/web 36 | // 步骤2:查看近期笔记,并下拉刷新直到全部显示笔记 37 | // 步骤3:利用下面的js,在控制台运行得到所有的笔记链接 38 | // 步骤4:将上面得到的笔记地址,填入$notes数组 39 | // 步骤5:运行php 15_downloadWizNote.php开始下载笔记 (注:加密笔记无法下载正确内容,考虑临时取消加密) 40 | // 步骤6:解析笔记json,存储为html 41 | /* 42 | 43 | //控制台运行js代码 44 | var res = ''; 45 | var token = document.cookie.match(/token=([^;]+)/)[1] 46 | $(".note-list-item").each(function(){ 47 | var title = $(this).find(".title").attr('title'); 48 | res += '"https://note.wiz.cn/api/document/info?client_type=web2.0&api_version=6&token=' 49 | +token+'&kb_guid='+$(this).attr('data-kbguid')+'&document_guid='+$(this).attr('data-docguid') 50 | +'&_='+(Math.floor(new Date().getTime() / 1000))+(parseInt(Math.random()*1000))+'", //' +title+ "\n"; 51 | }); 52 | console.log(res); 53 | 54 | */ 55 | 56 | //所有笔记采集链接,利用js在控制台运行获取 57 | $notes = array( 58 | 'https://note.wiz.cn/api/document/info?client_type=web2.0&api_version=6&token=ebeda6e29d35b1d113a7190ce8fd268at75l8wpsw8ybta&kb_guid=781635a1-97b6-44ee-a2c9-33ead2a3ab1e&document_guid=31efcb50-36dc-4c1c-9576-6b103cd219e1&_=1481679224449', 59 | 'https://note.wiz.cn/api/document/info?client_type=web2.0&api_version=6&token=ebeda6e29d35b1d113a7190ce8fd268at75l8wpsw8ybta&kb_guid=781635a1-97b6-44ee-a2c9-33ead2a3ab1e&document_guid=10de4633-d3ed-441b-ac1a-9e899cda640b&_=1481679224449', 60 | ); 61 | 62 | //测试发送信息 63 | foreach($notes as $noteUrl) { 64 | //网页版登录后,获取一条笔记加载的curl命令 65 | $curl = "curl 'https://note.wiz.cn/api/document/info?client_type=web2.0&api_version=6&token=ebeda6e29d35b1d113a7190ce8fd268at75l8wpsw8ybta&kb_guid=781635a1-97b6-44ee-a2c9-33ead2a3ab1e&document_guid=fcb921c1-8dbd-46a1-af24-7a43343c18c5&_=1481679224449' -H 'Accept: application/json, text/javascript, */*; q=0.01' -H 'Accept-Encoding: gzip, deflate, br' -H 'Accept-Language: zh-CN,zh;q=0.8,en-US;q=0.5,en;q=0.3' -H 'Connection: keep-alive' -H 'Cookie: Hm_lvt_df6808d18fab4a1df17434a064069692=1481528227,1481678379; Hm_lpvt_df6808d183a14a1dfa7454a064069692=1481679228; token=ebeda6e29d35b1d113a7190ce8fd268at75l8wpsw8ybta; wizID=1000000%40qq.com; CertNo=dd233f28e1460fde5ef72d63c00a1e6f13d3790cf90a0e2d0f0c148a504adee3b893423f0d4341aad03470f6c79b620b; express:sess=eyJrYnMiOiIsNzExMmQ1Yj15Y2VjZSZkYzA3OTdkZjMxN2YwMTE0YTUifQ==; express:sess.sig=ioeZRP1j19691rDqGo6ZOnjHTUQ' -H 'Host: note.wiz.cn' -H 'Referer: https://note.wiz.cn/web?dc=f2b91bc1-8d1d-46a1-aff4-7a43c44c28c5&cmd=kw%2C&kb=78125a1-97b6-441e-12c9-33e322a3ab1e' -H 'User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.10; rv:50.0) Gecko/20100101 Firefox/50.0' -H 'X-Requested-With: XMLHttpRequest'"; 66 | $content = $autologin->execCurlWithCookie($curl); 67 | //锁定cookie 68 | $autologin->lockLastCookieFile(); 69 | 70 | //替换为最新的token 71 | $tokenPattern = '#token=([^&]+)#'; 72 | preg_match($tokenPattern, $curl, $tokenMatch); 73 | $noteUrl = preg_replace($tokenPattern, 'token=' . $tokenMatch[1], $noteUrl); 74 | 75 | //替换为最新的kb_guid 76 | $kbGuidPattern = '#kb_guid=([^&]+)#'; 77 | preg_match($kbGuidPattern, $curl, $kbGuidMatch); 78 | $noteUrl = preg_replace($tokenPattern, 'kb_guid=' . $kbGuidMatch[1], $noteUrl); 79 | 80 | echo "正在下载笔记:{$noteUrl}\n"; 81 | 82 | $noteContent = $autologin->getUrl($noteUrl); 83 | 84 | //使用文档id作为文件名 85 | preg_match('#document_guid=([^&]+)#', $noteUrl, $documentGuidMatch); 86 | $filename = $documentGuidMatch[1] . '.json'; 87 | 88 | //存储笔记json 89 | file_put_contents($jsonDir . $filename, $noteContent); 90 | } 91 | 92 | //解析json存入html文件 93 | foreach(glob($jsonDir . '*.json') as $file) { 94 | $htmlFile = str_replace('/json/', '/html/', substr($file, 0, -4) . 'html'); 95 | $content = file_get_contents($file); 96 | $dataArr = json_decode($content, true); 97 | if(empty($dataArr['document_info']['document_body'])) { 98 | echo "{$file} 无法解析,请确认是否为加密笔记,加密笔记无法下载内容。\n"; 99 | continue; 100 | } 101 | $document = $dataArr['document_info']['document_body']; 102 | file_put_contents($htmlFile, $document); 103 | } 104 | die; 105 | -------------------------------------------------------------------------------- /demo/16_commonCurl/code.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Zjmainstay/php-curl/7a55c6f4f3bcc2d52b82227d9bea9cc450227de5/demo/16_commonCurl/code.png -------------------------------------------------------------------------------- /demo/16_commonCurl/curlPage.cookie.txt: -------------------------------------------------------------------------------- 1 | # Netscape HTTP Cookie File 2 | # http://curl.haxx.se/docs/http-cookies.html 3 | # This file was generated by libcurl! Edit at your own risk. 4 | 5 | demo.zjmainstay.cn FALSE / FALSE 0 PHPSESSID 9tp5iahuu6m28r1s9tbb7ckbl1 6 | -------------------------------------------------------------------------------- /demo/16_commonCurl/curlPage.php: -------------------------------------------------------------------------------- 1 | $value) { 64 | curl_setopt($ch, $key, $value); //自定义OPT 65 | } 66 | } 67 | //执行 68 | $content = curl_exec($ch); 69 | if($error = curl_error($ch)) { 70 | //log error 71 | error_log($error); 72 | } 73 | curl_close($ch); 74 | 75 | return $content; 76 | } 77 | 78 | #测试http 79 | $url = 'http://api.zjmainstay.cn'; 80 | echo "http url ok: ", curlPage($url) , "\n"; 81 | 82 | #测试https 83 | $url = 'https://api.zjmainstay.cn'; 84 | echo "https url ok: ", curlPage($url) , "\n"; 85 | 86 | #测试缺少referere 87 | $url = 'http://demo.zjmainstay.cn/php/curl/search_refer.php'; 88 | $post = array( 89 | 'wd' => urlencode('php'), 90 | ); 91 | echo "no referer fail: ", substr(curlPage($url, $post), 0, 100) , "\n"; 92 | 93 | #测试使用referer 和 post数据 94 | $url = 'http://demo.zjmainstay.cn/php/curl/search_refer.php'; 95 | $post = array( 96 | 'wd' => urlencode('php'), 97 | ); 98 | $header = array( 99 | 'Referer: http://demo.zjmainstay.cn/', 100 | ); 101 | echo "referer in header ok: ", preg_replace('#\s+#', '', substr(curlPage($url, $post, $header), 0, 100)) , "\n"; 102 | 103 | #测试超时 104 | $url = 'http://demo.zjmainstay.cn/php/curl/sleep3seconds.php'; 105 | echo "timeout in 1's fail: ", substr(curlPage($url, $post, $header, array(), false, false, 1), 0, 100) , "\n"; 106 | 107 | #测试gzip正常 108 | $url = 'http://news.sohu.com/'; 109 | echo "gzip is ok: ", substr(curlPage($url), 0, 100) , "\n"; 110 | 111 | #测试301正常(没有看到301 Move) 112 | $url = 'http://zjmainstay.cn'; 113 | echo "301 is ok: ", substr(curlPage($url), 0, 100) , "\n"; 114 | 115 | #测试存储cookie成功 116 | $url = 'http://demo.zjmainstay.cn/jquery/autoCheckCaptcha/createcode.php?t=' . rand(100000, 999999); 117 | $saveCookieFile = __DIR__ . '/curlPage.cookie.txt'; 118 | if(file_exists($saveCookieFile)) { @unlink($saveCookieFile); } 119 | $imgContent = curlPage($url, false, false, array(), $saveCookieFile); 120 | $codeFile = __DIR__ . '/code.png'; 121 | file_put_contents($codeFile, $imgContent); 122 | echo "save cookie is ok: ", file_get_contents($saveCookieFile) , "\n"; 123 | 124 | echo "请输入一个验证码( {$codeFile} ):"; 125 | $code = trim(fgets(STDIN)); 126 | 127 | #测试使用cookie 128 | $url = 'http://demo.zjmainstay.cn/jquery/autoCheckCaptcha/checkcode.php'; 129 | $post = array( 130 | 'code' => $code, //手动填写验证码并提交运行 131 | ); 132 | echo "use cookie is ok when status=1: ", curlPage($url, $post, false, array(), false, $saveCookieFile) , "\n"; 133 | 134 | #测试添加额外opt 135 | $url = 'http://zjmainstay.cn'; 136 | $content = curlPage($url, array(), false, array( 137 | CURLOPT_FOLLOWLOCATION => FALSE, 138 | CURLOPT_HEADER => TRUE, 139 | )); 140 | echo "get url with no follow(302) and get header info: \n" , substr($content, 0, 200), "\n"; 141 | -------------------------------------------------------------------------------- /demo/17_dev.360.cn_STDINCaptcha.php: -------------------------------------------------------------------------------- 1 | getLineBreak(); 17 | 18 | $username = urlencode('100000@qq.com'); //登录邮箱 19 | $password = '密码加密串'; //利用浏览器登录后,复制加密密码串填入 20 | 21 | //0. 未登录 22 | $getDataUrl = "curl 'http://dev.360.cn/dev/getuser?callback=onData&_=1489659410069' -H 'Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8' -H 'Accept-Encoding: gzip, deflate' -H 'Accept-Language: zh-CN,zh;q=0.8,en-US;q=0.5,en;q=0.3' -H 'Cache-Control: max-age=0' -H 'Connection: keep-alive' -H 'Cookie: test_cookie_enable=null' -H 'Host: dev.360.cn' -H 'Referer: http://dev.360.cn/mod/developer/?_=186613593&from=mobile' -H 'Upgrade-Insecure-Requests: 1' -H 'User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.10; rv:52.0) Gecko/20100101 Firefox/52.0'"; 23 | echo 'Before Login: ' . $autologin->execCurl($getDataUrl) . $lineBreak; 24 | 25 | //1. 首页 26 | $curl1 = "curl 'http://dev.360.cn/' -H 'Host: dev.360.cn' -H 'User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.10; rv:52.0) Gecko/20100101 Firefox/52.0' -H 'Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8' -H 'Accept-Language: zh-CN,zh;q=0.8,en-US;q=0.5,en;q=0.3' -H 'Accept-Encoding: gzip, deflate' -H 'Connection: keep-alive' -H 'Upgrade-Insecure-Requests: 1' -H 'Cache-Control: max-age=0'"; 27 | $content = $autologin->execCurl($curl1); 28 | 29 | //2. 获取验证码链接 30 | $curl2 = "curl 'http://login.360.cn/?callback=jQuery19109780439789015878_1489658824142&src=pcw_open_app&from=pcw_open_app&charset=UTF-8&requestScema=http&o=sso&m=checkNeedCaptcha&account=hzgdys%40163.com&captchaApp=i360&_=1489658824143' -H 'Accept: */*' -H 'Accept-Encoding: gzip, deflate' -H 'Accept-Language: zh-CN,zh;q=0.8,en-US;q=0.5,en;q=0.3' -H 'Connection: keep-alive' -H 'Cookie: __guid=69710341.1799766187254211600.1489658825084.8904' -H 'Host: login.360.cn' -H 'Referer: http://dev.360.cn/' -H 'User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.10; rv:52.0) Gecko/20100101 Firefox/52.0'"; 31 | $content = $autologin->execCurl($curl2); 32 | $json = substr(str_replace('jQuery19109780439789015878_1489658824142(', '', $content), 0, -1); 33 | $jsonToArr = json_decode($json, true); 34 | 35 | $captchaUrl = $jsonToArr['captchaUrl']; 36 | 37 | //3. 读取验证码 38 | $curl3 = "curl '{$captchaUrl}' -H 'Accept: */*' -H 'Accept-Encoding: gzip, deflate' -H 'Accept-Language: zh-CN,zh;q=0.8,en-US;q=0.5,en;q=0.3' -H 'Connection: keep-alive' -H 'Cookie: __guid=69710341.1799766187254211600.1489658825084.8904' -H 'Host: passport.360.cn' -H 'Referer: http://dev.360.cn/' -H 'User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.10; rv:52.0) Gecko/20100101 Firefox/52.0'"; 39 | $content = $autologin->execCurl($curl3); 40 | $codeFile = __DIR__ . '/code.png'; 41 | file_put_contents($codeFile, $content); 42 | echo "请输入一个验证码( {$codeFile} ):"; 43 | $captcha = trim(fgets(STDIN)); 44 | 45 | //4. 获取token 46 | $curl4 = "curl 'https://login.360.cn/?func=jQuery19109780439789015878_1489658824142&src=pcw_open_app&from=pcw_open_app&charset=UTF-8&requestScema=https&o=sso&m=getToken&userName={$username}&_=1489658824144' -H 'Host: login.360.cn' -H 'User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.10; rv:52.0) Gecko/20100101 Firefox/52.0' -H 'Accept: */*' -H 'Accept-Language: zh-CN,zh;q=0.8,en-US;q=0.5,en;q=0.3' -H 'Accept-Encoding: gzip, deflate, br' -H 'Referer: http://dev.360.cn/' -H 'Cookie: __guid=69710341.1799766187254211600.1489658825084.8904' -H 'Connection: keep-alive'"; 47 | $content = $autologin->execCurl($curl4); 48 | $json = substr(str_replace('jQuery19109780439789015878_1489658824142(', '', $content), 0, -1); 49 | $jsonToArr = json_decode($json, true); 50 | $token = $jsonToArr['token']; 51 | 52 | //5. 提交 53 | $curl5 = "curl 'https://login.360.cn/' -H 'Host: login.360.cn' -H 'User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.10; rv:52.0) Gecko/20100101 Firefox/52.0' -H 'Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8' -H 'Accept-Language: zh-CN,zh;q=0.8,en-US;q=0.5,en;q=0.3' -H 'Accept-Encoding: gzip, deflate, br' -H 'Referer: http://dev.360.cn/' -H 'Cookie: __guid=69710341.1799766187254211600.1489658825084.8904' -H 'Connection: keep-alive' -H 'Upgrade-Insecure-Requests: 1' -H 'Content-Type: application/x-www-form-urlencoded' --data 'src=pcw_open_app&from=pcw_open_app&charset=UTF-8&requestScema=https&o=sso&m=login&lm=0&captFlag=1&rtype=data&validatelm=0&isKeepAlive=1&captchaApp=i360&userName={$username}&type=normal&account={$username}&password={$password}&captcha={$captcha}&token={$token}&proxy=http%3A%2F%2Fdev.360.cn%2Fpsp_jump.html&callback=QiUserJsonp658825108&func=QiUserJsonp658825108'"; 54 | $content = $autologin->execCurl($curl5); 55 | // var_dump($content); 56 | 57 | //6. 回调1 login.360.cn 58 | $curl6 = "curl 'https://login.360.cn/?func=jQuery19109780439789015878_1489658824152&src=pcw_open_app&from=pcw_open_app&charset=UTF-8&requestScema=https&o=sso&m=setcookie&s=c3k%3Ce%2CA%3Bgjhi3%3EtN-%7C+dHG*j*%22UkWCe%5Cw%7C_1rT%2BRGBZz%7Bqe%40m%60o%22s0!u)dr%3A8GOvKA_T%2B%23wA%3AgPKAJxN%2BH%7C%24aMR%5Cc_79ssF4k%3Ey+J(7!%24H1Jr%3EIbH%2F7%256s.RV%23%5Cdtc!pB%3A%3FBnh3gqq%5Dm!+T(ppp%2FS1SM%25_Jb4Rdx%3F8L%3DLyO8eyith_8F%5C-%7CCrcP*7%3BBFe%40z!hq%261%2B%3Fe%5D4am%7D)b%22A_%40%3F%3CbPjNx%26%7DFe(DPzLn%5C0z%2F&_=1489658824153' -H 'Host: login.360.cn' -H 'User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.10; rv:52.0) Gecko/20100101 Firefox/52.0' -H 'Accept: */*' -H 'Accept-Language: zh-CN,zh;q=0.8,en-US;q=0.5,en;q=0.3' -H 'Accept-Encoding: gzip, deflate, br' -H 'Referer: http://dev.360.cn/' -H 'Cookie: __guid=69710341.1799766187254211600.1489658825084.8904' -H 'Connection: keep-alive'"; 59 | $content = $autologin->execCurl($curl6); 60 | 61 | //7. 回调2 login.360.cn 62 | $curl7 = "curl 'http://login.360.cn/?callback=jQuery19109780439789015878_1489658824154&src=pcw_open_app&from=pcw_open_app&charset=UTF-8&requestScema=http&o=sso&m=info&show_name_flag=1&head_type=b&_=1489658824160' -H 'Accept: */*' -H 'Accept-Encoding: gzip, deflate' -H 'Accept-Language: zh-CN,zh;q=0.8,en-US;q=0.5,en;q=0.3' -H 'Connection: keep-alive' -H 'Cookie: __guid=69710341.1799766187254211600.1489658825084.8904' -H 'Host: login.360.cn' -H 'Referer: http://dev.360.cn/' -H 'User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.10; rv:52.0) Gecko/20100101 Firefox/52.0'"; 63 | $content = $autologin->execCurl($curl7); 64 | // var_dump($content); 65 | 66 | //8. 登录成功,锁定cookie的更新,直接访问已登录页面内容(类似采集内容),演示cookie锁定多次采集效果与cookie失效效果 67 | $autologin->lockLastCookieFile(); 68 | echo 'After Login 1(with_cookie): ' . $autologin->execCurl($getDataUrl) . $lineBreak; 69 | $autologin->removeLastCookie(); 70 | echo 'After Login 2(without_cookie): ' . $autologin->execCurl($getDataUrl) . $lineBreak; 71 | -------------------------------------------------------------------------------- /demo/19_www.tianyancha.com.php: -------------------------------------------------------------------------------- 1 | execCurl($curl); 28 | // var_dump($content); 29 | 30 | //2. 统计 31 | /* 32 | //对应js 33 | _tongJi = function(companyName, service, $q) { 34 | var deferred = $q.defer(); 35 | return service.tongji(companyName).then(function(data) { 36 | for (var arr = data.data.data.v.split(","), fnStr = "", i = 0; i < arr.length; i++) fnStr += String.fromCharCode(arr[i]); 37 | eval(fnStr), 38 | deferred.resolve() 39 | }, 40 | function(e) { (403 == e.status || 404 == e.status || 501 == e.status || 502 == e.status || 503 == e.status || 504 == e.status) && QueryService.errorMassageSend(e.status) 41 | }), 42 | deferred.promise 43 | } 44 | */ 45 | $random = time() . rand(100,999); 46 | $curl = "curl 'http://www.tianyancha.com/tongji/{$searchKey}.json?random={$random}' -H 'Host: www.tianyancha.com' -H 'User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.10; rv:52.0) Gecko/20100101 Firefox/52.0' -H 'Accept: application/json, text/plain, */*' -H 'Accept-Language: zh-CN,zh;q=0.8,en-US;q=0.5,en;q=0.3' --compressed -H 'Tyc-From: normal' -H 'Referer: http://www.tianyancha.com/search?key={$searchKey}&checkFrom=searchBox' -H 'Cookie: aliyungf_tc=AQAAAPZekiabgwQAyl8XDgCN/TtlujOh; TYCID=387bf43d7b7b483ebcdf4e877a912dc6; tnet=14.23.95.202; _pk_id.1.e431=06a39c0c47b56b73.1492395992.1.1492398258.1492395992.; _pk_ses.1.e431=*; gr_user_id=bea87b53-255e-4110-b23a-0be163ed57f1; gr_session_id_869c1f8ef123f88b=fe5a8a32-50d0-4eac-b30c-5c9c0c674712; Hm_lvt_e92c8d65d92d534b0fc290df538b4758=1492395993; Hm_lpvt_e92c8d65d92d534b0fc290df538b4758=1492398258; paaptp=dc8bd40bc98ddb35b74c80efedd60de3ed9ccf63c705bc19e815b79e5729b; token=b9bef624b51d4d278827803ed618f2b3; _utm=03492b4af4b3429ea43988dc944b8f43; _pk_id.6835.e431=1d6b2bfd25408756.1492396001.1.1492398258.1492396001.; _pk_ses.6835.e431=*; RTYCID=a5c8142e447f4601859c85d0ba826e29' -H 'Connection: keep-alive'"; 47 | $content = $autologin->execCurl($curl); 48 | $dataArr = json_decode($content, true); 49 | $charsArr = explode(',', $dataArr['data']['v']); 50 | $realChar = ''; 51 | foreach($charsArr as $char) { 52 | $realChar .= chr($char); 53 | } 54 | preg_match("#token=([^;]+)#", $realChar, $match); 55 | $token = $match[1]; 56 | 57 | //3. 数据 58 | $curl = "curl 'http://www.tianyancha.com/v2/search/{$searchKey}.json?' -H 'Host: www.tianyancha.com' -H 'User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.10; rv:52.0) Gecko/20100101 Firefox/52.0' -H 'Accept: application/json, text/plain, */*' -H 'Accept-Language: zh-CN,zh;q=0.8,en-US;q=0.5,en;q=0.3' --compressed -H 'Tyc-From: normal' -H 'loop: null' -H 'CheckError: check' -H 'Referer: http://www.tianyancha.com/search?key={$searchKey}&checkFrom=searchBox' -H 'Cookie: aliyungf_tc=AQAAAPZekiabgwQAyl8XDgCN/TtlujOh; TYCID=387bf43d7b7b483ebcdf4e877a912dc6; tnet=14.23.95.202; _pk_id.1.e431=06a39c0c47b56b73.1492395992.1.1492398732.1492395992.; _pk_ses.1.e431=*; gr_user_id=bea87b53-255e-4110-b23a-0be163ed57f1; gr_session_id_869c1f8ef123f88b=fe5a8a32-50d0-4eac-b30c-5c9c0c674712; Hm_lvt_e92c8d65d92d534b0fc290df538b4758=1492395993; Hm_lpvt_e92c8d65d92d534b0fc290df538b4758=1492398732; paaptp=4fd9f7303262c59b3d0fc19092ffd756ba8731bc790119a4fa15b79e573f9; token=669baeb13d1d4979b19ce6aa4d0164c2; _utm=e30a65104ce74c8a85a2d855cfcec817; _pk_id.6835.e431=1d6b2bfd25408756.1492396001.1.1492398258.1492396001.; _pk_ses.6835.e431=*; RTYCID=a5c8142e447f4601859c85d0ba826e29' -H 'Connection: keep-alive' -H 'Cache-Control: max-age=0'"; 59 | $content = $autologin->execCurl($curl, function($parseCurlResult) use ($token) { 60 | $parseCurlResult['header'][] = "Cookie:token={$token}"; 61 | return $parseCurlResult; 62 | }); 63 | 64 | var_dump($content); 65 | -------------------------------------------------------------------------------- /demo/1_simpleAutoLogin.php: -------------------------------------------------------------------------------- 1 | getLineBreak(); 17 | 18 | //0. 未登录 19 | $getDataUrl = 'http://demo.zjmainstay.cn/js/simpleAjax/loginResult.php'; 20 | echo 'Before Login: ' . $autologin->getUrl($getDataUrl) . $lineBreak; 21 | 22 | //1. 初始化登录页 23 | $curl1 = "curl 'http://demo.zjmainstay.cn/js/simpleAjax/' -H 'Host: demo.zjmainstay.cn' -H 'User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.10; rv:47.0) Gecko/20100101 Firefox/47.0' -H 'Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8' -H 'Accept-Language: zh-CN,zh;q=0.8,en-US;q=0.5,en;q=0.3' -H 'Accept-Encoding: gzip, deflate' -H 'Cookie: Hm_lvt_1526d5aecf5561ef9401f7c7b7842a97=1468327822,1468327904,1468341636,1468411918; Hm_lpvt_1526d5aecf5561ef9401f7c7b7842a97=1468421526' -H 'Connection: keep-alive' -H 'If-Modified-Since: Mon, 27 Oct 2014 08:31:18 GMT' -H 'If-None-Match: \"32e-453-506635ac5e180\"' -H 'Cache-Control: max-age=0'"; 24 | $content = $autologin->execCurl($curl1); 25 | 26 | //2. 提交登录表单 27 | $curl2 = "curl 'http://demo.zjmainstay.cn/js/simpleAjax/doPost.php' -H 'Host: demo.zjmainstay.cn' -H 'User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.10; rv:47.0) Gecko/20100101 Firefox/47.0' -H 'Accept: application/json, text/javascript, */*; q=0.01' -H 'Accept-Language: zh-CN,zh;q=0.8,en-US;q=0.5,en;q=0.3' -H 'Accept-Encoding: gzip, deflate' -H 'Content-Type: application/x-www-form-urlencoded; charset=UTF-8' -H 'X-Requested-With: XMLHttpRequest' -H 'Referer: http://demo.zjmainstay.cn/js/simpleAjax/' -H 'Cookie: Hm_lvt_1526d5aecf5561ef9401f7c7b7842a97=1468327822,1468327904,1468341636,1468411918; Hm_lpvt_1526d5aecf5561ef9401f7c7b7842a97=1468421526' -H 'Connection: keep-alive' --data 'username=demousername'"; 28 | $realUsername = 'Zjmainstay'; 29 | //前置处理,替换错误的用户名(也可以在上面填充curl的时候,使用变量替换对应内容) 30 | $content = $autologin->execCurl($curl2, function($parseCurlResult) use ($realUsername) { 31 | $parseCurlResult['post'] = str_replace('=demousername', "={$realUsername}", $parseCurlResult['post']); 32 | return $parseCurlResult; 33 | }); 34 | 35 | //3. 登录成功,锁定cookie的更新,直接访问已登录页面内容(类似采集内容),演示cookie锁定多次采集效果与cookie失效效果 36 | $autologin->lockLastCookieFile(); 37 | echo 'After Login 1(with_cookie): ' . $autologin->getUrl($getDataUrl) . $lineBreak; 38 | echo 'After Login 2(with_cookie): ' . $autologin->getUrl($getDataUrl) . $lineBreak; 39 | $autologin->removeLastCookie(); 40 | echo 'After Login 3(without_cookie): ' . $autologin->getUrl($getDataUrl) . $lineBreak; 41 | -------------------------------------------------------------------------------- /demo/20_u.mumayi.com_OnlineCaptcha.php: -------------------------------------------------------------------------------- 1 | execCurl($getDataUrl); 10 | 11 | $curl_code = "curl 'http://u.mumayi.com/oauth/?m=Oauth&a=getmycode&9414.216286713418' -H 'Host: u.mumayi.com' -H 'User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.10; rv:53.0) Gecko/20100101 Firefox/53.0' -H 'Accept: */*' -H 'Accept-Language: zh-CN,zh;q=0.8,en-US;q=0.5,en;q=0.3' --compressed -H 'Referer: http://u.mumayi.com/oauth/?m=Oauth&a=authorize&client_id=100004&redirect_uri=http://pay.mumayi.com/?a=callback&response_type=code&changeuser=y' -H 'Cookie: PHPSESSID=g705ctncodie3rd2df50tlg585' -H 'Connection: keep-alive' -H 'Cache-Control: max-age=0'"; 12 | $content = $autologin->execCurl($curl_code); 13 | 14 | //保存cookie 15 | file_put_contents($loginCookieFile, $autologin->getLastCookieContent()); 16 | ?> 17 |
18 | 19 | 20 | 21 |
22 | setLastCookieFile($loginCookieFile); 25 | $username = 'qq'; 26 | $password = "password"; 27 | $captcha = isset($_REQUEST["captcha"]) ? $_REQUEST["captcha"] : ""; 28 | $curl_login = "curl 'http://u.mumayi.com/oauth/?m=Oauth&a=authorize' -H 'Host: u.mumayi.com' -H 'User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.10; rv:53.0) Gecko/20100101 Firefox/53.0' -H 'Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8' -H 'Accept-Language: zh-CN,zh;q=0.8,en-US;q=0.5,en;q=0.3' --compressed -H 'Content-Type: application/x-www-form-urlencoded' -H 'Referer: http://u.mumayi.com/oauth/?m=Oauth&a=authorize&client_id=100004&redirect_uri=http://pay.mumayi.com/?a=callback&response_type=code&changeuser=y' -H 'Cookie: PHPSESSID=g705ctncodie3rd2df50tlg585' -H 'Connection: keep-alive' -H 'Upgrade-Insecure-Requests: 1' --data 'usernm={$username}&passwd={$password}&mycode={$captcha}&scopelist%5B%5D=basicinfo&scopelist%5B%5D=bbsinfo&client_id=100004&response_type=code&redirect_uri=http%3A%2F%2Fpay.mumayi.com%2F%3Fa%3Dcallback&state=&scope=&display=&accept=Yep'"; 29 | 30 | $content = $autologin->execCurl($curl_login); 31 | unlink($loginCookieFile); //删除临时文件 32 | echo $content; 33 | die; 34 | } 35 | 36 | -------------------------------------------------------------------------------- /demo/22_tools.cnforex.com-phantomjs-parse-js.php: -------------------------------------------------------------------------------- 1 | getLineBreak(); 15 | 16 | //初始化获得js内容 17 | $getUrl = "curl 'http://tools.cnforex.com/hangqing/app/app.html'"; 18 | $content = $autologin->execCurl($getUrl); 19 | 20 | $jsPattern = '#window.onload=.*}#is'; 21 | preg_match($jsPattern, $content, $match); 22 | $js = $match[0]; 23 | 24 | //替换js内容,打印目标数据,加入phantom退出方法 25 | $js = str_replace('eval("qo=eval;qo(po);");', 'console.log(po);phantom.exit();', $js); 26 | 27 | //解析js 28 | $file = '/tmp/tools.cnforex.com.js'; 29 | file_put_contents($file, $js); 30 | $result = `/usr/bin/phantomjs $file`; 31 | echo $result; 32 | unlink($file); 33 | 34 | //获取页面访问cookie 35 | $pattern = '#_ydclearance=([^;]+)#is'; 36 | preg_match($pattern, $result, $match); 37 | $_ydclearance = $match[1]; 38 | 39 | //携带cookie请求 40 | $content = $autologin->execCurl($getUrl, function($parseCurlResult) use ($_ydclearance) { 41 | $parseCurlResult['header'][] = "Cookie: _ydclearance={$_ydclearance}"; 42 | return $parseCurlResult; 43 | }); 44 | 45 | echo $content; 46 | -------------------------------------------------------------------------------- /demo/26_publish.haodanku.com.php: -------------------------------------------------------------------------------- 1 | getLineBreak(); 17 | 18 | $phone = '手机号'; //手机号 19 | $password = '密码'; //密码 20 | 21 | $getDataUrl = "curl 'http://publish.haodanku.com/index/index.html'"; 22 | echo 'Before Login: ' . isLogin($autologin->execCurl($getDataUrl)) . $lineBreak; 23 | 24 | //1. 首页 25 | $curl = "curl 'http://publish.haodanku.com/login/index.html' -H 'Host: publish.haodanku.com' -H 'User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.10; rv:55.0) Gecko/20100101 Firefox/55.0' -H 'Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8' -H 'Accept-Language: zh-CN,zh;q=0.8,en-US;q=0.5,en;q=0.3' --compressed -H 'Connection: keep-alive' -H 'Upgrade-Insecure-Requests: 1' -H 'Cache-Control: max-age=0'"; 26 | $content = $autologin->execCurl($curl); 27 | 28 | //2. 读取验证码 29 | $curl = "curl 'http://publish.haodanku.com/authcode/index?t=?0.94427897345314' -H 'Host: publish.haodanku.com' -H 'User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.10; rv:55.0) Gecko/20100101 Firefox/55.0' -H 'Accept: */*' -H 'Accept-Language: zh-CN,zh;q=0.8,en-US;q=0.5,en;q=0.3' --compressed -H 'Referer: http://publish.haodanku.com/login/index.html' -H 'Cookie: PHPSESSID=gle0jjtlli5r55gk4mru9rsq61; __root_domain_v=.haodanku.com; _qddaz=QD.2oyyj7.cf30mz.j7vjw8i7; _qdda=3-1.91z3j; _qddab=3-x0k9tx.j7vjw8wd; _qddamta_2852060675=3-0; UM_distinctid=15ea870b69a479-02f04379124def8-49546e-13c680-15ea870b69b28a' -H 'Connection: keep-alive'"; 30 | $content = $autologin->execCurl($curl); 31 | $codeFile = __DIR__ . '/code.png'; 32 | file_put_contents($codeFile, $content); 33 | echo "请输入一个验证码( {$codeFile} ):"; 34 | $captcha = trim(fgets(STDIN)); 35 | 36 | //3. 提交 37 | $curl = "curl 'http://publish.haodanku.com/login' -H 'Host: publish.haodanku.com' -H 'User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.10; rv:55.0) Gecko/20100101 Firefox/55.0' -H 'Accept: */*' -H 'Accept-Language: zh-CN,zh;q=0.8,en-US;q=0.5,en;q=0.3' --compressed -H 'Content-Type: application/x-www-form-urlencoded; charset=UTF-8' -H 'X-Requested-With: XMLHttpRequest' -H 'Referer: http://publish.haodanku.com/login/index.html' -H 'Cookie: PHPSESSID=gle0jjtlli5r55gk4mru9rsq61' -H 'Connection: keep-alive' --data 'phone={$phone}&password={$password}&authcode={$captcha}'"; 38 | $content = $autologin->execCurl($curl); 39 | 40 | //4. 登录成功,锁定cookie的更新,直接访问已登录页面内容(类似采集内容),演示cookie锁定多次采集效果与cookie失效效果 41 | $autologin->lockLastCookieFile(); 42 | echo 'After Login: ' . isLogin($autologin->execCurl($getDataUrl)) . $lineBreak; 43 | 44 | function isLogin($content) { 45 | return (bool)stripos($content, '个人主页') ? 'Yes' : 'No'; 46 | } 47 | -------------------------------------------------------------------------------- /demo/2_wxqq.php: -------------------------------------------------------------------------------- 1 | getLineBreak(); 25 | //复制浏览器登录成功后,访问https://wx.qq.com/cgi-bin/mmwebwx-bin/webwxcheckurl?requrl=http%3A%2F%2Fwww.zjmainstay.cn的curl命令 26 | $curl = "curl 'https://wx.qq.com/cgi-bin/mmwebwx-bin/webwxcheckurl?requrl=http%3A%2F%2Fwww.zjmainstay.cn' -H 'Host: wx.qq.com' -H 'User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.10; rv:47.0) Gecko/20100101 Firefox/46.0' -H 'Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8' -H 'Accept-Language: zh-CN,zh;q=0.8,en-US;q=0.5,en;q=0.3' -H 'Accept-Encoding: gzip, deflate, br' -H 'Cookie: pgv_info=ssid=s7821947904; pgv_pvid=7479620263 ...' -H 'Connection: keep-alive' -H 'Cache-Control: max-age=0'"; 27 | 28 | $content = $autologin->execCurl($curl, function($parseCurlResult) { 29 | $parseCurlResult['header'][] = $parseCurlResult['cookie']; 30 | return $parseCurlResult; 31 | }); 32 | $res = $autologin->assertContainStr($content, '请不要在该网页上填写QQ账号及密码'); 33 | if($res) { 34 | echo "Yes" . $lineBreak; 35 | } else { 36 | echo "No" . $lineBreak; 37 | } 38 | 39 | 40 | 41 | //方法二 直接调用parseCurl对curl命令进行解析,并组装包含cookie的header头进行请求 42 | $autologin = new PHPCurl\CurlAutoLogin(); 43 | //复制浏览器登录成功后,访问 https://wx.qq.com/cgi-bin/mmwebwx-bin/webwxcheckurl?requrl=http%3A%2F%2Fwww.zjmainstay.cn 的curl命令 44 | $curl = "curl 'https://wx.qq.com/cgi-bin/mmwebwx-bin/webwxcheckurl?requrl=http%3A%2F%2Fwww.zjmainstay.cn' -H 'Host: wx.qq.com' -H 'User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.10; rv:47.0) Gecko/20100101 Firefox/46.0' -H 'Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8' -H 'Accept-Language: zh-CN,zh;q=0.8,en-US;q=0.5,en;q=0.3' -H 'Accept-Encoding: gzip, deflate, br' -H 'Cookie: pgv_info=ssid=s7821947904; pgv_pvid=7479620263 ...' -H 'Connection: keep-alive' -H 'Cache-Control: max-age=0'"; 45 | $url = 'https://wx.qq.com/cgi-bin/mmwebwx-bin/webwxcheckurl?requrl=http%3A%2F%2Fwww.zjmainstay.cn'; 46 | //仅用来解析头 47 | $curlInfo = $autologin->parseCurl($curl); 48 | $header = array_merge((array)$curlInfo['header'], array($curlInfo['cookie'])); 49 | $content = $autologin->getUrl($url, $header); 50 | $res = $autologin->assertContainStr($content, '请不要在该网页上填写QQ账号及密码'); 51 | if($res) { 52 | echo "Yes" . $lineBreak; 53 | } else { 54 | echo "No" . $lineBreak; 55 | } 56 | 57 | //方法三 直接调用execCurlWithCookie调用 58 | $autologin = new PHPCurl\CurlAutoLogin(); 59 | //复制浏览器登录成功后,访问 https://wx.qq.com/cgi-bin/mmwebwx-bin/webwxcheckurl?requrl=http%3A%2F%2Fwww.zjmainstay.cn 的curl命令 60 | $curl = "curl 'https://wx.qq.com/cgi-bin/mmwebwx-bin/webwxcheckurl?requrl=http%3A%2F%2Fwww.zjmainstay.cn' -H 'Host: wx.qq.com' -H 'User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.10; rv:47.0) Gecko/20100101 Firefox/46.0' -H 'Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8' -H 'Accept-Language: zh-CN,zh;q=0.8,en-US;q=0.5,en;q=0.3' -H 'Accept-Encoding: gzip, deflate, br' -H 'Cookie: pgv_info=ssid=s7821947904; pgv_pvid=7479620263 ...' -H 'Connection: keep-alive' -H 'Cache-Control: max-age=0'"; 61 | $content = $autologin->execCurlWithCookie($curl); 62 | $res = $autologin->assertContainStr($content, '请不要在该网页上填写QQ账号及密码'); 63 | if($res) { 64 | echo "Yes" . $lineBreak; 65 | } else { 66 | echo "No" . $lineBreak; 67 | } 68 | -------------------------------------------------------------------------------- /demo/34_www.aliwx.com.cn/34_www.aliwx.com.cn.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | function decodeCont(t) { 3 | return t = function (t) { 4 | return t.split('').map(function (t) { 5 | var e, 6 | i; 7 | return t.match(/[A-Za-z]/) ? (e = Math.floor(t.charCodeAt(0) / 97), i = (t.toLowerCase().charCodeAt(0) - 83) % 26 || 26, String.fromCharCode(i + (0 == e ? 64 : 96))) : t 8 | }).join('') 9 | }(t), 10 | function (t) { 11 | var e, 12 | i, 13 | a, 14 | n, 15 | r, 16 | c, 17 | o, 18 | s = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=', 19 | d = '', 20 | l = 0; 21 | for (t = t.replace(/[^A-Za-z0-9\+\/\=]/g, ''); l < t.length; ) n = s.indexOf(t.charAt(l++)), 22 | r = s.indexOf(t.charAt(l++)), 23 | c = s.indexOf(t.charAt(l++)), 24 | o = s.indexOf(t.charAt(l++)), 25 | e = n << 2 | r >> 4, 26 | i = (15 & r) << 4 | c >> 2, 27 | a = (3 & c) << 6 | o, 28 | d += String.fromCharCode(e), 29 | 64 != c && (d += String.fromCharCode(i)), 30 | 64 != o && (d += String.fromCharCode(a)); 31 | return function (t) { 32 | for (var e, i = '', a = 0, n = 0, r = 0; a < t.length; ) n = t.charCodeAt(a), 33 | n < 128 ? (i += String.fromCharCode(n), a++) : n > 191 && n < 224 ? (r = t.charCodeAt(a + 1), i += String.fromCharCode((31 & n) << 6 | 63 & r), a += 2) : (r = t.charCodeAt(a + 1), e = t.charCodeAt(a + 2), i += String.fromCharCode((15 & n) << 12 | (63 & r) << 6 | 63 & e), a += 3); 34 | return i 35 | }(d) 36 | }(t) 37 | } 38 | 39 | var system = require('system'); 40 | 41 | var content = decodeCont(system.args[1]); 42 | console.log(content); 43 | phantom.exit(); 44 | 45 | -------------------------------------------------------------------------------- /demo/34_www.aliwx.com.cn/34_www.aliwx.com.cn.php: -------------------------------------------------------------------------------- 1 | execCurl($curl); 18 | 19 | $pattern = '#(.*)#i'; 20 | preg_match($pattern, $content, $match); 21 | 22 | $data = json_decode(str_replace('"', '"', $match[1]), true); 23 | 24 | foreach($data['chapterList'][0]['volumeList'] as $chapter) { 25 | $url = htmlspecialchars_decode("http://c13.shuqireader.com/pcapi/chapter/contentfree/{$chapter['contUrlSuffix']}"); 26 | $curl = "curl '{$url}' -H 'Host: c13.shuqireader.com' -H 'User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/62.0.3202.9 Safari/537.36' -H 'Accept: */*' -H 'Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2' --compressed -H 'Referer: http://www.aliwx.com.cn/reader?bid=7379267' -H 'Origin: http://www.aliwx.com.cn' -H 'Connection: keep-alive'"; 27 | $content = $autologin->execCurl($curl); 28 | 29 | if(empty($content)) { 30 | //到达VIP章节 31 | break; 32 | } 33 | $responeArr = json_decode($content, true); 34 | $chapterContent = $responeArr['ChapterContent']; 35 | 36 | $chapterContent = `phantomjs 34_www.aliwx.com.cn.js '{$chapterContent}'`; 37 | 38 | file_put_contents($noteFile, str_replace('
', "\n", $chapter['chapterName'] . "({$chapter['chapterId']})\n" . $chapterContent) . "\n\n", FILE_APPEND); 39 | } 40 | -------------------------------------------------------------------------------- /demo/34_www.aliwx.com.cn/books/.gitignore: -------------------------------------------------------------------------------- 1 | * 2 | !.gitignore 3 | -------------------------------------------------------------------------------- /demo/38_upload.otar.im_image_upload.php: -------------------------------------------------------------------------------- 1 | execCurl($curl); 17 | 18 | if(!preg_match('#"x-csrf-token","([^"]+)"#i', $content, $match)) { 19 | exit("无法获取x-csrf-token,请检查数据源,url: http://upload.otar.im \n"); 20 | } 21 | $csrfToken = $match[1]; 22 | 23 | $delimiter = '-----------------------------' . rand(1000000000, 9999999999) . rand(1000000000, 9999999999) . rand(10000000, 99999999); 24 | $filePath = __DIR__ . '/../images/get-curl-text.png'; 25 | $data = buildFileUploadData($delimiter, 'img', $filePath); 26 | $contentType = 'multipart/form-data; boundary=' . $delimiter; 27 | $contentLength = strlen($data); 28 | 29 | // $apiUrl = 'http://upload.otar.im/api/upload/sina'; 30 | // $apiUrl = 'http://upload.otar.im/api/upload/smms'; 31 | $apiUrl = 'http://upload.otar.im/api/upload/imgur'; 32 | 33 | //2. 上传图片 34 | $curl = "curl '{$apiUrl}' -H 'Accept: */*' --compressed -H 'Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2' -H 'Connection: keep-alive' -H 'Cookie: koa.sid=6fuuKG4qGhJg2CFP0Y3Go1X92QKNjlI2; koa.sid.sig=FqGx8un0r_LBzf_60ROuaik-pPE' -H 'Host: upload.otar.im' -H 'Referer: http://upload.otar.im/' -H 'User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.10; rv:59.0) Gecko/20100101 Firefox/59.0' -H 'x-csrf-token: {$csrfToken}' -H 'Content-Type: {$contentType}' -H 'Content-Length: {$contentLength}'"; 35 | // die(var_dump($curl)); 36 | $content = $autologin->execCurl($curl, function($parseCurlResult) use ($data) { 37 | $parseCurlResult['post'] = $data; 38 | return $parseCurlResult; 39 | }); 40 | 41 | echo $content; 42 | 43 | /** 44 | * 构建文件上传数据 45 | * @param [type] $delimiter [description] 46 | * @param [type] $inputName [description] 47 | * @param [type] $file [description] 48 | * @return [type] [description] 49 | */ 50 | function buildFileUploadData($delimiter, $inputName, $file) { 51 | $data = ''; 52 | $data .= "--" . $delimiter . "\r\n"; 53 | $data .= 'Content-Disposition: form-data; name="' . $inputName . '";' . 54 | ' filename="' . basename($file) . '"' . "\r\n"; 55 | $data .= 'Content-Type: ' . mime_content_type($file) . "\r\n"; 56 | $data .= "\r\n"; 57 | $data .= file_get_contents($file) . "\r\n"; 58 | $data .= "--" . $delimiter . "--\r\n"; 59 | 60 | return $data; 61 | } 62 | -------------------------------------------------------------------------------- /demo/3_preloadCookieAndVisit.php: -------------------------------------------------------------------------------- 1 | execCurl($curl1); 19 | 20 | $curl2 = "curl 'http://book.m.5read.com/search?sw=php&channel=search&Field=all&Sort=3&page=1&ecode=UTF-8'"; 21 | $content = $autologin->execCurl($curl2); 22 | 23 | $pattern = '#(作者:.+)#'; 24 | 25 | preg_match_all($pattern, $content, $matches); 26 | 27 | $itemPattern = '#([^:]+:.*?)(?: )+#'; 28 | foreach($matches[1] as $author) { 29 | $author = preg_replace('#(\d{4}\.\d{2}  ).+#i', '$1', $author); 30 | preg_match_all($itemPattern, $author, $itemMatches); 31 | var_dump($itemMatches[1]); 32 | } 33 | 34 | 35 | -------------------------------------------------------------------------------- /demo/41_cli.im.php: -------------------------------------------------------------------------------- 1 | execCurl($curl); 17 | 18 | // echo "1. " . $content . "\n"; 19 | 20 | $delimiter = '-----------------------------' . rand(1000000000, 9999999999) . rand(1000000000, 9999999999) . rand(10000000, 99999999); 21 | $filePath = __DIR__ . '/../images/php-curl-qrcode.png'; 22 | $data = buildFileUploadData($delimiter, 'Filedata', $filePath); 23 | $contentType = 'multipart/form-data; boundary=' . $delimiter; 24 | $contentLength = strlen($data); 25 | 26 | $apiUrl = 'https://upload.api.cli.im/upload.php?kid=cliim'; 27 | 28 | //2. 上传图片 29 | $curl = "curl '{$apiUrl}' -H 'Accept: */*' --compressed -H 'Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2' -H 'Connection: keep-alive' -H 'Cookie: koa.sid=6fuuKG4qGhJg2CFP0Y3Go1X92QKNjlI2; koa.sid.sig=FqGx8un0r_LBzf_60ROuaik-pPE' -H 'Origin: https://cli.im' -H 'Referer: https://cli.im/deqr' -H 'User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.10; rv:59.0) Gecko/20100101 Firefox/59.0' -H 'Content-Type: {$contentType}' -H 'Content-Length: {$contentLength}'"; 30 | // die(var_dump($curl)); 31 | $content = $autologin->execCurl($curl, function($parseCurlResult) use ($data) { 32 | $parseCurlResult['post'] = $data; 33 | return $parseCurlResult; 34 | }); 35 | 36 | echo "2. " . $content . "\n"; 37 | 38 | $imgInfo = json_decode($content, true); 39 | $imgUrl = urlencode($imgInfo['data']['path']); 40 | 41 | //3. 解析二维码 42 | $curl = "curl 'https://cli.im/apis/up/deqrimg' -H 'User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.13; rv:61.0) Gecko/20100101 Firefox/61.0' -H 'Accept: application/json, text/javascript, */*; q=0.01' -H 'Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2' --compressed -H 'Referer: https://cli.im/deqr' -H 'Content-Type: application/x-www-form-urlencoded; charset=UTF-8' -H 'X-Requested-With: XMLHttpRequest' -H 'Cookie: _ga=GA1.2.612629640.1509329069; Hm_lvt_cb508e5fef81367bfa47f4ec313bf68c=1536997019; SERVERID=845671255dd12630e5f3f4b14406bdaa|1536997573|1536996809; PHPSESSID=57fn56uo3ca1e1pcb1aan1as71; Hm_lpvt_cb508e5fef81367bfa47f4ec313bf68c=1536997782; climanager_v2=%7B%22manager_id%22%3A%2211%22%2C%22type%22%3A%221%22%2C%22weight%22%3A%220%22%2C%22nickname%22%3A%22%u5C0F%u8D75%22%2C%22realname%22%3A%22%u8D75%u8FD0%22%2C%22star_text%22%3A%22%u4E13%u5C5E%u987E%u95EE%22%2C%22vcard_pic%22%3A%22https%3A//static.clewm.net/cli/images/contact/kefu-default@2x.png%22%2C%22logo_pic%22%3A%22https%3A//static.clewm.net/cli/images/contact/logo-zy@2x.png%22%2C%22telphone%22%3A%220574-55330927%22%2C%22qq%22%3A%222852371507%22%2C%22contact_link%22%3A%22https%3A//q.url.cn/s/mjzkTcm%22%2C%22group_link%22%3A%22//q.url.cn/s/wGb3v6m%22%2C%22complete%22%3A0%7D; text-content-words=33; qrs=157961239; _gat=1' -H 'Connection: keep-alive' --data 'img={$imgUrl}'"; 43 | $content = $autologin->execCurl($curl); 44 | 45 | echo "3. " . $content . "\n"; 46 | 47 | /** 48 | * 构建文件上传数据 49 | * @param [type] $delimiter [description] 50 | * @param [type] $inputName [description] 51 | * @param [type] $file [description] 52 | * @return [type] [description] 53 | */ 54 | function buildFileUploadData($delimiter, $inputName, $file) { 55 | $data = ''; 56 | $data .= "--" . $delimiter . "\r\n"; 57 | $data .= 'Content-Disposition: form-data; name="' . $inputName . '";' . 58 | ' filename="' . basename($file) . '"' . "\r\n"; 59 | $data .= 'Content-Type: ' . mime_content_type($file) . "\r\n"; 60 | $data .= "\r\n"; 61 | $data .= file_get_contents($file) . "\r\n"; 62 | $data .= "--" . $delimiter . "--\r\n"; 63 | 64 | return $data; 65 | } 66 | -------------------------------------------------------------------------------- /demo/48_request_repeat.php: -------------------------------------------------------------------------------- 1 | getLineBreak(); 17 | 18 | //获取登录态(失败) 19 | $curl = "curl 'http://demo.zjmainstay.cn/js/simpleAjax/loginResult.php'"; 20 | $content = $autologin->execCurl($curl); 21 | echo 'Before Login: ' . $content . $lineBreak; 22 | 23 | //登录 24 | $username = 'Zjmainstay'; 25 | $curl = "curl 'http://demo.zjmainstay.cn/js/simpleAjax/doPost.php' -H 'Host: demo.zjmainstay.cn' -H 'User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.10; rv:47.0) Gecko/20100101 Firefox/47.0' -H 'Accept: application/json, text/javascript, */*; q=0.01' -H 'Accept-Language: zh-CN,zh;q=0.8,en-US;q=0.5,en;q=0.3' -H 'Accept-Encoding: gzip, deflate' -H 'Content-Type: application/x-www-form-urlencoded; charset=UTF-8' -H 'X-Requested-With: XMLHttpRequest' -H 'Referer: http://demo.zjmainstay.cn/js/simpleAjax/' -H 'Cookie: Hm_lvt_1526d5aecf5561ef9401f7c7b7842a97=1468327822,1468327904,1468341636,1468411918; Hm_lpvt_1526d5aecf5561ef9401f7c7b7842a97=1468421526' -H 'Connection: keep-alive' --data 'username=[username]'"; 26 | $curl = str_replace('[username]', $username, $curl); 27 | $autologin->execCurl($curl, false, false, false); //登录不需要记录最后请求参数 28 | 29 | //重放获取登录态 30 | $content = $autologin->repeatRequest(); 31 | echo 'After Login: ' . $content . $lineBreak; 32 | -------------------------------------------------------------------------------- /demo/49_format_cookie.php: -------------------------------------------------------------------------------- 1 | parseCurl($curl); 24 | $cookieForFile = $autologin->formatHeaderCookieToFileContent($parseResult['cookie'], '.zjmainstay.cn'); 25 | $autologin->appendCookieContent($cookieForFile, true); 26 | $content = $autologin->execCurl($curl); 27 | var_dump($content, $autologin->getLastCookieContent()); 28 | -------------------------------------------------------------------------------- /demo/61_tophub.today.php: -------------------------------------------------------------------------------- 1 | execCurl($curl); 32 | 33 | preg_match_all('#]*itemid="(\d+)"#i', $content, $matches); 34 | 35 | // 这里做测试,只抓取一个地址 36 | foreach($matches[0] as $key => $value) { 37 | $url = $matches[1][$key]; 38 | $itemid = $matches[2][$key]; 39 | 40 | break; 41 | } 42 | // var_dump($url, $itemid); 43 | 44 | $curl = <<execCurl($curl); 60 | var_dump($content); 61 | 62 | 63 | -------------------------------------------------------------------------------- /demo/62_curlmulti/.gitignore: -------------------------------------------------------------------------------- 1 | vendor 2 | composer.lock 3 | result.log 4 | !.gitignore -------------------------------------------------------------------------------- /demo/62_curlmulti/62_wiz.cn.php: -------------------------------------------------------------------------------- 1 | setLastCookieFile($loginCookieFile); 35 | $resArr = json_decode(file_get_contents($loginResultFile), true); 36 | } 37 | 38 | if(empty($resArr['result']['kbGuid'])) { 39 | exit("未登录成功,请检查帐号和密码是否正确\n"); 40 | } 41 | 42 | $kbGuid = $resArr['result']['kbGuid']; 43 | $wizToken = $resArr['result']['token']; 44 | 45 | //加载全部笔记数据 46 | $size = 100; 47 | $i = 0; 48 | $docGuidArr = []; 49 | while(true){ 50 | $start = $i * $size; 51 | $curl = <<execCurl($curl); 68 | $resArr = json_decode($content, true); 69 | //登录态丢失自动登录,然后返回重新请求 70 | if(isset($resArr['returnMessage']) && $resArr['returnMessage'] == 'Invalid token') { 71 | $resArr = doLogin($autoLogin, $username, $password, $loginResultFile, $loginCookieFile); 72 | if(empty($resArr['result']['kbGuid'])) { 73 | exit("未登录成功,请检查帐号和密码是否正确\n"); 74 | } 75 | $kbGuid = $resArr['result']['kbGuid']; 76 | $wizToken = $resArr['result']['token']; 77 | continue; 78 | } 79 | if(empty($resArr['result'])) { 80 | break; 81 | } 82 | $docGuidArr = array_merge($docGuidArr, array_column($resArr['result'], 'title', 'docGuid')); 83 | // file_put_contents(__DIR__ . '/result.log', $content . "\n\n", 8); 84 | $i++; 85 | } 86 | 87 | //单个下载示例 88 | //测试下载460个文档,耗时370秒 89 | //$start = microtime(true); 90 | //echo "逐个请求,开始:" . date('Y-m-d H:i:s') . "\n"; 91 | //foreach($docGuidArr as $docGuid => $title) { 92 | // $curl = <<execCurl($curl); 109 | // $resArr = json_decode($content, true); 110 | // $dir = __DIR__ . '/cache/type_1/' . ltrim($resArr['info']['category'], '/'); 111 | // if(!is_dir($dir)) { 112 | // mkdir($dir, 0755, true); 113 | // } 114 | // if(!empty($resArr['html'])) { 115 | // file_put_contents($dir . str_replace("/", ":", $resArr['info']['title']), $resArr['html']); 116 | // } else { 117 | // echo "empty content: {$resArr['info']['category']}{$title}\n"; 118 | // } 119 | //} 120 | //echo "逐个请求,结束:" . date('Y-m-d H:i:s') . "\n"; 121 | //$timeCost = microtime(true) - $start; 122 | //echo "逐个请求,耗时:" . $timeCost . "秒 \n"; 123 | 124 | //批量下载示例 125 | //测试下载460个文档,耗时45秒 126 | $multiStart = microtime(true); 127 | echo "批量请求,开始:" . date('Y-m-d H:i:s') . "\n"; 128 | 129 | //解析下载url,获取url、header等信息,由于url是依赖每个笔记的ID,因此埋入一个替换标记[docGuid] 130 | $curl = <<parseCurl($curl); 146 | 147 | $multiCurl = new \Ares333\Curl\Curl(); 148 | //回调打印最后一个下载完成的时间 149 | $multiCurl->onInfo = function($info, $_this, $isLast) { 150 | global $multiStart; 151 | if($isLast) { 152 | echo "批量请求,结束:" . date('Y-m-d H:i:s') . "\n"; 153 | $timeCost = microtime(true) - $multiStart; 154 | echo "批量请求,耗时:" . $timeCost . "秒 \n"; 155 | } 156 | }; 157 | $docCount = count($docGuidArr); 158 | echo "开始下载文档,共{$docCount}个\n"; 159 | $index = 0; 160 | //把全部下载地址加入批量下载队列 161 | foreach ($docGuidArr as $docGuid => $title) { 162 | //替换文档ID变量,得到真实下载地址 163 | $url = str_replace('[docGuid]', $docGuid, $curlInfo['url']); 164 | //加入下载队列 165 | $multiCurl->add([ 166 | 'opt' => array( 167 | CURLOPT_URL => $url, //指定下载地址 168 | CURLOPT_HTTPHEADER => $curlInfo['header'], //引用下载header参数 169 | CURLOPT_COOKIEFILE => $autoLogin->getLastCookieFile(), //引用前面模拟登录的cookie 170 | CURLOPT_RETURNTRANSFER => true, //抓取结果不直接输出,返回内容 171 | ), 172 | 'args' => [ //下载完成回调参数,传入一下后续要用的参数,方便打印记录 173 | 'index' => $index + 1, 174 | 'title' => $title, 175 | ], 176 | ], 'parseDocResult'); 177 | $index++; 178 | } 179 | //开始下载 180 | $multiCurl->start(); 181 | 182 | //功能函数 183 | /** 184 | * 文档下载结果解析 185 | * @param $r 186 | * @param $args 187 | */ 188 | function parseDocResult($r, $args) { 189 | if($r['info']['http_code'] == 200) { 190 | $resArr = json_decode($r['body'], true); 191 | $dir = __DIR__ . '/cache/type_2/' . ltrim($resArr['info']['category'], '/'); 192 | if (!is_dir($dir)) { 193 | mkdir($dir, 0755, true); 194 | } 195 | if(!empty($resArr['html'])) { 196 | echo "下载第[{$args['index']}]个文档: {$resArr['info']['category']}{$args['title']}\n"; 197 | file_put_contents($dir . str_replace("/", ":", $resArr['info']['title']), $resArr['html']); 198 | } else { 199 | echo "下载第[{$args['index']}]个文档: {$resArr['info']['category']}{$args['title']},无内容\n"; 200 | } 201 | } else { 202 | echo "fail {$r['info']['url']}\n"; 203 | } 204 | } 205 | 206 | /** 207 | * 执行登录 208 | * @param $username 209 | * @param $password 210 | */ 211 | function doLogin($autoLogin, $username, $password, $loginResultFile, $loginCookieFile) 212 | { 213 | echo "无登录态,模拟登录...\n"; 214 | $curl = <<execCurl($curl); 234 | $resArr = json_decode($content, true); 235 | file_put_contents($loginResultFile, $content); //存储登录结果 236 | file_put_contents($loginCookieFile, $autoLogin->getLastCookieContent()); //存储登录后的cookie 237 | 238 | return $resArr; 239 | } 240 | -------------------------------------------------------------------------------- /demo/62_curlmulti/cache/.gitignore: -------------------------------------------------------------------------------- 1 | * 2 | !.gitignore -------------------------------------------------------------------------------- /demo/62_curlmulti/composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "zjmainstay/php-curl-multi", 3 | "description": "基于cURL命令自动登录后,引用ares333/php-curl类库进行批量采集。", 4 | "type": "project", 5 | "require": { 6 | "zjmainstay/php-curl": "^1.0", 7 | "ares333/php-curl": "^4.6" 8 | }, 9 | "license": "Apache-2.0", 10 | "authors": [ 11 | { 12 | "name": "Zjmainstay", 13 | "email": "hzgdys@163.com" 14 | } 15 | ] 16 | } 17 | -------------------------------------------------------------------------------- /demo/7_cnki.net.php: -------------------------------------------------------------------------------- 1 | execCurl($curl1, function($parseResult) { 16 | $parseResult['opt'][CURLOPT_HEADER] = true; 17 | return $parseResult; 18 | }); 19 | 20 | preg_match('#Location: (http[^\r\n]+)#i', $content, $match); 21 | $loginUrl = $match[1]; 22 | 23 | //http://epub.cnki.net/kns/download.aspx?filename=iF0arlHSv10crJEU1UHZklEVJJUR3gWMFdmYj1mQI10bxU1R1lFbvlzQmhVSEBVWZNXWkRXWVZlV5ZXZ1BXUyAXMwtCWJ5WSYRlVJpWc08yMYRVOVZXTMd1TuNkeUVHZSBzRZNleTZFaIZDaxg2UrBXZWF2ZwETT&tablename=CCNDPREP 24 | 25 | $curl2 = "curl '{$loginUrl}' -H 'Host: epub.cnki.net' -H 'User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.10; rv:47.0) Gecko/20100101 Firefox/47.0' -H 'Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8' -H 'Accept-Language: zh-CN,zh;q=0.8,en-US;q=0.5,en;q=0.3' -H 'Accept-Encoding: gzip, deflate' -H 'Referer: http://epub.cnki.net/kns/download.aspx?filename=iF0arlHSv10crJEU1UHZklEVJJUR3gWMFdmYj1mQI10bxU1R1lFbvlzQmhVSEBVWZNXWkRXWVZlV5ZXZ1BXUyAXMwtCWJ5WSYRlVJpWc08yMYRVOVZXTMd1TuNkeUVHZSBzRZNleTZFaIZDaxg2UrBXZWF2ZwETT&tablename=CCNDPREP' -H 'Cookie: ASP.NET_SessionId=vabrf4am2gv3v445febxduqy; Ecp_IpLoginFail=16082561.51.129.138' -H 'Connection: keep-alive' -H 'Content-Type: application/x-www-form-urlencoded' --data 'username=123456%40qq.com&password=2222222'"; 26 | 27 | $content = $autologin->execCurl($curl2); 28 | 29 | var_dump($content); 30 | -------------------------------------------------------------------------------- /demo/8_webqq.php: -------------------------------------------------------------------------------- 1 | getLineBreak(); 17 | 18 | //测试发送信息 19 | for($i = 1; $i <= 3; $i++) { 20 | $message = rawurlencode(date('Y-m-d H:i:s') . ': message_' . $i); 21 | $curl1 = "curl 'http://d1.web2.qq.com/channel/send_qun_msg2' -H 'Host: d1.web2.qq.com' -H 'User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.10; rv:48.0) Gecko/20100101 Firefox/48.0' -H 'Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8' -H 'Accept-Language: zh-CN,zh;q=0.8,en-US;q=0.5,en;q=0.3' -H 'Accept-Encoding: gzip, deflate' -H 'Content-Type: application/x-www-form-urlencoded' -H 'Referer: http://d1.web2.qq.com/proxy.html?v=20151105001&callback=1&id=2' -H 'Cookie: ts_uid=6512215782; ts_refer=www.popoho.com/tool/denglu/; p_uin=o01000088; p_skey=miwiAfcSoDeZCoFJa6OefkUZ7w03HWmRVKzLxUZZ-1U_; pt4_token=we*K*xMoPd5*BqM4m16h8yI*NSvonZ3MjeyEb5r90sw_; pgv_info=ssid=s4959849500; pgv_pvid=649892905; pt2gguin=o01000088; uin=o01000088; skey=@a5s8A3qb3; ptisp=cnc; RK=YIGuZAlSQS; ptwebqq=37848925dee6af86f6579c9c46fed9f19a; o_cookie=1000088' --data 'r=%7B%22group_uin%22%3A3978381470%2C%22content%22%3A%22%5B%5C%22{$message}%5C%22%2C%5B%5C%22font%5C%22%2C%7B%5C%22name%5C%22%3A%5C%22%E5%AE%8B%E4%BD%93%5C%22%2C%5C%22size%5C%22%3A10%2C%5C%22style%5C%22%3A%5B0%2C0%2C0%5D%2C%5C%22color%5C%22%3A%5C%22000000%5C%22%7D%5D%5D%22%2C%22face%22%3A0%2C%22clientid%22%3A53999199%2C%22msg_id%22%3A20080001%2C%22psessionid%22%3A%228368046764001d636f6e6e7365727665725f77656271714031302e3133332e34312e383400001ad00000066b026e040015808a206d0000000a406172314338344a69526d000000285918d94e66218548d1ecb1a12513c86126b3afb97a3c2955b1070324790733ddb059ab166de6857%22%7D'"; 22 | 23 | //注:频繁发送会导致账号锁定,慎用!!! 24 | $msg = rawurlencode(date('Y-m-d H:i:s ') . '我轰死你个煞笔' . $i); 25 | $curl1 = "curl 'http://d1.web2.qq.com/channel/send_buddy_msg2' -H 'Host: d1.web2.qq.com' -H 'User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.10; rv:48.0) Gecko/20100101 Firefox/48.0' -H 'Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8' -H 'Accept-Language: zh-CN,zh;q=0.8,en-US;q=0.5,en;q=0.3' -H 'Accept-Encoding: gzip, deflate' -H 'Content-Type: application/x-www-form-urlencoded' -H 'Referer: http://d1.web2.qq.com/proxy.html?v=20151105001&callback=1&id=2' -H 'Cookie: ts_uid=6512215782; ts_refer=www.popoho.com/tool/denglu/; p_uin=o01000088; p_skey=2rnpdQKMZJz2IP9zqvixxKNUVgm2DwFNm2NiHEH0F0E_; pt4_token=ArYeZZXriUbYi157LEY2QhbQKHIwvEUdWDyNFpEgSPw_; pgv_info=ssid=s1842987996; pgv_pvid=5589981100; pt2gguin=o01000088; uin=o01000088; skey=@9KF9yztXZ; ptisp=cnc; RK=mIGmcAlTQS; ptwebqq=1554f1205a9ff09c1ce44' -H 'Connection: keep-alive' --data 'r=%7B%22to%22%3A3820995309%2C%22content%22%3A%22%5B%5C%22{$msg}%5C%22%2C%5B%5C%22font%5C%22%2C%7B%5C%22name%5C%22%3A%5C%22%E5%AE%8B%E4%BD%93%5C%22%2C%5C%22size%5C%22%3A10%2C%5C%22style%5C%22%3A%5B0%2C0%2C0%5D%2C%5C%22color%5C%22%3A%5C%22000000%5C%22%7D%5D%5D%22%2C%22face%22%3A0%2C%22clientid%22%3A53999199%2C%22msg_id%22%3A45070001%2C%22psessionid%22%3A%228368046764001d636f6e6e7365727665725f77656271714031302e3133332e34312e383400001ad00000066b026e040015808a206d0000000a406172314338344a69526d000000285918d94e66218548d1ecb1a12513c86126b3afb97a3c2955b1070324790733ddb059ab166de6857%22%7D'"; 26 | $content = $autologin->execCurlWithCookie($curl1); 27 | var_dump($content); 28 | sleep(rand(3, 5)); 29 | } 30 | -------------------------------------------------------------------------------- /demo/parseCurlCode/.gitignore: -------------------------------------------------------------------------------- 1 | * 2 | !.gitignore 3 | -------------------------------------------------------------------------------- /demo/parseCurlGetPhpCode.php: -------------------------------------------------------------------------------- 1 | 16384) { 100 | exit('curl内容过长'); 101 | } 102 | if(!isset($_POST['withCookie'])) { 103 | $_POST['withCookie'] = false; 104 | } 105 | if(!isset($_POST['timeout']) || !abs((int)$_POST['timeout'])) { 106 | $_POST['timeout'] = 10; 107 | } 108 | 109 | if(empty($_POST['share'])) { 110 | highlight_string(parseCurlToCode($_POST['curl'], (bool)$_POST['withCookie'], $_POST['timeout'])); 111 | exit; 112 | } 113 | 114 | //分享 115 | ob_start(); 116 | highlight_string(parseCurlToCode($_POST['curl'], (bool)$_POST['withCookie'], $_POST['timeout'])); 117 | $content = ob_get_contents(); 118 | ob_clean(); 119 | 120 | $filename = md5(implode('_', [$_POST['curl'], (int)$_POST['withCookie'], $_POST['timeout']])) . '.html'; 121 | 122 | $dir = __DIR__ . '/parseCurlCode/' . date('Ymd/'); 123 | if(!is_dir($dir)) { 124 | @mkdir($dir, 0777); 125 | } 126 | 127 | @file_put_contents( $dir . $filename, $content); 128 | 129 | header('Location: ./parseCurlCode/' . date('Ymd/') . $filename); 130 | exit; 131 | } 132 | ?> 133 | 134 | 135 | 136 | 137 | 基于cURL命令解析获得PHP代码 138 | 139 | 140 |
141 |
cURL命令:
142 |
携带Cookie:
143 |
超时时间:
144 |
分享:
145 |
146 |
147 |
148 |
149 |
150 |

151 | 如何从浏览器获取cURL命令 152 |
153 | 利用浏览器的开发者工具(控制台),Firefox如下图: 154 |
155 | 如何获取cURL命令 156 |

157 |

158 | 更多PHP cURL内容,请查看博客《PHP cURL实现模拟登录与采集使用方法详解》 159 |

160 | 161 | 162 | -------------------------------------------------------------------------------- /images/get-curl-text.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Zjmainstay/php-curl/7a55c6f4f3bcc2d52b82227d9bea9cc450227de5/images/get-curl-text.png -------------------------------------------------------------------------------- /images/php-curl-qrcode.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Zjmainstay/php-curl/7a55c6f4f3bcc2d52b82227d9bea9cc450227de5/images/php-curl-qrcode.png -------------------------------------------------------------------------------- /logs/.htaccess: -------------------------------------------------------------------------------- 1 | deny from all 2 | -------------------------------------------------------------------------------- /phpunit.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /src/CurlAutoLogin.php: -------------------------------------------------------------------------------- 1 | removeCookieFileAtDestruct = $removeCookieFileAtDestruct; 27 | if(!empty($logPath) && is_writable($logPath)) { 28 | $this->logPath = $logPath; 29 | } else { 30 | $this->logPath = dirname(__FILE__) . '/../logs/run.log'; 31 | if(!file_exists($this->logPath)) { 32 | if(!is_dir(dirname($this->logPath))) { 33 | mkdir(dirname($this->logPath), 0755, true); 34 | } 35 | } 36 | } 37 | } 38 | 39 | //程序退出销毁处理 40 | public function __destruct() 41 | { 42 | //如果设置了清理cookie文件 43 | if($this->removeCookieFileAtDestruct && file_exists($this->getLastCookieFile())) { 44 | unlink($this->getLastCookieFile()); 45 | } 46 | } 47 | 48 | /** 49 | * 设置全局请求opt(方便使用代理之类的请求) 50 | * @param $opts 51 | */ 52 | public function setGlobalOpts($opts = []) 53 | { 54 | $this->globalOpts += $opts; 55 | return $this; 56 | } 57 | 58 | /** 59 | * 根据curl信息执行并解析结果,核心方法常用方法之一 60 | * @param string $curlContent 利用Firefox浏览器复制cURL命令 61 | * @param boolean $callbackBefore 对curl结果前置处理,如更换用户名、密码等 62 | * @param boolean $callbackAfter 对采集结果后置处理,如解析结果的csrf token等 63 | * @param boolean $storeParams 是否存储最后请求参数供重放使用,默认存储 64 | * @return mixed 65 | */ 66 | public function execCurl($curlContent, $callbackBefore = false, $callbackAfter = false, $storeParams = true) { 67 | //存储参数供请求重放使用 68 | if($storeParams) { 69 | $this->lastExecParams = func_get_args(); 70 | } 71 | $parseCurlResult = $this->parseCurl($curlContent); 72 | if(is_callable($callbackBefore)) { 73 | $parseCurlResult = $callbackBefore($parseCurlResult); 74 | } 75 | $parseCurlResult['opt'] += $this->globalOpts; 76 | $execCurlResult = $this->_execCurl($parseCurlResult); 77 | 78 | if(is_callable($callbackAfter)) { 79 | $execCurlResult = $callbackAfter($parseCurlResult, $execCurlResult); 80 | } 81 | 82 | return $execCurlResult; 83 | } 84 | 85 | /** 86 | * 携带cookie执行curl命令,核心方法常用方法之一,直接利用curl命令里的header头cookie参数 87 | * @param string $curlContent 利用Firefox浏览器复制cURL命令 88 | * @param boolean $callbackBefore 对curl结果前置处理,如更换用户名、密码等 89 | * @param boolean $callbackAfter 对采集结果后置处理,如解析结果的csrf token等 90 | * @return mixed 91 | */ 92 | public function execCurlWithCookie($curlContent, $callbackBefore = false, $callbackAfter = false) { 93 | return $this->execCurl($curlContent, function($parseCurlResult) use ($callbackBefore) { 94 | $parseCurlResult['header'][] = $parseCurlResult['cookie']; 95 | if(is_callable($callbackBefore)) { 96 | $parseCurlResult = $callbackBefore($parseCurlResult); 97 | } 98 | return $parseCurlResult; 99 | }, $callbackAfter); 100 | } 101 | 102 | /** 103 | * 重放请求,依赖登录的场景出现登录失败的情况,重新登录后,调用此方法重试上一次的请求 104 | * @return mixed 105 | */ 106 | public function repeatRequest() 107 | { 108 | //最后一次请求参数不为空才重放 109 | if(!empty($this->lastExecParams)) { 110 | list($curlContent, $callbackBefore, $callbackAfter) = array_pad($this->lastExecParams, 3, false); 111 | return $this->execCurl($curlContent, $callbackBefore, $callbackAfter, true); 112 | } 113 | return null; 114 | } 115 | 116 | /** 117 | * 获取最后一次请求参数 118 | * @return array 119 | */ 120 | public function getLastExecParams() 121 | { 122 | return $this->lastExecParams; 123 | } 124 | 125 | /** 126 | * 主动销毁最后一次请求参数 127 | * @return $this 128 | */ 129 | public function unsetLastExecParams() 130 | { 131 | $this->lastExecParams = []; 132 | return $this; 133 | } 134 | 135 | /** 136 | * 解析curl信息 137 | * @param string $curlContent 利用Firefox浏览器复制cURL命令 138 | * @return bool|array 139 | */ 140 | public function parseCurl($curlContent) { 141 | if(!preg_match("#curl '([^']*)'#is", $curlContent, $matchUrl) 142 | && !preg_match("#curl.*'([^']*)'\s*$#is", $curlContent, $matchUrl) 143 | ) { 144 | return false; 145 | } 146 | 147 | //get cookie 148 | if(!preg_match("#-H '(Cookie:[^']*)'#is", $curlContent, $cookieMatch)) { 149 | $cookieData = ''; 150 | } else { 151 | $cookieData = $cookieMatch[1]; 152 | } 153 | 154 | //兼容 -b 参数 155 | if(empty($cookieData) && preg_match("#-b '([^']*)'#is", $curlContent, $cookieMatch)) { 156 | $cookieData = "Cookie: " . $cookieMatch[1]; 157 | } 158 | 159 | //remove cookie data in header 160 | $curlContent = preg_replace("#-H 'Cookie:[^']*'#is", '', $curlContent); 161 | 162 | //get header 163 | if(!preg_match_all("#-H '([^']*)'#is", $curlContent, $headerMatches)) { 164 | $httpHeader = array(); 165 | } else { 166 | $httpHeader = $headerMatches[1]; 167 | } 168 | 169 | //get data 170 | //单引号 171 | if(!preg_match("#(?:--data\S*|-d) \\$?'([^']*)'#is", $curlContent, $postDataMatch)) { 172 | //双引号 173 | if(!preg_match('#(?:--data\S*|-d) \\$?"([^"]*)"#is', $curlContent, $postDataMatch)) { 174 | $postDataMatch[1] = ''; 175 | } 176 | } 177 | $postData = $postDataMatch[1]; 178 | 179 | return array( 180 | 'url' => $matchUrl[1], 181 | 'header' => $httpHeader, 182 | 'post' => $postData, 183 | 'opt' => array(), //扩展opt,在callbackBefore里添加 184 | 'cookie' => $cookieData, 185 | ); 186 | } 187 | 188 | /** 189 | * 执行curl请求 190 | * @param array $parseCurlResult curl信息的解析结果,包含 url/header/post 三个键值参数 191 | * @return string 192 | */ 193 | protected function _execCurl($parseCurlResult) { 194 | if(empty($parseCurlResult['url'])) { 195 | return ''; 196 | } 197 | 198 | $ch = curl_init($parseCurlResult['url']); 199 | curl_setopt($ch,CURLOPT_HEADER,0); 200 | curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); //返回数据不直接输出 201 | curl_setopt($ch, CURLOPT_ENCODING, "gzip"); //指定gzip压缩 202 | 203 | //add header 204 | if(!empty($parseCurlResult['header'])) { 205 | curl_setopt($ch, CURLOPT_HTTPHEADER, $parseCurlResult['header']); 206 | } 207 | 208 | //add ssl support 209 | if(substr($parseCurlResult['url'], 0, 5) == 'https') { 210 | // curl_setopt($ch, CURLOPT_SSLVERSION,1); //error:14077458:SSL routines:SSL23_GET_SERVER_HELLO:reason(1112) 211 | curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); //SSL 报错时使用 212 | curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false); //SSL 报错时使用 213 | } 214 | 215 | //add 302 support 216 | curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true); 217 | 218 | //add cookie support 219 | $cookieFile = $this->getTempFile(); 220 | curl_setopt($ch,CURLOPT_COOKIEJAR,$cookieFile); //存储提交后得到的cookie数据 221 | 222 | //add previous curl cookie 223 | if($this->getLastCookieFile()) { 224 | curl_setopt($ch,CURLOPT_COOKIEFILE, $this->getLastCookieFile()); //使用提交后得到的cookie数据 225 | } 226 | 227 | //add post data support 228 | if(!empty($parseCurlResult['post'])) { 229 | curl_setopt($ch,CURLOPT_POST, 1); 230 | curl_setopt($ch,CURLOPT_POSTFIELDS, $parseCurlResult['post']); 231 | } 232 | 233 | //extend opt 234 | if(!empty($parseCurlResult['opt'])) { 235 | foreach ($parseCurlResult['opt'] as $key => $value) { 236 | curl_setopt($ch, $key, $value); 237 | } 238 | } 239 | 240 | $content = ''; 241 | try { 242 | $content = curl_exec($ch); //执行并存储结果 243 | } catch (\Exception $e) { 244 | $this->_log($e->getMessage()); 245 | } 246 | 247 | $curlError = curl_error($ch); 248 | if(!empty($curlError)) { 249 | $this->_log($curlError); 250 | } 251 | 252 | curl_close($ch); 253 | 254 | //update last cookie file 255 | $this->setLastCookieFile($cookieFile); 256 | 257 | return $content; 258 | } 259 | 260 | /** 261 | * 设置日志路径 262 | * @param string $logPath 绝对路径,必须可写 263 | */ 264 | public function setLogPath($logPath) { 265 | $this->logPath = $logPath; 266 | return $this; 267 | } 268 | 269 | /** 270 | * 记录日志 271 | * @param [type] $msg [description] 272 | * @return [type] [description] 273 | */ 274 | protected function _log($msg) { 275 | try { 276 | $res = file_put_contents($this->logPath, $msg . "\n", FILE_APPEND); 277 | } catch (\Exception $e) { 278 | error_log("CurlAutoLogin 无法写入日志文件 {$this->logPath}: {$msg}"); 279 | } 280 | } 281 | 282 | /** 283 | * 获取上一次存储cookie的文件 284 | * @return [type] [description] 285 | */ 286 | public function getLastCookieFile() { 287 | return $this->lastCookieFile; 288 | } 289 | 290 | /** 291 | * 获取最后一次存储的cookie内容 292 | * @return string 293 | */ 294 | public function getLastCookieContent() { 295 | if($file = $this->getLastCookieFile()) { 296 | if(file_exists($file)) { 297 | return file_get_contents($file); 298 | } 299 | } 300 | return ''; 301 | } 302 | 303 | /** 304 | * 手动追加cookie内容到最后一次存储的cookie文件 305 | * @param string $content 306 | * @param bool $init 307 | * @return bool|int 308 | */ 309 | public function appendCookieContent($content, $init = true) 310 | { 311 | if(file_exists($file = $this->getLastCookieFile()) || $init) { 312 | //初始cookie文件 313 | if(empty($file)) { 314 | $file = $this->getTempFile(); 315 | if(!$file) { 316 | return false; 317 | } 318 | $this->setLastCookieFile($file); 319 | } 320 | return file_put_contents($file, $content . "\n", FILE_APPEND); 321 | } 322 | return false; 323 | } 324 | 325 | /** 326 | * 获取临时文件 327 | * @return false|string 328 | */ 329 | public function getTempFile() { 330 | $file = tempnam(dirname($this->logPath), 'autologin_cookie_'); 331 | if(!$file) { 332 | $this->_log("tempnam创建临时文件失败,请检查"); 333 | return false; 334 | } 335 | return $file; 336 | } 337 | 338 | /** 339 | * 设置上一次存储cookie的文件 340 | * @param [type] $cookieFile [description] 341 | */ 342 | public function setLastCookieFile($cookieFile) { 343 | if(!$this->lockedLastCookieFile) { 344 | //移除上一个存储cookie的临时文件 345 | if(file_exists($this->lastCookieFile) && $this->lastCookieFile != $cookieFile) { 346 | unlink($this->lastCookieFile); 347 | } 348 | $this->lastCookieFile = $cookieFile; 349 | } 350 | return $this; 351 | } 352 | 353 | /** 354 | * 清空上次存储的cookie 355 | */ 356 | public function removeLastCookie() { 357 | if($file = $this->getLastCookieFile()) { 358 | //文件存在才清空 359 | if(file_exists($file)) { 360 | file_put_contents($file, ''); 361 | } 362 | } 363 | return $this; 364 | } 365 | 366 | /** 367 | * 登录成功后,锁定上一次存储cookie的文件,避免覆盖 368 | * @return [type] [description] 369 | */ 370 | public function lockLastCookieFile() { 371 | $this->lockedLastCookieFile = true; 372 | return $this; 373 | } 374 | 375 | /** 376 | * 解锁上一次存储cookie的文件 377 | * @return [type] [description] 378 | */ 379 | public function unlockLastCookieFile() { 380 | $this->lockedLastCookieFile = false; 381 | return $this; 382 | } 383 | 384 | /** 385 | * 登录成功后,锁定cookie,可以基于get方式获取url信息 386 | * @param [type] $url [description] 387 | * @param boolean $header [description] 388 | * @param array $opts [description] 389 | * @return [type] [description] 390 | */ 391 | public function getUrl($url, $header = false, $opts = []) { 392 | $ch = curl_init($url); 393 | curl_setopt($ch,CURLOPT_HEADER,0); 394 | curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); //返回数据不直接输出 395 | curl_setopt($ch, CURLOPT_ENCODING, "gzip"); //指定gzip压缩 396 | 397 | //add header 398 | if(!empty($header)) { 399 | curl_setopt($ch, CURLOPT_HTTPHEADER, $header); 400 | } 401 | 402 | //add ssl support 403 | if(substr($url, 0, 5) == 'https') { 404 | // curl_setopt($ch, CURLOPT_SSLVERSION,1); 405 | curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); //SSL 报错时使用 406 | curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false); //SSL 报错时使用 407 | } 408 | 409 | //add 302 support 410 | curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true); 411 | 412 | curl_setopt($ch,CURLOPT_COOKIEFILE, $this->getLastCookieFile()); //使用提交后得到的cookie数据 413 | 414 | //extend opt 415 | $opts += $this->globalOpts; 416 | if(!empty($opts)) { 417 | foreach ($opts as $key => $value) { 418 | curl_setopt($ch, $key, $value); 419 | } 420 | } 421 | 422 | $content = ''; 423 | try { 424 | $content = curl_exec($ch); //执行并存储结果 425 | } catch (\Exception $e) { 426 | $this->_log($e->getMessage()); 427 | } 428 | 429 | $curlError = curl_error($ch); 430 | if(!empty($curlError)) { 431 | $this->_log($curlError); 432 | } 433 | 434 | curl_close($ch); 435 | 436 | return $content; 437 | } 438 | 439 | /** 440 | * 登录成功后,锁定cookie,可以基于post方式获取url信息 441 | * @param [type] $url [description] 442 | * @param boolean $postData [description] 443 | * @param boolean $header [description] 444 | * @param array $opts [description] 445 | * @return [type] [description] 446 | */ 447 | public function postUrl($url, $postData = false, $header = false, $opts = []) { 448 | $ch = curl_init($url); 449 | curl_setopt($ch,CURLOPT_HEADER,0); 450 | curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); //返回数据不直接输出 451 | curl_setopt($ch, CURLOPT_ENCODING, "gzip"); //指定gzip压缩 452 | 453 | //add header 454 | if(!empty($header)) { 455 | curl_setopt($ch, CURLOPT_HTTPHEADER, $header); 456 | } 457 | 458 | //add ssl support 459 | if(substr($url, 0, 5) == 'https') { 460 | // curl_setopt($ch, CURLOPT_SSLVERSION,1); 461 | curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); //SSL 报错时使用 462 | curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false); //SSL 报错时使用 463 | } 464 | 465 | //add 302 support 466 | curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true); 467 | 468 | curl_setopt($ch,CURLOPT_COOKIEFILE, $this->getLastCookieFile()); //使用提交后得到的cookie数据 469 | 470 | //add post data support 471 | curl_setopt($ch,CURLOPT_POST, 1); 472 | if(!empty($postData)) { 473 | curl_setopt($ch,CURLOPT_POSTFIELDS, $postData); 474 | } 475 | 476 | //extend opt 477 | $opts += $this->globalOpts; 478 | if(!empty($opts)) { 479 | foreach ($opts as $key => $value) { 480 | curl_setopt($ch, $key, $value); 481 | } 482 | } 483 | 484 | $content = ''; 485 | try { 486 | $content = curl_exec($ch); //执行并存储结果 487 | } catch (\Exception $e) { 488 | $this->_log($e->getMessage()); 489 | } 490 | 491 | $curlError = curl_error($ch); 492 | if(!empty($curlError)) { 493 | $this->_log($curlError); 494 | } 495 | 496 | curl_close($ch); 497 | 498 | return $content; 499 | } 500 | 501 | /** 502 | * 断言内容中包含某个字符(判断登录信息,如“退出”字眼) 503 | * @param string $content 内容 504 | * @param string $subStr 包含字符串 505 | */ 506 | public function assertContainStr($content, $subStr) { 507 | if(false !== stripos($content, $subStr)) { 508 | return true; 509 | } 510 | 511 | return false; 512 | } 513 | 514 | /** 515 | * 获取换行符 516 | */ 517 | public function getLineBreak() { 518 | if('cli' == PHP_SAPI) { 519 | $lineBreak = "\n"; 520 | } else { 521 | $lineBreak = "
"; 522 | } 523 | 524 | return $lineBreak; 525 | } 526 | 527 | /** 528 | * 格式化header头cookie成文件存储格式 529 | * @param string $headerCookie //-H 'Cookie: xxxxx=xxxx;',单引号内容 530 | * @param string $domain //授权域名,如www.baidu.com,则传入.baidu.com,根前面有个点 531 | */ 532 | public function formatHeaderCookieToFileContent($headerCookie, $domain) { 533 | $rows = []; 534 | if(preg_match_all("#([^ ;]+)=([^ ;]+)#i", $headerCookie, $matches)) { 535 | foreach($matches[0] as $key => $value) { 536 | $rows[] = sprintf("#HttpOnly_%s\tTRUE\t/\tFALSE\t0\t%s\t%s", $domain, $matches[1][$key], $matches[2][$key]); 537 | } 538 | } 539 | return implode("\n", $rows); 540 | } 541 | 542 | /** 543 | * 从curl内容解析cookie内容并追加保存到cookie文件 544 | * @param $curlContent string 545 | * @param $domain string //授权域名,如www.baidu.com,则传入.baidu.com,根前面有个点 546 | */ 547 | public function addCookieFromCurl($curlContent, $domain) { 548 | $parseCurlResult = $this->parseCurl($curlContent); //解析curl内容获取cookie内容 549 | $cookieContent = $this->formatHeaderCookieToFileContent($parseCurlResult["cookie"], $domain); //格式化cookie内容 550 | $this->appendCookieContent($cookieContent); //追加cookie内容到cookie文件 551 | } 552 | } 553 | --------------------------------------------------------------------------------