├── .gitignore ├── .npmignore ├── README.MD ├── errors.js ├── index.js ├── links.md ├── links ├── 20181021.issue.html ├── 20190624.html ├── 20190624002.html ├── 20190719.html ├── 20190719002.html ├── break.html ├── document.write.html ├── expire.html ├── image.html ├── post.html ├── profile.html ├── quota_limit.html ├── video.2019.11.29.html └── video.html ├── package.json ├── parse-wechat-url.js ├── test.js ├── test ├── mp-link.html └── mp-links.js ├── util.js ├── video.js └── yarn.lock /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | node_modules 3 | links 4 | temp -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | links 2 | temp 3 | .DS_Store 4 | test 5 | -------------------------------------------------------------------------------- /README.MD: -------------------------------------------------------------------------------- 1 | # we-extract 2 | 3 | ## 介绍 4 | 5 | `we-extract` 用以解析微信公众号文章的账号及文章信息,居家旅行、采集微信公众号文章必备工具。 6 | 7 | `we-extract` 是微信公众号 RSS 订阅服务 `WeRss` 的核心解析工具,欢迎使用: 8 | 9 |

10 |
11 | 12 | 13 | 14 |

15 | 16 | ## 安装 17 | 18 | ``` 19 | npm install we-extract 20 | 21 | // or 22 | 23 | yarn add we-extract 24 | ``` 25 | 26 | ## 使用 27 | 28 | > Node 版本需要支持 async 29 | 30 | 31 | ``` js 32 | const extract = require('we-extract').extract 33 | 34 | const rs = await extract('微信文章 url 或者 文章内容') 35 | 36 | // 选项 37 | const rs = await extract('微信文章 url 或者 文章内容', { 38 | shouldReturnContent: true, // 是否返回内容,默认返回 39 | shouldExtractMpLinks: false, // v2.1.0 是否返回文章中出现的所有公众号文章链接,如果为 true,将返回 mp_links 数组 40 | shouldExtractTags: false, // v2.2.0 是否解析文章中的收录标签 41 | shouldExtractRepostMeta: false // v2.2.3 是否解析转载文章来源 42 | }) 43 | ``` 44 | 45 | ## 返回结果说明 46 | 47 | 48 | > 正确返回 49 | 50 | ``` js 51 | { 52 | done: true, 53 | code: 0, 54 | data: { 55 | account_name: '微信派', 56 | account_alias: 'wx-pai', 57 | account_avatar: 'http://wx.qlogo.cn/mmhead/Q3auHgzwzM7Xb5Qbdia5AuGTX4AeZSWYlv5TEqD1FicUDOrnEIwVak1A/132', 58 | account_description: '微信第一手官方活动信息发布,线下沙龙活动在线互动平台。独家分享微信公众平台优秀案例,以及权威专家的精彩观点。', 59 | account_id: 'gh_bc5ec2ee663f', 60 | account_biz: 'MjM5NjM4MDAxMg==', 61 | account_biz_number: 2396380012, 62 | account_qr_code: 'https://open.weixin.qq.com/qr/code?username=gh_bc5ec2ee663f', 63 | msg_has_copyright: false, // 是否原创 64 | msg_content: '省略的文章内容', 65 | msg_author: null, // 作者 66 | msg_sn: '9a0a54f2e7c8ac4019812aa78bd4b3e0', 67 | msg_idx: 1, 68 | msg_mid: 2655078412, 69 | msg_title: '重磅 | 微信订阅号全新改版上线!', 70 | msg_desc: '今后,头图也很重要', 71 | msg_link: 'http://mp.weixin.qq.com/s?__biz=MjM5NjM4MDAxMg==&mid=2655078412&idx=1&sn=9a0a54f2e7c8ac4019812aa78bd4b3e0&chksm=bd5fc40f8a284d19360e956074ffced37d8e2d78cb01a4ecdfaae40247823e7056b9d31ae3ef#rd', 72 | msg_source_url: null, // 音频,视频时,此处为音频、视频链接 73 | msg_cover: 'http://mmbiz.qpic.cn/mmbiz_jpg/OiaFLUqewuIDldpxsV3ZYJzzyH9HTFsSwOEPX82WEvBZozGiam3LbRSzpIIKGzj72nxjhLjnscWsibDPFmnpFZykg/0?wx_fmt=jpeg', 74 | msg_article_type: null, // 文章分类 75 | msg_publish_time: '2018-06-20T10:52:35.000Z', // date 类型 76 | msg_publish_time_str: '2018/06/20 18:52:35', 77 | msg_type: 'post', // 可能为 post text repost voice video image 78 | mp_links: [{ // 在 shouldExtractMpLinks = true 时返回 79 | title: '', 80 | href: '' 81 | }], 82 | tags: [{ // 在 shouldExtractTags = true 时返回 83 | id: '', 84 | url: '', 85 | name: '', 86 | count: 1 87 | }], 88 | repost_meta: { // 在 shouldExtractRepostMeta = true 时返回 89 | account_name: '文章来源账号名字' 90 | } 91 | } 92 | } 93 | ``` 94 | 95 | > 错误返回 96 | 97 | ``` js 98 | { 99 | done: false, 100 | code: 2002, 101 | msg: '链接已过期' 102 | } 103 | ``` 104 | 105 | ## 常见错误 106 | 107 | `we-extract` 定义了详细的错误信息方便开发和出错处理,`1` 开头错误表示可能需要重试(或者暂时将内容保存下来 debug),`2` 表示没有疑问的错误,可以不处理。 108 | 109 | 请使用 code(数字类型) 来判断而不是 message 内容,因为 message 可能会变化。 110 | 111 | ``` js 112 | module.exports = { 113 | '1000': '解析失败,可能文章内容不完整', 114 | '1001': '字段缺失', 115 | '1002': '请求文章内容失败', 116 | '1003': '请求文章内容为空', 117 | '1004': '访问过于频繁(URL模式)', // 可以换 ip 重新请求,注意与 2010 的区别 118 | '1005': 'js 变量解析出错', 119 | 120 | '2001': '参数缺失', 121 | '2002': '链接已过期', 122 | '2003': '该内容被投诉且经审核涉嫌侵权,无法查看', 123 | '2004': '公众号迁移但文章未同步', 124 | '2005': '该内容已被发布者删除', 125 | '2006': '此内容因违规无法查看', 126 | '2007': '涉嫌违反相关法律法规和政策发送失败', 127 | '2008': '微信文章系统出错', 128 | '2009': '链接不正确', 129 | '2010': '访问过于频繁(HTML模式)', // 解析参数为直接的文章内容,此时该篇内容已经无效,可以丢弃 130 | '2011': '由用户投诉并经平台审核,涉嫌过度营销、骚扰用户', 131 | '2012': '此帐号已被屏蔽', 132 | '2013': '此帐号已自主注销', 133 | '2014': '不实信息', 134 | '2016': '冒名侵权' 135 | } 136 | 137 | ``` 138 | 139 | ## 经验 140 | 141 | + 一个微信由 biz+mid+idx 组成,mid 在单个公众号内唯一。 142 | + 文章所属账号信息以文章解析结果为准,采集搜狗时不要相信账号名字,因为搜狗显示的可能是改名或者迁移前的账号信息。 143 | + 如果在搜狗微信搜不到账号,极有可能是因为公众号改了名字,试试以前的名字应该能搜索到。 144 | + 微信链接的 search 拼接符可能为 `&` 需要做一个替换处理,否则解析链接参数时会有问题。 145 | + 一个 ip 获取微信文章内容有限制,需要限制速率或者轮换 ip。 146 | 147 | 148 | ## 链接类型 149 | 150 | 图片:https://mp.weixin.qq.com/s/5tpbsFR1k_3744P0Egdnxg -------------------------------------------------------------------------------- /errors.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | '1000': '解析失败,可能文章内容不完整', 3 | '1001': '字段缺失', 4 | '1002': '请求文章内容失败', 5 | '1003': '请求文章内容为空', 6 | '1004': '访问过于频繁(url模式)', // 可以换 ip 重新请求,注意与 2010 的区别 7 | '1005': 'js 变量解析出错', 8 | '1006': '链接重定向', // 开启不 follow transfer link 后会有这个错误 9 | 10 | '2001': '参数缺失', 11 | '2002': '链接已过期', 12 | '2003': '该内容被投诉且经审核涉嫌侵权,无法查看', 13 | '2004': '公众号迁移但文章未同步', 14 | '2005': '该内容已被发布者删除', 15 | '2006': '此内容因违规无法查看', 16 | '2007': '涉嫌违反相关法律法规和政策发送失败', 17 | '2008': '微信文章系统出错', 18 | '2009': '链接不正确', 19 | '2010': '访问过于频繁(HTML模式)', // 解析参数为直接的文章内容,此时该篇内容已经无效,可以丢弃 20 | '2011': '由用户投诉并经平台审核,涉嫌过度营销、骚扰用户', 21 | '2012': '帐号已被屏蔽, 内容无法查看', 22 | '2013': '此帐号已自主注销', 23 | '2014': '不实信息', 24 | '2015': '此帐号处于帐号迁移流程中', 25 | '2016': '冒名侵权' 26 | } 27 | -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | const qs = require('qs') 2 | const dayjs = require('dayjs') 3 | const request = require('request-promise') 4 | const cheerio = require('cheerio') 5 | const parseUrl = require('./parse-wechat-url') 6 | const errors = require('./errors') 7 | const unescape = require('lodash.unescape') 8 | const { 9 | getParameterByName, 10 | normalizeUrl 11 | } = require('./util') 12 | 13 | const video = require('./video') 14 | 15 | const defaultConfig = { 16 | shouldReturnRawMeta: false, 17 | shouldReturnContent: true, 18 | shouldFollowTransferLink: true, 19 | shouldExtractMpLinks: false, 20 | shouldExtractTags: false, 21 | shouldExtractRepostMeta: false 22 | } 23 | 24 | const basic = {} 25 | basic.accountId = '' 26 | basic.accountAvatar = '' 27 | 28 | basic.accountBiz = null 29 | basic.accountBizNumber = null 30 | basic.accountName = null 31 | 32 | const getError = function(code) { 33 | return { 34 | done: false, 35 | code: code, 36 | msg: errors[code] 37 | } 38 | } 39 | 40 | const extract = async function(html, options = {}) { 41 | const { 42 | shouldReturnRawMeta, 43 | shouldReturnContent, 44 | shouldFollowTransferLink, 45 | shouldExtractMpLinks, 46 | shouldExtractTags, 47 | shouldExtractRepostMeta 48 | } = Object.assign({}, defaultConfig, options) 49 | 50 | let paramType = 'HTML' // 参数为 URL 还是 HTML 51 | let url = null 52 | let rawUrl = null 53 | 54 | if (options.url) { 55 | url = normalizeUrl(options.url) 56 | } 57 | 58 | let type = 'post' 59 | let hasCopyright = false 60 | let shareContentTpl 61 | 62 | if (!html) { 63 | return getError(2001) 64 | } 65 | 66 | // 参数错误 67 | 68 | // 支持地址 69 | if (/^http/.test(html)) { 70 | html = normalizeUrl(html) 71 | if (!/http(s?):\/\/mp.weixin.qq.com/.test(html) && !/http(s?):\/\/weixin.sogou.com/.test(html)) { 72 | return getError(2009) 73 | } 74 | paramType = 'URL' 75 | rawUrl = html 76 | if (!url) { 77 | url = html 78 | } 79 | let host = 'mp.weixin.qq.com' 80 | if (/http(s?):\/\/weixin.sogou.com/.test(html)) { 81 | host = 'weixin.sogou.com' 82 | } 83 | try { 84 | html = await request({ 85 | uri: html, 86 | method: 'GET', 87 | headers: { 88 | 'user-agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/66.0.3359.181 Safari/537.36', 89 | 'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8', 90 | 'Accept-Language': 'zh-CN,zh;q=0.9,en;q=0.8', 91 | 'Cache-Control': 'max-age=0', 92 | 'Connection': 'keep-alive', 93 | 'Host': host 94 | } 95 | }) 96 | 97 | // unknown purpose 98 | // if (html.includes('location.replace')) { 99 | // const rs = html.match(/([\s\S]*?)<\/script>/gi) 100 | // if (rs && rs[0]) { 101 | // const code = rs[0].split('\n').filter(one => { 102 | // return !one.includes('location.replace') && !one.includes('script>') 103 | // }).join('\n') + '\n return url;' 104 | 105 | // try { 106 | // const fn = new Function(code) 107 | // return await extract(fn(), options) 108 | // } catch (e) { 109 | // return getError(1005) 110 | // } 111 | // } 112 | // } 113 | } catch (e) { 114 | return getError(1002) 115 | } 116 | } else { 117 | html = html.replace(/\\n/g, '') 118 | } 119 | 120 | if (!html) { 121 | return getError(1003) 122 | } 123 | 124 | if (html.includes('访问过于频繁') && !html.includes('js_content')) { 125 | return paramType === 'URL' ? getError(1004) : getError(2010) 126 | } else if (html.includes('链接已过期') && !html.includes('js_content')) { 127 | return getError(2002) 128 | } else if (html.includes('被投诉且经审核涉嫌侵权,无法查看')) { 129 | return getError(2003) 130 | } else if (html.includes('该公众号已迁移')) { 131 | const match = html.match(/var\stransferTargetLink\s=\s'(.*?)';/) 132 | if (match && match[1]) { 133 | if (shouldFollowTransferLink) { 134 | return await extract(match[1]) 135 | } else { 136 | return { 137 | ...getError(1006), 138 | url: match[1] 139 | } 140 | } 141 | } else { 142 | return getError(2004) 143 | } 144 | } else if (html.includes('该内容已被发布者删除')) { 145 | return getError(2005) 146 | } else if (html.includes('此内容因违规无法查看')) { 147 | return getError(2006) 148 | } else if (html.includes('此内容发送失败无法查看')) { 149 | return getError(2007) 150 | } else if (html.includes('由用户投诉并经平台审核,涉嫌过度营销、骚扰用户')) { 151 | return getError(2011) 152 | } else if (html.includes('此帐号已被屏蔽') && !html.includes('id="js_content"')) { 153 | return getError(2012) 154 | } else if (html.includes('此帐号已自主注销') && !html.includes('id="js_content"')) { 155 | return getError(2013) 156 | } else if (!html.includes('id="js_content"') && html.includes('此帐号处于帐号迁移流程中')) { 157 | return getError(2015) 158 | } else if (html.includes('page_rumor') && !html.includes('id="js_content"')) { 159 | return getError(2014) 160 | } else if (html.includes('投诉类型') && html.includes('冒名侵权')) { 161 | return getError(2016) 162 | } else if (!html.includes('id="js_content"') && html.includes('参数错误') && html.includes('appmsg/error.html')) { 163 | return getError(2009) 164 | } else if (!html.includes('id="js_content"') && !html.includes('id=\\"js_content\\"')) { 165 | // http://mp.weixin.qq.com/s?__biz=MjM5ODIyMTE0MA==&mid=2650971473&idx=1&sn=f529f2a74fac89ed2a8ca8f7a44d93b3&chksm=bd38396a8a4fb07ce4ebab564de2ef01c2d50d60a225328c987cbf66e6167d067bc45f1527d3#rd 166 | // 图片类型但是没有 js_content 容器 167 | if (html.includes('cover_url')) { 168 | type = 'image' 169 | } else { 170 | return getError(1000) 171 | } 172 | } 173 | 174 | html = html.replace('>微信号', ' id="append-account-alias">微信号') 175 | .replace('>功能介绍', ' id="append-account-desc">功能介绍') 176 | .replace(/\n\s+ 21 | 视频 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 98 | 99 | 103 | 104 | 105 | 106 | 109 | 110 |
111 | 112 | 113 | 280 | 281 | 282 | 283 | 284 |
285 | 286 | 287 | 288 | 289 | 290 | 291 | 292 |
293 | 294 | 295 | 311 | 312 |
313 |
314 | 315 | 318 | 319 | 320 | 321 | 425 | 432 | 433 | 469 | 470 | 471 | 517 | 534 | 535 | 543 | 544 | 545 | 607 | 608 | 654 | 655 | 656 | 707 | 708 | 709 | 717 | 718 | 719 | 733 | 734 | 737 | 738 | 739 | -------------------------------------------------------------------------------- /links/expire.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 18 | 19 | 20 | 21 | 22 | 69 | 70 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 |
82 |
83 |
84 |

85 | 链接已过期 86 |

87 |
88 |
89 | 90 | 91 | 92 | 99 | 100 | 137 | 138 | 139 | 142 | 143 | 144 | 145 | 146 | \n \n \n\n\n\n\n\n\n\n \n \n \n\n\n\n\n\n \n \n\n\n\n \n \n \n\n\n \n \n\n\n \n \n\n \n \n\n\n\n -------------------------------------------------------------------------------- /links/video.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 19 | 视频 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 33 | 34 | 35 | 36 | 37 | 38 | 85 | 86 | 90 | 91 | 92 | 95 | 96 |
97 | 98 |
99 | 116 |
117 |
118 | 119 |
120 |
121 |
122 |

123 | 今天的推送,会动! 124 |

125 | 126 |
127 |
128 |
129 |
130 | 131 | 134 | 135 |
136 |
137 | 138 | 139 | 140 | 141 |
142 | 143 | 144 | 145 | 146 |
147 | 148 | 149 | 150 | 166 | 167 |
168 |
169 | 170 | 173 | 174 | 175 | 176 | 183 | 184 | 221 | 222 | 223 | 233 | 250 | 251 | 259 | 260 | 261 | 315 | 316 | 358 | 359 | 360 | 407 | 408 | 409 | 417 | 418 | 421 | 422 | 423 | 424 | 425 | 426 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "we-extract", 3 | "version": "2.3.22", 4 | "main": "index.js", 5 | "description": "微信公众号文章元信息解析", 6 | "keywords": [ 7 | "微信公众号文章", 8 | "微信公众号解析", 9 | "微信公众号" 10 | ], 11 | "author": "airyland ", 12 | "repository": { 13 | "type": "git", 14 | "url": "https://github.com/airyland/we-extract" 15 | }, 16 | "license": "MIT", 17 | "dependencies": { 18 | "cheerio": "^1.0.0-rc.2", 19 | "dayjs": "^1.7.4", 20 | "lodash": "^4.17.15", 21 | "lodash.unescape": "^4.0.1", 22 | "request": "^2.88.0", 23 | "request-promise": "^4.2.2" 24 | }, 25 | "devDependencies": { 26 | "axios": "^0.21.1" 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /parse-wechat-url.js: -------------------------------------------------------------------------------- 1 | const querystring = require('querystring') 2 | 3 | function parse (url) { 4 | if (!url) { 5 | return {} 6 | } 7 | 8 | const rs = querystring.parse(url.replace(/&/g, '&').split('?')[1]) 9 | return { 10 | mid: rs.mid * 1, 11 | idx: rs.idx * 1, 12 | sn: rs.sn, 13 | biz: rs.__biz 14 | } 15 | } 16 | 17 | module.exports = parse 18 | -------------------------------------------------------------------------------- /test.js: -------------------------------------------------------------------------------- 1 | const extract = require('.').extract 2 | const assert = require('assert') 3 | const fs = require('fs') 4 | 5 | ;(async function () { 6 | // const url = fs.readFileSync('./links/post.html', 'utf-8') 7 | // const postRs = await extract(url, { 8 | // shouldReturnContent: false 9 | // }) 10 | // 11 | // console.log(postRs) 12 | // 13 | // const expected = { 14 | // account_name: '微信派', 15 | // account_alias: 'wx-pai', 16 | // account_id: 'gh_bc5ec2ee663f', 17 | // account_biz: 'MjM5NjM4MDAxMg==', 18 | // account_biz_number: 2396380012, 19 | // account_qr_code: 'https://open.weixin.qq.com/qr/code?username=gh_bc5ec2ee663f', 20 | // msg_has_copyright: false, 21 | // msg_content: null, 22 | // msg_author: null, 23 | // msg_sn: '9a0a54f2e7c8ac4019812aa78bd4b3e0', 24 | // msg_idx: 1, 25 | // msg_mid: 2655078412, 26 | // msg_title: '重磅 | 微信订阅号全新改版上线!', 27 | // msg_desc: '今后,头图也很重要', 28 | // msg_link: 'http://mp.weixin.qq.com/s?__biz=MjM5NjM4MDAxMg==&mid=2655078412&idx=1&sn=9a0a54f2e7c8ac4019812aa78bd4b3e0&chksm=bd5fc40f8a284d19360e956074ffced37d8e2d78cb01a4ecdfaae40247823e7056b9d31ae3ef#rd', 29 | // msg_source_url: null, 30 | // msg_cover: 'http://mmbiz.qpic.cn/mmbiz_jpg/OiaFLUqewuIDldpxsV3ZYJzzyH9HTFsSwOEPX82WEvBZozGiam3LbRSzpIIKGzj72nxjhLjnscWsibDPFmnpFZykg/0?wx_fmt=jpeg', 31 | // msg_article_type: null, 32 | // msg_publish_time_str: '2018/06/20 18:52:35', 33 | // msg_type: 'post' 34 | // } 35 | // for (let i in expected) { 36 | // assert(postRs.data[i] === expected[i]) 37 | // } 38 | // 39 | // const link001 = fs.readFileSync('./links/quota_limit.html', 'utf-8') 40 | // const res001 = await extract(link001) 41 | // console.log(res001) 42 | // assert(res001.code === 2010) 43 | // 44 | // const imageUrl = fs.readFileSync('./links/image.html', 'utf-8') 45 | // const imageRs = await extract(imageUrl) 46 | // 47 | // console.log(imageRs) 48 | // 49 | // const videoUrl = fs.readFileSync('./links/video.html', 'utf-8') 50 | // const videoRs = await extract(videoUrl) 51 | // 52 | // console.log(videoRs) 53 | // 54 | // const documentWriteUrl = fs.readFileSync('./links/document.write.html', 'utf-8') 55 | // const documentWriteRs = await extract(documentWriteUrl) 56 | // 57 | // console.log(documentWriteRs) 58 | // 59 | // const _20181021WriteUrl = fs.readFileSync('./links/20181021.issue.html', 'utf-8') 60 | // const _20181021WriteRs = await extract(_20181021WriteUrl) 61 | // 62 | // console.log(_20181021WriteRs) 63 | 64 | // const issue3WriteUrl = fs.readFileSync('./links/issue3.html', 'utf-8') 65 | // const issue3WriteRs = await extract(issue3WriteUrl) 66 | 67 | // console.log(issue3WriteRs) 68 | 69 | // const sogou = await extract('https://mp.weixin.qq.com/s?src=3×tamp=1559431337&ver=1&signature=K*8sgrrv9y5KoQr22U2gh3Tut0DIldkcZ67t4Oc3BzcyNEQMtX3l459-K2JvxxeLvWbdhtjtuzSWorY-zsW-Nm2Rloy30WAJi82JmQGYI2GlWpIcFuXNh53g1jY*Dh8XRczrRrjewQgRj*N1Kg8FK0j5W-3wb*NdM3JzzhO4jWc=') 70 | 71 | // console.log(sogou) 72 | 73 | const url = fs.readFileSync('./links/20240107.html', 'utf-8') 74 | const postRs = await extract(url, { 75 | shouldReturnContent: true 76 | }) 77 | 78 | console.log(postRs) 79 | 80 | })() 81 | -------------------------------------------------------------------------------- /test/mp-links.js: -------------------------------------------------------------------------------- 1 | const extract = require('..').extract 2 | const assert = require('assert') 3 | const fs = require('fs') 4 | const path = require('path') 5 | 6 | const url = 'https://mp.weixin.qq.com/s?__biz=MzIwNjU2ODk1MQ==&mid=2247497639&idx=1&sn=bba35c164cbae04da8d78808151d35aa&chksm=971d1b3fa06a922971367bca63cce1f8a754b582c4ce7c2d07dfb28e5dd2b38d7695ff72b56b&scene=132#wechat_redirect' 7 | 8 | const content = fs.readFileSync(path.join(__dirname, './mp-link.html'), 'utf-8') 9 | ;(async () => { 10 | const res = await extract(content, { 11 | shouldReturnContent: false, 12 | shouldExtractMpLinks: true 13 | }) 14 | console.log(JSON.stringify(res, null, 2)) 15 | })() 16 | -------------------------------------------------------------------------------- /util.js: -------------------------------------------------------------------------------- 1 | const qs = require('qs') 2 | 3 | function getParameterByName(name, url = window.location.href) { 4 | name = name.replace(/[\[\]]/g, '\\$&'); 5 | var regex = new RegExp('[?&]' + name + '(=([^&#]*)|&|#|$)'), 6 | results = regex.exec(url); 7 | if (!results) return null; 8 | if (!results[2]) return ''; 9 | return decodeURIComponent(results[2].replace(/\+/g, ' ')); 10 | } 11 | 12 | function normalizeUrl (url = '') { 13 | const parts = url.replace(/&/g, '&').split('?') 14 | const rs = qs.parse(parts[1]) 15 | const querys = qs.stringify(rs) 16 | if (querys) { 17 | return parts[0] + '?' + querys 18 | } else { 19 | return parts[0] 20 | } 21 | } 22 | 23 | module.exports = { 24 | getParameterByName, 25 | normalizeUrl 26 | } -------------------------------------------------------------------------------- /video.js: -------------------------------------------------------------------------------- 1 | const dayjs = require('dayjs') 2 | 3 | module.exports = function({ 4 | post, 5 | basic, 6 | script, 7 | getError, 8 | html, 9 | $, 10 | shouldReturnRawMeta 11 | }) { 12 | const lines = script.split('\n') 13 | const lines2 = lines.filter(line => !!line.trim()) 14 | let code = lines2.filter((line, index) => { 15 | return /d\./.test(line) || (lines2[index - 1] && lines2[index - 1].includes('d.') && !line.includes('}')) 16 | }) 17 | code = `var d = {}; 18 | \nfunction getXmlValue (path) { 19 | return false 20 | }\n` + code.join('\n').replace('var d = _g.cgiData;', 'var d = {}') + '\n return d;' 21 | let data = {} 22 | code = `var _g = {};` + code 23 | const fn = new Function(code) 24 | data = fn() 25 | basic.accountName = data.nick_name 26 | basic.accountAvatar = data.hd_head_img 27 | basic.accountId = data.user_name 28 | 29 | // biz 30 | if (!basic.accountBiz && data.biz) { 31 | basic.accountBiz = data.biz 32 | basic.accountBizNumber = Buffer.from(basic.accountBiz, 'base64').toString() * 1 33 | } 34 | 35 | // 标题 36 | post.msg_title = data.title 37 | post.msg_desc = null 38 | post.msg_cover = null 39 | post.msg_link = data.msg_link || null 40 | post.msg_article_type = null 41 | 42 | // sn, idx, mid 43 | post.msg_sn = data.sn || null 44 | post.msg_idx = data.idx ? data.idx * 1 : null 45 | post.msg_mid = data.mid ? data.mid * 1 : null 46 | 47 | // 视频链接赋值于 source_url 48 | const vidMatch = html.match(/vid\s*:\s*'(.*?)'/) 49 | if (vidMatch && vidMatch[1]) { 50 | data.vid = vidMatch[1] 51 | // 旧版 vid 已经不适用 52 | // post.msg_source_url = 'http://v.qq.com/x/page/' + vid + '.html' 53 | } 54 | if (!post.msg_cover) { 55 | // 旧版废弃 56 | // post.msg_cover = `https://vpic.video.qq.com/60643382/${vid}.png` 57 | post.msg_cover = $("meta[property='og:image']").attr("content") 58 | } 59 | 60 | // 视频只有标题 + 内容,内容直接从 meta 里取 61 | const description = $("meta[name='description']").attr("content") 62 | post.msg_content = description 63 | 64 | // 发布时间 65 | if (data.create_time) { 66 | post.msg_publish_time = new Date(data.create_time * 1000) 67 | post.msg_publish_time_str = dayjs(post.msg_publish_time).format('YYYY/MM/DD HH:mm:ss') 68 | } 69 | 70 | // 如果没有,使用 ct_str 71 | if (!data.create_time && data.ct_str) { 72 | post.msg_publish_time = new Date(data.ct_str) 73 | post.msg_publish_time_str = dayjs(post.msg_publish_time).format('YYYY/MM/DD HH:mm:ss') 74 | } 75 | 76 | if (shouldReturnRawMeta) { 77 | post.raw_data = data 78 | } 79 | 80 | } -------------------------------------------------------------------------------- /yarn.lock: -------------------------------------------------------------------------------- 1 | # THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. 2 | # yarn lockfile v1 3 | 4 | 5 | "@types/node@*": 6 | version "10.5.3" 7 | resolved "http://registry.npm.taobao.org/@types/node/download/@types/node-10.5.3.tgz#5bcfaf088ad17894232012877669634c06b20cc5" 8 | integrity sha1-W8+vCIrReJQjIBKHdmljTAayDMU= 9 | 10 | ajv@^6.5.5: 11 | version "6.10.0" 12 | resolved "http://registry.npm.taobao.org/ajv/download/ajv-6.10.0.tgz#90d0d54439da587cd7e843bfb7045f50bd22bdf1" 13 | integrity sha1-kNDVRDnaWHzX6EO/twRfUL0ivfE= 14 | dependencies: 15 | fast-deep-equal "^2.0.1" 16 | fast-json-stable-stringify "^2.0.0" 17 | json-schema-traverse "^0.4.1" 18 | uri-js "^4.2.2" 19 | 20 | asn1@~0.2.3: 21 | version "0.2.4" 22 | resolved "http://registry.npm.taobao.org/asn1/download/asn1-0.2.4.tgz#8d2475dfab553bb33e77b54e59e880bb8ce23136" 23 | integrity sha1-jSR136tVO7M+d7VOWeiAu4ziMTY= 24 | dependencies: 25 | safer-buffer "~2.1.0" 26 | 27 | assert-plus@1.0.0, assert-plus@^1.0.0: 28 | version "1.0.0" 29 | resolved "http://registry.npm.taobao.org/assert-plus/download/assert-plus-1.0.0.tgz#f12e0f3c5d77b0b1cdd9146942e4e96c1e4dd525" 30 | integrity sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU= 31 | 32 | asynckit@^0.4.0: 33 | version "0.4.0" 34 | resolved "http://registry.npm.taobao.org/asynckit/download/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79" 35 | integrity sha1-x57Zf380y48robyXkLzDZkdLS3k= 36 | 37 | aws-sign2@~0.7.0: 38 | version "0.7.0" 39 | resolved "http://registry.npm.taobao.org/aws-sign2/download/aws-sign2-0.7.0.tgz#b46e890934a9591f2d2f6f86d7e6a9f1b3fe76a8" 40 | integrity sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg= 41 | 42 | aws4@^1.8.0: 43 | version "1.8.0" 44 | resolved "http://registry.npm.taobao.org/aws4/download/aws4-1.8.0.tgz#f0e003d9ca9e7f59c7a508945d7b2ef9a04a542f" 45 | integrity sha1-8OAD2cqef1nHpQiUXXsu+aBKVC8= 46 | 47 | axios@^0.21.1: 48 | version "0.21.1" 49 | resolved "https://registry.yarnpkg.com/axios/-/axios-0.21.1.tgz#22563481962f4d6bde9a76d516ef0e5d3c09b2b8" 50 | integrity sha512-dKQiRHxGD9PPRIUNIWvZhPTPpl1rf/OxTYKsqKUDjBwYylTvV7SjSHJb9ratfyzM6wCdLCOYLzs73qpg5c4iGA== 51 | dependencies: 52 | follow-redirects "^1.10.0" 53 | 54 | bcrypt-pbkdf@^1.0.0: 55 | version "1.0.2" 56 | resolved "http://registry.npm.taobao.org/bcrypt-pbkdf/download/bcrypt-pbkdf-1.0.2.tgz#a4301d389b6a43f9b67ff3ca11a3f6637e360e9e" 57 | integrity sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4= 58 | dependencies: 59 | tweetnacl "^0.14.3" 60 | 61 | bluebird@^3.5.0: 62 | version "3.5.1" 63 | resolved "http://registry.npm.taobao.org/bluebird/download/bluebird-3.5.1.tgz#d9551f9de98f1fcda1e683d17ee91a0602ee2eb9" 64 | integrity sha1-2VUfnemPH82h5oPRfukaBgLuLrk= 65 | 66 | boolbase@~1.0.0: 67 | version "1.0.0" 68 | resolved "http://registry.npm.taobao.org/boolbase/download/boolbase-1.0.0.tgz#68dff5fbe60c51eb37725ea9e3ed310dcc1e776e" 69 | integrity sha1-aN/1++YMUes3cl6p4+0xDcwed24= 70 | 71 | caseless@~0.12.0: 72 | version "0.12.0" 73 | resolved "http://registry.npm.taobao.org/caseless/download/caseless-0.12.0.tgz#1b681c21ff84033c826543090689420d187151dc" 74 | integrity sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw= 75 | 76 | cheerio@^1.0.0-rc.2: 77 | version "1.0.0-rc.2" 78 | resolved "http://registry.npm.taobao.org/cheerio/download/cheerio-1.0.0-rc.2.tgz#4b9f53a81b27e4d5dac31c0ffd0cfa03cc6830db" 79 | integrity sha1-S59TqBsn5NXawxwP/Qz6A8xoMNs= 80 | dependencies: 81 | css-select "~1.2.0" 82 | dom-serializer "~0.1.0" 83 | entities "~1.1.1" 84 | htmlparser2 "^3.9.1" 85 | lodash "^4.15.0" 86 | parse5 "^3.0.1" 87 | 88 | combined-stream@^1.0.6, combined-stream@~1.0.6: 89 | version "1.0.7" 90 | resolved "http://registry.npm.taobao.org/combined-stream/download/combined-stream-1.0.7.tgz#2d1d24317afb8abe95d6d2c0b07b57813539d828" 91 | integrity sha1-LR0kMXr7ir6V1tLAsHtXgTU52Cg= 92 | dependencies: 93 | delayed-stream "~1.0.0" 94 | 95 | core-util-is@1.0.2, core-util-is@~1.0.0: 96 | version "1.0.2" 97 | resolved "http://registry.npm.taobao.org/core-util-is/download/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7" 98 | integrity sha1-tf1UIgqivFq1eqtxQMlAdUUDwac= 99 | 100 | css-select@~1.2.0: 101 | version "1.2.0" 102 | resolved "http://registry.npm.taobao.org/css-select/download/css-select-1.2.0.tgz#2b3a110539c5355f1cd8d314623e870b121ec858" 103 | integrity sha1-KzoRBTnFNV8c2NMUYj6HCxIeyFg= 104 | dependencies: 105 | boolbase "~1.0.0" 106 | css-what "2.1" 107 | domutils "1.5.1" 108 | nth-check "~1.0.1" 109 | 110 | css-what@2.1: 111 | version "2.1.0" 112 | resolved "http://registry.npm.taobao.org/css-what/download/css-what-2.1.0.tgz#9467d032c38cfaefb9f2d79501253062f87fa1bd" 113 | integrity sha1-lGfQMsOM+u+58teVASUwYvh/ob0= 114 | 115 | dashdash@^1.12.0: 116 | version "1.14.1" 117 | resolved "http://registry.npm.taobao.org/dashdash/download/dashdash-1.14.1.tgz#853cfa0f7cbe2fed5de20326b8dd581035f6e2f0" 118 | integrity sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA= 119 | dependencies: 120 | assert-plus "^1.0.0" 121 | 122 | dayjs@^1.7.4: 123 | version "1.7.4" 124 | resolved "http://registry.npm.taobao.org/dayjs/download/dayjs-1.7.4.tgz#6001277372aec83021943157fa279ecf2b5f5cf8" 125 | integrity sha1-YAEnc3KuyDAhlDFX+ieezytfXPg= 126 | 127 | delayed-stream@~1.0.0: 128 | version "1.0.0" 129 | resolved "http://registry.npm.taobao.org/delayed-stream/download/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619" 130 | integrity sha1-3zrhmayt+31ECqrgsp4icrJOxhk= 131 | 132 | dom-serializer@0, dom-serializer@~0.1.0: 133 | version "0.1.0" 134 | resolved "http://registry.npm.taobao.org/dom-serializer/download/dom-serializer-0.1.0.tgz#073c697546ce0780ce23be4a28e293e40bc30c82" 135 | integrity sha1-BzxpdUbOB4DOI75KKOKT5AvDDII= 136 | dependencies: 137 | domelementtype "~1.1.1" 138 | entities "~1.1.1" 139 | 140 | domelementtype@1, domelementtype@^1.3.0: 141 | version "1.3.0" 142 | resolved "http://registry.npm.taobao.org/domelementtype/download/domelementtype-1.3.0.tgz#b17aed82e8ab59e52dd9c19b1756e0fc187204c2" 143 | integrity sha1-sXrtguirWeUt2cGbF1bg/BhyBMI= 144 | 145 | domelementtype@~1.1.1: 146 | version "1.1.3" 147 | resolved "http://registry.npm.taobao.org/domelementtype/download/domelementtype-1.1.3.tgz#bd28773e2642881aec51544924299c5cd822185b" 148 | integrity sha1-vSh3PiZCiBrsUVRJJCmcXNgiGFs= 149 | 150 | domhandler@^2.3.0: 151 | version "2.4.2" 152 | resolved "http://registry.npm.taobao.org/domhandler/download/domhandler-2.4.2.tgz#8805097e933d65e85546f726d60f5eb88b44f803" 153 | integrity sha1-iAUJfpM9ZehVRvcm1g9euItE+AM= 154 | dependencies: 155 | domelementtype "1" 156 | 157 | domutils@1.5.1: 158 | version "1.5.1" 159 | resolved "http://registry.npm.taobao.org/domutils/download/domutils-1.5.1.tgz#dcd8488a26f563d61079e48c9f7b7e32373682cf" 160 | integrity sha1-3NhIiib1Y9YQeeSMn3t+Mjc2gs8= 161 | dependencies: 162 | dom-serializer "0" 163 | domelementtype "1" 164 | 165 | domutils@^1.5.1: 166 | version "1.7.0" 167 | resolved "http://registry.npm.taobao.org/domutils/download/domutils-1.7.0.tgz#56ea341e834e06e6748af7a1cb25da67ea9f8c2a" 168 | integrity sha1-Vuo0HoNOBuZ0ivehyyXaZ+qfjCo= 169 | dependencies: 170 | dom-serializer "0" 171 | domelementtype "1" 172 | 173 | ecc-jsbn@~0.1.1: 174 | version "0.1.2" 175 | resolved "http://registry.npm.taobao.org/ecc-jsbn/download/ecc-jsbn-0.1.2.tgz#3a83a904e54353287874c564b7549386849a98c9" 176 | integrity sha1-OoOpBOVDUyh4dMVkt1SThoSamMk= 177 | dependencies: 178 | jsbn "~0.1.0" 179 | safer-buffer "^2.1.0" 180 | 181 | entities@^1.1.1, entities@~1.1.1: 182 | version "1.1.1" 183 | resolved "http://registry.npm.taobao.org/entities/download/entities-1.1.1.tgz#6e5c2d0a5621b5dadaecef80b90edfb5cd7772f0" 184 | integrity sha1-blwtClYhtdra7O+AuQ7ftc13cvA= 185 | 186 | extend@~3.0.2: 187 | version "3.0.2" 188 | resolved "http://registry.npm.taobao.org/extend/download/extend-3.0.2.tgz#f8b1136b4071fbd8eb140aff858b1019ec2915fa" 189 | integrity sha1-+LETa0Bx+9jrFAr/hYsQGewpFfo= 190 | 191 | extsprintf@1.3.0: 192 | version "1.3.0" 193 | resolved "http://registry.npm.taobao.org/extsprintf/download/extsprintf-1.3.0.tgz#96918440e3041a7a414f8c52e3c574eb3c3e1e05" 194 | integrity sha1-lpGEQOMEGnpBT4xS48V06zw+HgU= 195 | 196 | extsprintf@^1.2.0: 197 | version "1.4.0" 198 | resolved "http://registry.npm.taobao.org/extsprintf/download/extsprintf-1.4.0.tgz#e2689f8f356fad62cca65a3a91c5df5f9551692f" 199 | integrity sha1-4mifjzVvrWLMplo6kcXfX5VRaS8= 200 | 201 | fast-deep-equal@^2.0.1: 202 | version "2.0.1" 203 | resolved "http://registry.npm.taobao.org/fast-deep-equal/download/fast-deep-equal-2.0.1.tgz#7b05218ddf9667bf7f370bf7fdb2cb15fdd0aa49" 204 | integrity sha1-ewUhjd+WZ79/Nwv3/bLLFf3Qqkk= 205 | 206 | fast-json-stable-stringify@^2.0.0: 207 | version "2.0.0" 208 | resolved "http://registry.npm.taobao.org/fast-json-stable-stringify/download/fast-json-stable-stringify-2.0.0.tgz#d5142c0caee6b1189f87d3a76111064f86c8bbf2" 209 | integrity sha1-1RQsDK7msRifh9OnYREGT4bIu/I= 210 | 211 | follow-redirects@^1.10.0: 212 | version "1.14.0" 213 | resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.14.0.tgz#f5d260f95c5f8c105894491feee5dc8993b402fe" 214 | integrity sha512-0vRwd7RKQBTt+mgu87mtYeofLFZpTas2S9zY+jIeuLJMNvudIgF52nr19q40HOwH5RrhWIPuj9puybzSJiRrVg== 215 | 216 | forever-agent@~0.6.1: 217 | version "0.6.1" 218 | resolved "http://registry.npm.taobao.org/forever-agent/download/forever-agent-0.6.1.tgz#fbc71f0c41adeb37f96c577ad1ed42d8fdacca91" 219 | integrity sha1-+8cfDEGt6zf5bFd60e1C2P2sypE= 220 | 221 | form-data@~2.3.2: 222 | version "2.3.3" 223 | resolved "http://registry.npm.taobao.org/form-data/download/form-data-2.3.3.tgz#dcce52c05f644f298c6a7ab936bd724ceffbf3a6" 224 | integrity sha1-3M5SwF9kTymManq5Nr1yTO/786Y= 225 | dependencies: 226 | asynckit "^0.4.0" 227 | combined-stream "^1.0.6" 228 | mime-types "^2.1.12" 229 | 230 | getpass@^0.1.1: 231 | version "0.1.7" 232 | resolved "http://registry.npm.taobao.org/getpass/download/getpass-0.1.7.tgz#5eff8e3e684d569ae4cb2b1282604e8ba62149fa" 233 | integrity sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo= 234 | dependencies: 235 | assert-plus "^1.0.0" 236 | 237 | har-schema@^2.0.0: 238 | version "2.0.0" 239 | resolved "http://registry.npm.taobao.org/har-schema/download/har-schema-2.0.0.tgz#a94c2224ebcac04782a0d9035521f24735b7ec92" 240 | integrity sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI= 241 | 242 | har-validator@~5.1.0: 243 | version "5.1.3" 244 | resolved "http://registry.npm.taobao.org/har-validator/download/har-validator-5.1.3.tgz#1ef89ebd3e4996557675eed9893110dc350fa080" 245 | integrity sha1-HvievT5JllV2de7ZiTEQ3DUPoIA= 246 | dependencies: 247 | ajv "^6.5.5" 248 | har-schema "^2.0.0" 249 | 250 | htmlparser2@^3.9.1: 251 | version "3.9.2" 252 | resolved "http://registry.npm.taobao.org/htmlparser2/download/htmlparser2-3.9.2.tgz#1bdf87acca0f3f9e53fa4fcceb0f4b4cbb00b338" 253 | integrity sha1-G9+HrMoPP55T+k/M6w9LTLsAszg= 254 | dependencies: 255 | domelementtype "^1.3.0" 256 | domhandler "^2.3.0" 257 | domutils "^1.5.1" 258 | entities "^1.1.1" 259 | inherits "^2.0.1" 260 | readable-stream "^2.0.2" 261 | 262 | http-signature@~1.2.0: 263 | version "1.2.0" 264 | resolved "http://registry.npm.taobao.org/http-signature/download/http-signature-1.2.0.tgz#9aecd925114772f3d95b65a60abb8f7c18fbace1" 265 | integrity sha1-muzZJRFHcvPZW2WmCruPfBj7rOE= 266 | dependencies: 267 | assert-plus "^1.0.0" 268 | jsprim "^1.2.2" 269 | sshpk "^1.7.0" 270 | 271 | inherits@^2.0.1, inherits@~2.0.3: 272 | version "2.0.3" 273 | resolved "http://registry.npm.taobao.org/inherits/download/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de" 274 | integrity sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4= 275 | 276 | is-typedarray@~1.0.0: 277 | version "1.0.0" 278 | resolved "http://registry.npm.taobao.org/is-typedarray/download/is-typedarray-1.0.0.tgz#e479c80858df0c1b11ddda6940f96011fcda4a9a" 279 | integrity sha1-5HnICFjfDBsR3dppQPlgEfzaSpo= 280 | 281 | isarray@~1.0.0: 282 | version "1.0.0" 283 | resolved "http://registry.npm.taobao.org/isarray/download/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11" 284 | integrity sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE= 285 | 286 | isstream@~0.1.2: 287 | version "0.1.2" 288 | resolved "http://registry.npm.taobao.org/isstream/download/isstream-0.1.2.tgz#47e63f7af55afa6f92e1500e690eb8b8529c099a" 289 | integrity sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo= 290 | 291 | jsbn@~0.1.0: 292 | version "0.1.1" 293 | resolved "http://registry.npm.taobao.org/jsbn/download/jsbn-0.1.1.tgz#a5e654c2e5a2deb5f201d96cefbca80c0ef2f513" 294 | integrity sha1-peZUwuWi3rXyAdls77yoDA7y9RM= 295 | 296 | json-schema-traverse@^0.4.1: 297 | version "0.4.1" 298 | resolved "http://registry.npm.taobao.org/json-schema-traverse/download/json-schema-traverse-0.4.1.tgz#69f6a87d9513ab8bb8fe63bdb0979c448e684660" 299 | integrity sha1-afaofZUTq4u4/mO9sJecRI5oRmA= 300 | 301 | json-schema@0.2.3: 302 | version "0.2.3" 303 | resolved "http://registry.npm.taobao.org/json-schema/download/json-schema-0.2.3.tgz#b480c892e59a2f05954ce727bd3f2a4e882f9e13" 304 | integrity sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM= 305 | 306 | json-stringify-safe@~5.0.1: 307 | version "5.0.1" 308 | resolved "http://registry.npm.taobao.org/json-stringify-safe/download/json-stringify-safe-5.0.1.tgz#1296a2d58fd45f19a0f6ce01d65701e2c735b6eb" 309 | integrity sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus= 310 | 311 | jsprim@^1.2.2: 312 | version "1.4.1" 313 | resolved "http://registry.npm.taobao.org/jsprim/download/jsprim-1.4.1.tgz#313e66bc1e5cc06e438bc1b7499c2e5c56acb6a2" 314 | integrity sha1-MT5mvB5cwG5Di8G3SZwuXFastqI= 315 | dependencies: 316 | assert-plus "1.0.0" 317 | extsprintf "1.3.0" 318 | json-schema "0.2.3" 319 | verror "1.10.0" 320 | 321 | lodash.unescape@^4.0.1: 322 | version "4.0.1" 323 | resolved "http://registry.npm.taobao.org/lodash.unescape/download/lodash.unescape-4.0.1.tgz#bf2249886ce514cda112fae9218cdc065211fc9c" 324 | integrity sha1-vyJJiGzlFM2hEvrpIYzcBlIR/Jw= 325 | 326 | lodash@^4.13.1, lodash@^4.15.0, lodash@^4.17.15: 327 | version "4.17.21" 328 | resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c" 329 | integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg== 330 | 331 | mime-db@~1.38.0: 332 | version "1.38.0" 333 | resolved "http://registry.npm.taobao.org/mime-db/download/mime-db-1.38.0.tgz#1a2aab16da9eb167b49c6e4df2d9c68d63d8e2ad" 334 | integrity sha1-GiqrFtqesWe0nG5N8tnGjWPY4q0= 335 | 336 | mime-types@^2.1.12, mime-types@~2.1.19: 337 | version "2.1.22" 338 | resolved "http://registry.npm.taobao.org/mime-types/download/mime-types-2.1.22.tgz#fe6b355a190926ab7698c9a0556a11199b2199bd" 339 | integrity sha1-/ms1WhkJJqt2mMmgVWoRGZshmb0= 340 | dependencies: 341 | mime-db "~1.38.0" 342 | 343 | nth-check@~1.0.1: 344 | version "1.0.1" 345 | resolved "http://registry.npm.taobao.org/nth-check/download/nth-check-1.0.1.tgz#9929acdf628fc2c41098deab82ac580cf149aae4" 346 | integrity sha1-mSms32KPwsQQmN6rgqxYDPFJquQ= 347 | dependencies: 348 | boolbase "~1.0.0" 349 | 350 | oauth-sign@~0.9.0: 351 | version "0.9.0" 352 | resolved "http://registry.npm.taobao.org/oauth-sign/download/oauth-sign-0.9.0.tgz#47a7b016baa68b5fa0ecf3dee08a85c679ac6455" 353 | integrity sha1-R6ewFrqmi1+g7PPe4IqFxnmsZFU= 354 | 355 | parse5@^3.0.1: 356 | version "3.0.3" 357 | resolved "http://registry.npm.taobao.org/parse5/download/parse5-3.0.3.tgz#042f792ffdd36851551cf4e9e066b3874ab45b5c" 358 | integrity sha1-BC95L/3TaFFVHPTp4Gazh0q0W1w= 359 | dependencies: 360 | "@types/node" "*" 361 | 362 | performance-now@^2.1.0: 363 | version "2.1.0" 364 | resolved "http://registry.npm.taobao.org/performance-now/download/performance-now-2.1.0.tgz#6309f4e0e5fa913ec1c69307ae364b4b377c9e7b" 365 | integrity sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns= 366 | 367 | process-nextick-args@~2.0.0: 368 | version "2.0.0" 369 | resolved "http://registry.npm.taobao.org/process-nextick-args/download/process-nextick-args-2.0.0.tgz#a37d732f4271b4ab1ad070d35508e8290788ffaa" 370 | integrity sha1-o31zL0JxtKsa0HDTVQjoKQeI/6o= 371 | 372 | psl@^1.1.24: 373 | version "1.1.28" 374 | resolved "http://registry.npm.taobao.org/psl/download/psl-1.1.28.tgz#4fb6ceb08a1e2214d4fd4de0ca22dae13740bc7b" 375 | integrity sha1-T7bOsIoeIhTU/U3gyiLa4TdAvHs= 376 | 377 | punycode@^1.4.1: 378 | version "1.4.1" 379 | resolved "http://registry.npm.taobao.org/punycode/download/punycode-1.4.1.tgz#c0d5a63b2718800ad8e1eb0fa5269c84dd41845e" 380 | integrity sha1-wNWmOycYgArY4esPpSachN1BhF4= 381 | 382 | punycode@^2.1.0: 383 | version "2.1.1" 384 | resolved "http://registry.npm.taobao.org/punycode/download/punycode-2.1.1.tgz#b58b010ac40c22c5657616c8d2c2c02c7bf479ec" 385 | integrity sha1-tYsBCsQMIsVldhbI0sLALHv0eew= 386 | 387 | qs@~6.5.2: 388 | version "6.5.2" 389 | resolved "http://registry.npm.taobao.org/qs/download/qs-6.5.2.tgz?cache=0&other_urls=http%3A%2F%2Fregistry.npm.taobao.org%2Fqs%2Fdownload%2Fqs-6.5.2.tgz#cb3ae806e8740444584ef154ce8ee98d403f3e36" 390 | integrity sha1-yzroBuh0BERYTvFUzo7pjUA/PjY= 391 | 392 | readable-stream@^2.0.2: 393 | version "2.3.6" 394 | resolved "http://registry.npm.taobao.org/readable-stream/download/readable-stream-2.3.6.tgz#b11c27d88b8ff1fbe070643cf94b0c79ae1b0aaf" 395 | integrity sha1-sRwn2IuP8fvgcGQ8+UsMea4bCq8= 396 | dependencies: 397 | core-util-is "~1.0.0" 398 | inherits "~2.0.3" 399 | isarray "~1.0.0" 400 | process-nextick-args "~2.0.0" 401 | safe-buffer "~5.1.1" 402 | string_decoder "~1.1.1" 403 | util-deprecate "~1.0.1" 404 | 405 | request-promise-core@1.1.1: 406 | version "1.1.1" 407 | resolved "http://registry.npm.taobao.org/request-promise-core/download/request-promise-core-1.1.1.tgz#3eee00b2c5aa83239cfb04c5700da36f81cd08b6" 408 | integrity sha1-Pu4AssWqgyOc+wTFcA2jb4HNCLY= 409 | dependencies: 410 | lodash "^4.13.1" 411 | 412 | request-promise@^4.2.2: 413 | version "4.2.2" 414 | resolved "http://registry.npm.taobao.org/request-promise/download/request-promise-4.2.2.tgz#d1ea46d654a6ee4f8ee6a4fea1018c22911904b4" 415 | integrity sha1-0epG1lSm7k+O5qT+oQGMIpEZBLQ= 416 | dependencies: 417 | bluebird "^3.5.0" 418 | request-promise-core "1.1.1" 419 | stealthy-require "^1.1.0" 420 | tough-cookie ">=2.3.3" 421 | 422 | request@^2.88.0: 423 | version "2.88.0" 424 | resolved "http://registry.npm.taobao.org/request/download/request-2.88.0.tgz#9c2fca4f7d35b592efe57c7f0a55e81052124fef" 425 | integrity sha1-nC/KT301tZLv5Xx/ClXoEFIST+8= 426 | dependencies: 427 | aws-sign2 "~0.7.0" 428 | aws4 "^1.8.0" 429 | caseless "~0.12.0" 430 | combined-stream "~1.0.6" 431 | extend "~3.0.2" 432 | forever-agent "~0.6.1" 433 | form-data "~2.3.2" 434 | har-validator "~5.1.0" 435 | http-signature "~1.2.0" 436 | is-typedarray "~1.0.0" 437 | isstream "~0.1.2" 438 | json-stringify-safe "~5.0.1" 439 | mime-types "~2.1.19" 440 | oauth-sign "~0.9.0" 441 | performance-now "^2.1.0" 442 | qs "~6.5.2" 443 | safe-buffer "^5.1.2" 444 | tough-cookie "~2.4.3" 445 | tunnel-agent "^0.6.0" 446 | uuid "^3.3.2" 447 | 448 | safe-buffer@^5.0.1, safe-buffer@^5.1.2, safe-buffer@~5.1.0, safe-buffer@~5.1.1: 449 | version "5.1.2" 450 | resolved "http://registry.npm.taobao.org/safe-buffer/download/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d" 451 | integrity sha1-mR7GnSluAxN0fVm9/St0XDX4go0= 452 | 453 | safer-buffer@^2.0.2, safer-buffer@^2.1.0, safer-buffer@~2.1.0: 454 | version "2.1.2" 455 | resolved "http://registry.npm.taobao.org/safer-buffer/download/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" 456 | integrity sha1-RPoWGwGHuVSd2Eu5GAL5vYOFzWo= 457 | 458 | sshpk@^1.7.0: 459 | version "1.16.1" 460 | resolved "http://registry.npm.taobao.org/sshpk/download/sshpk-1.16.1.tgz#fb661c0bef29b39db40769ee39fa70093d6f6877" 461 | integrity sha1-+2YcC+8ps520B2nuOfpwCT1vaHc= 462 | dependencies: 463 | asn1 "~0.2.3" 464 | assert-plus "^1.0.0" 465 | bcrypt-pbkdf "^1.0.0" 466 | dashdash "^1.12.0" 467 | ecc-jsbn "~0.1.1" 468 | getpass "^0.1.1" 469 | jsbn "~0.1.0" 470 | safer-buffer "^2.0.2" 471 | tweetnacl "~0.14.0" 472 | 473 | stealthy-require@^1.1.0: 474 | version "1.1.1" 475 | resolved "http://registry.npm.taobao.org/stealthy-require/download/stealthy-require-1.1.1.tgz#35b09875b4ff49f26a777e509b3090a3226bf24b" 476 | integrity sha1-NbCYdbT/SfJqd35QmzCQoyJr8ks= 477 | 478 | string_decoder@~1.1.1: 479 | version "1.1.1" 480 | resolved "http://registry.npm.taobao.org/string_decoder/download/string_decoder-1.1.1.tgz#9cf1611ba62685d7030ae9e4ba34149c3af03fc8" 481 | integrity sha1-nPFhG6YmhdcDCunkujQUnDrwP8g= 482 | dependencies: 483 | safe-buffer "~5.1.0" 484 | 485 | tough-cookie@>=2.3.3, tough-cookie@~2.4.3: 486 | version "2.4.3" 487 | resolved "http://registry.npm.taobao.org/tough-cookie/download/tough-cookie-2.4.3.tgz#53f36da3f47783b0925afa06ff9f3b165280f781" 488 | integrity sha1-U/Nto/R3g7CSWvoG/587FlKA94E= 489 | dependencies: 490 | psl "^1.1.24" 491 | punycode "^1.4.1" 492 | 493 | tunnel-agent@^0.6.0: 494 | version "0.6.0" 495 | resolved "http://registry.npm.taobao.org/tunnel-agent/download/tunnel-agent-0.6.0.tgz#27a5dea06b36b04a0a9966774b290868f0fc40fd" 496 | integrity sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0= 497 | dependencies: 498 | safe-buffer "^5.0.1" 499 | 500 | tweetnacl@^0.14.3, tweetnacl@~0.14.0: 501 | version "0.14.5" 502 | resolved "http://registry.npm.taobao.org/tweetnacl/download/tweetnacl-0.14.5.tgz?cache=0&other_urls=http%3A%2F%2Fregistry.npm.taobao.org%2Ftweetnacl%2Fdownload%2Ftweetnacl-0.14.5.tgz#5ae68177f192d4456269d108afa93ff8743f4f64" 503 | integrity sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q= 504 | 505 | uri-js@^4.2.2: 506 | version "4.2.2" 507 | resolved "http://registry.npm.taobao.org/uri-js/download/uri-js-4.2.2.tgz#94c540e1ff772956e2299507c010aea6c8838eb0" 508 | integrity sha1-lMVA4f93KVbiKZUHwBCupsiDjrA= 509 | dependencies: 510 | punycode "^2.1.0" 511 | 512 | util-deprecate@~1.0.1: 513 | version "1.0.2" 514 | resolved "http://registry.npm.taobao.org/util-deprecate/download/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" 515 | integrity sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8= 516 | 517 | uuid@^3.3.2: 518 | version "3.3.2" 519 | resolved "http://registry.npm.taobao.org/uuid/download/uuid-3.3.2.tgz#1b4af4955eb3077c501c23872fc6513811587131" 520 | integrity sha1-G0r0lV6zB3xQHCOHL8ZROBFYcTE= 521 | 522 | verror@1.10.0: 523 | version "1.10.0" 524 | resolved "http://registry.npm.taobao.org/verror/download/verror-1.10.0.tgz#3a105ca17053af55d6e270c1f8288682e18da400" 525 | integrity sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA= 526 | dependencies: 527 | assert-plus "^1.0.0" 528 | core-util-is "1.0.2" 529 | extsprintf "^1.2.0" 530 | --------------------------------------------------------------------------------