-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathapp.js
181 lines (161 loc) · 5.25 KB
/
app.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
const fs = require('fs')
const querystring = require('querystring')
const gm = require('gm')
const axios = require('axios')
const keypress = require('keypress')
const open = require('open')
const colors = require('colors')
const {baidu: {client_id, client_secret}, saveScreenshots, questionArea, optionArea, keyName} = require('./config')
axios.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded'
const WDAURL = 'http://localhost:8100'
const searchURL = 'http://www.baidu.com/s?wd='
async function getScreenshot () {
try {
const result = await axios.get(`${WDAURL}/screenshot`)
return result.data.value
} catch (e) {
console.error(e)
}
}
let baiduAccessToken = ''
async function getBaiduAccessToken () {
if (!baiduAccessToken) {
const res = await axios.get('https://aip.baidubce.com/oauth/2.0/token', {
params: {
grant_type: 'client_credentials',
client_id,
client_secret
}
})
baiduAccessToken = res.data.access_token
}
return baiduAccessToken
}
async function baiduOcr (image) {
const {data} = await axios.post(`https://aip.baidubce.com/rest/2.0/ocr/v1/general_basic?access_token=${await getBaiduAccessToken()}`,
querystring.stringify({image})
)
return data
}
async function getQuestion () {
try {
const [questionImg, optionImg] = await getImage()
const [{words_result: questionWorld}, {words_result: optionWorld}] = await Promise.all([baiduOcr(questionImg), baiduOcr(optionImg)])
// 把多行问题合并成一行,并且移除干扰字符
const question = questionWorld.reduce((str, item) => {
return str += item.words
}, '').replace(/^\d{0,2}\.?\s?(\S*?)\??$/, '$1')
// 获取答案选项
const option = optionWorld.map((item) => {
return item.words
})
return {question, option}
} catch (e) {
console.error(e)
}
}
function keypressListen () {
keypress(process.stdin)
// listen for the "keypress" event
process.stdin.on('keypress', function (ch, key) {
// 按空格时启动程序
if (key.name == keyName) {
search()
}
if (key && key.ctrl && key.name == 'c') {
process.stdin.pause()
}
})
process.stdin.setRawMode(true)
process.stdin.resume()
}
function gmPromise (buffer, width, height, x, y) {
return new Promise(function (resolve, reject) {
gm(buffer)
.crop(width, height, x, y)
.toBuffer('PNG', function (err, buffer) {
if (err) {
return reject(new Error(err))
}
return resolve(buffer.toString('base64'))
})
})
}
async function getImage () {
const image = await getScreenshot()
const imgBuf = new Buffer(image, 'base64')
// 保存截图
if (saveScreenshots) {
fs.writeFile(`./resource/${new Date().getTime()}.png`, imgBuf, function (err) {
if (err) {
console.log('保存截图失败'.red)
} else {
console.log('保存截图成功'.blue)
}
})
}
const res = await Promise.all([gmPromise.apply(this, [imgBuf, ...questionArea]), gmPromise.apply(this, [imgBuf, ...optionArea])])
return res
}
function openBrowser ({question}) {
console.log('\n=== 方法一:直接打开浏览器搜索问题 ===='.yellow)
open(`${searchURL}${question}`)
console.log('打开浏览器成功'.green)
}
async function baiduCount ({question, option}) {
const searchList = await Promise.all(option.map(item => axios.get(encodeURI(searchURL + question + item))))
console.log('\n=== 方法三:题目+选项搜索结果计数法 ===='.yellow)
console.log('问题:' + question)
const result = {}
searchList.forEach((item, index) => {
const match = item.data.match(/百度为您找到相关结果约([\d,]*)个/)
const count = Number(match && match[1].split(',').join('')) || 0
const key = option[index]
console.log(`${key}:${count}`)
result[count] = key
})
showResult(result, question)
}
async function baseCount ({question, option}) {
const {data} = await axios.get(encodeURI(searchURL + question))
console.log('\n=== 方法二:题目搜索结果包含选项词频计数法 ===='.yellow)
console.log('问题:' + question)
const result = {}
option.forEach((item, index) => {
const match = data.match(new RegExp(`${item}`, 'g'))
const count = match && match.length || 0
const key = option[index]
console.log(`${key}:${count}`)
result[count] = key
})
showResult(result, question)
}
function showResult (result, question) {
const invert = /不是|没有/.test(question)
if (invert) {
console.log('请注意,本体为否定题,选择结果最少的一项'.red)
}
const keys = Object.keys(result)
const num = invert ? Math.min.apply(null, keys) : Math.max.apply(null, keys)
if (num < 3) {
console.log('检索答案过少,请谨慎回答'.red)
return
}
console.log(`最大可能性为:${colors.red(result[num])} 共有 ${colors.green(num)} 个结果`)
}
async function start () {
try {
await axios.get(`${WDAURL}/status`)
console.log('连接 WDA 成功,按空格截图搜索'.green)
keypressListen()
} catch (e) {
console.log('连接 WDA 失败,请检查后重试'.red)
}
}
async function search () {
const result = await getQuestion()
baiduCount(result)
openBrowser(result)
baseCount(result)
}
start()