w-ipproxy 1.0.1 → 1.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (52) hide show
  1. package/.eslintrc.js +18 -17
  2. package/.github/workflows/ci-test.yml +2 -2
  3. package/README.md +64 -2
  4. package/babel.config.js +4 -2
  5. package/dist/w-ip-proxy.umd.js +7 -0
  6. package/dist/w-ip-proxy.umd.js.map +1 -0
  7. package/docs/WIpProxy.html +642 -0
  8. package/docs/WIpProxy.mjs.html +465 -0
  9. package/docs/fonts/Montserrat/Montserrat-Bold.eot +0 -0
  10. package/docs/fonts/Montserrat/Montserrat-Bold.ttf +0 -0
  11. package/docs/fonts/Montserrat/Montserrat-Bold.woff +0 -0
  12. package/docs/fonts/Montserrat/Montserrat-Bold.woff2 +0 -0
  13. package/docs/fonts/Montserrat/Montserrat-Regular.eot +0 -0
  14. package/docs/fonts/Montserrat/Montserrat-Regular.ttf +0 -0
  15. package/docs/fonts/Montserrat/Montserrat-Regular.woff +0 -0
  16. package/docs/fonts/Montserrat/Montserrat-Regular.woff2 +0 -0
  17. package/docs/fonts/Source-Sans-Pro/sourcesanspro-light-webfont.eot +0 -0
  18. package/docs/fonts/Source-Sans-Pro/sourcesanspro-light-webfont.svg +978 -0
  19. package/docs/fonts/Source-Sans-Pro/sourcesanspro-light-webfont.ttf +0 -0
  20. package/docs/fonts/Source-Sans-Pro/sourcesanspro-light-webfont.woff +0 -0
  21. package/docs/fonts/Source-Sans-Pro/sourcesanspro-light-webfont.woff2 +0 -0
  22. package/docs/fonts/Source-Sans-Pro/sourcesanspro-regular-webfont.eot +0 -0
  23. package/docs/fonts/Source-Sans-Pro/sourcesanspro-regular-webfont.svg +1049 -0
  24. package/docs/fonts/Source-Sans-Pro/sourcesanspro-regular-webfont.ttf +0 -0
  25. package/docs/fonts/Source-Sans-Pro/sourcesanspro-regular-webfont.woff +0 -0
  26. package/docs/fonts/Source-Sans-Pro/sourcesanspro-regular-webfont.woff2 +0 -0
  27. package/docs/index.html +84 -0
  28. package/docs/scripts/collapse.js +39 -0
  29. package/docs/scripts/commonNav.js +28 -0
  30. package/docs/scripts/linenumber.js +25 -0
  31. package/docs/scripts/nav.js +12 -0
  32. package/docs/scripts/polyfill.js +4 -0
  33. package/docs/scripts/prettify/Apache-License-2.0.txt +202 -0
  34. package/docs/scripts/prettify/lang-css.js +2 -0
  35. package/docs/scripts/prettify/prettify.js +28 -0
  36. package/docs/scripts/search.js +99 -0
  37. package/docs/styles/jsdoc.css +776 -0
  38. package/docs/styles/prettify.css +80 -0
  39. package/g-getByTimer.mjs +24 -0
  40. package/g-getOnce.mjs +11 -0
  41. package/g-srv.mjs +28 -0
  42. package/package.json +11 -9
  43. package/script.txt +17 -0
  44. package/src/WIpProxy.mjs +384 -14
  45. package/src/provideServer.mjs +65 -0
  46. package/toolg/cleanFolder.mjs +4 -0
  47. package/toolg/gDistRollup.mjs +29 -0
  48. package/toolg/modifyReadme.mjs +4 -0
  49. package/g.mjs +0 -12
  50. package/src/getHtml.mjs +0 -84
  51. package/src/getProxyListOrg.mjs +0 -66
  52. package/src/parseHtml.mjs +0 -19
@@ -0,0 +1,465 @@
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+
5
+ <meta charset="utf-8">
6
+ <title>WIpProxy.mjs - Documentation</title>
7
+
8
+
9
+ <script src="scripts/prettify/prettify.js"></script>
10
+ <script src="scripts/prettify/lang-css.js"></script>
11
+ <!--[if lt IE 9]>
12
+ <script src="//html5shiv.googlecode.com/svn/trunk/html5.js"></script>
13
+ <![endif]-->
14
+ <link type="text/css" rel="stylesheet" href="styles/prettify.css">
15
+ <link type="text/css" rel="stylesheet" href="styles/jsdoc.css">
16
+ <script src="scripts/nav.js" defer></script>
17
+
18
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
19
+ </head>
20
+ <body>
21
+
22
+ <input type="checkbox" id="nav-trigger" class="nav-trigger" />
23
+ <label for="nav-trigger" class="navicon-button x">
24
+ <div class="navicon"></div>
25
+ </label>
26
+
27
+ <label for="nav-trigger" class="overlay"></label>
28
+
29
+ <nav >
30
+
31
+
32
+ <h2><a href="index.html">Home</a></h2><h3>Classes</h3><ul><li><a href="WIpProxy.html">WIpProxy</a></li></ul>
33
+
34
+ </nav>
35
+
36
+ <div id="main">
37
+
38
+ <h1 class="page-title">WIpProxy.mjs</h1>
39
+
40
+
41
+
42
+
43
+
44
+
45
+
46
+ <section>
47
+ <article>
48
+ <pre class="prettyprint source linenums"><code>import axios from 'axios'
49
+ import https from 'https'
50
+ import get from 'lodash-es/get.js'
51
+ import size from 'lodash-es/size.js'
52
+ import each from 'lodash-es/each.js'
53
+ import map from 'lodash-es/map.js'
54
+ import trim from 'lodash-es/trim.js'
55
+ import values from 'lodash-es/values.js'
56
+ import evem from 'wsemi/src/evem.mjs'
57
+ import sep from 'wsemi/src/sep.mjs'
58
+ import isestr from 'wsemi/src/isestr.mjs'
59
+ import ispint from 'wsemi/src/ispint.mjs'
60
+ import isbol from 'wsemi/src/isbol.mjs'
61
+ import isearr from 'wsemi/src/isearr.mjs'
62
+ import iseobj from 'wsemi/src/iseobj.mjs'
63
+ import cint from 'wsemi/src/cint.mjs'
64
+ import waitFun from 'wsemi/src/waitFun.mjs'
65
+ import provideServer from './provideServer.mjs'
66
+
67
+
68
+ /**
69
+ * 抓取代理伺服器
70
+ *
71
+ * @class
72
+ * @param {Object} [opt={}] 輸入設定物件,預設{}
73
+ * @param {String} [opt.src='https://api.proxyscrape.com/v2/?request=displayproxies&amp;protocol=http&amp;timeout=5000&amp;anonymity=all'] 輸入取得代理伺服器API字串,預設'https://api.proxyscrape.com/v2/?request=displayproxies&amp;protocol=http&amp;timeout=5000&amp;anonymity=all'
74
+ * @param {String} [opt.tar='https://httpbin.org/ip'] 輸入檢測目標網址字串,預設'https://httpbin.org/ip'
75
+ * @param {Integer} [opt.timeGetProxies=30*1000] 輸入輪循抓取代理伺服器時間間隔整數,單位ms,預設30*1000
76
+ * @param {Integer} [opt.timeTestProxies=60*1000] 輸入輪循測試代理伺服器時間間隔整數,單位ms,預設60*1000
77
+ * @param {Boolean} [opt.withServer=false] 輸入是否創建供數據供給伺服器布林值,預設false
78
+ * @param {Integer} [opt.serverPort=8080] 輸入創建伺服器所用port整數,預設8080
79
+ * @param {String} [opt.serverApiName='getProxies'] 輸入供給數據API名稱字串,預設'getProxies'
80
+ * @param {Array} [opt.serverCorsOrigins=['*']] 輸入允許跨域網域陣列,若給予['*']代表允許全部,預設['*']
81
+ * @returns {Object} 回傳事件物件,提供函數getProxies,可監聽事件getRawProxies、add、delete、change
82
+ * @example
83
+ *
84
+ * import _ from 'lodash-es'
85
+ * import wip from './src/WIpProxy.mjs'
86
+ *
87
+ * let wo = wip({
88
+ * // tar: `https://www.google.com`,
89
+ * withServer: true,
90
+ * serverPort: 9000,
91
+ * serverCorsOrigins: ['*'],
92
+ * })
93
+ * wo.on('getRawProxies', (prxsRaw) => {
94
+ * console.log(`已抓取公開代理共 ${_.size(prxsRaw)} 個...`)
95
+ * })
96
+ * wo.on('add', (p, proxies) => {
97
+ * // console.log('新加入代理', { host: p.host, port: p.port }, _.map(proxies, 'proxy'))
98
+ * })
99
+ * wo.on('delete', (p, proxies) => {
100
+ * // console.log('刪除代理', { host: p.host, port: p.port }, _.map(proxies, 'proxy'))
101
+ * })
102
+ * wo.on('change', (proxies) => {
103
+ * // console.log(`有效代理`, _.map(proxies, 'proxy'))
104
+ * console.log(`已檢測有效代理共 ${_.size(proxies)} 個...`)
105
+ * })
106
+ *
107
+ * //browser view: http://localhost:9000/getProxies
108
+ *
109
+ */
110
+ function WIpProxy(opt = {}) {
111
+
112
+ //src
113
+ let src = get(opt, 'src', '')
114
+ if (!isestr(src)) {
115
+ src = 'https://api.proxyscrape.com/v2/?request=displayproxies' +
116
+ `&amp;protocol=http` +
117
+ // `&amp;protocol=https` +
118
+ `&amp;timeout=5000` +
119
+ // `&amp;country=${join(['tw', 'cn', 'hk', 'jp', 'kr', 'sg', 'my', 'in', 'id', 'th', 'vn'])}` +
120
+ // `&amp;ssl=yes` +
121
+ `&amp;anonymity=all`
122
+ }
123
+
124
+ //tar
125
+ let tar = get(opt, 'tar', '')
126
+ if (!isestr(tar)) {
127
+ tar = 'https://httpbin.org/ip' //'https://www.google.com'
128
+ }
129
+
130
+ //timeGetProxies
131
+ let timeGetProxies = get(opt, 'timeGetProxies')
132
+ if (!ispint(timeGetProxies)) {
133
+ timeGetProxies = 30 * 1000 //30s
134
+ }
135
+ timeGetProxies = cint(timeGetProxies)
136
+
137
+ //timeTestProxies
138
+ let timeTestProxies = get(opt, 'timeTestProxies')
139
+ if (!ispint(timeTestProxies)) {
140
+ timeTestProxies = 60 * 1000 //1min
141
+ }
142
+ timeTestProxies = cint(timeTestProxies)
143
+
144
+ //withServer
145
+ let withServer = get(opt, 'withServer')
146
+ if (!isbol(withServer)) {
147
+ withServer = false
148
+ }
149
+
150
+ //serverPort
151
+ let serverPort = get(opt, 'serverPort')
152
+ if (!ispint(serverPort)) {
153
+ serverPort = 8080
154
+ }
155
+ serverPort = cint(serverPort)
156
+
157
+ //serverApiName
158
+ let serverApiName = get(opt, 'serverApiName')
159
+ if (!isestr(serverApiName)) {
160
+ serverApiName = 'getProxies'
161
+ }
162
+
163
+ //serverCorsOrigins
164
+ let serverCorsOrigins = get(opt, 'serverCorsOrigins', [])
165
+ if (!isearr(serverCorsOrigins)) {
166
+ serverCorsOrigins = ['*']
167
+ }
168
+
169
+ //prxsRaw, kpPrx
170
+ let prxsRaw = []
171
+ let kpPrx = {}
172
+
173
+ async function _getProxiesCore(src) {
174
+ let ps = []
175
+
176
+ try {
177
+
178
+ //res
179
+ let res = await axios.get(src)
180
+
181
+ //c
182
+ let c = res.data
183
+ // console.log('c', c)
184
+
185
+ //sep
186
+ let ss = sep(c, '\n')
187
+ // console.log('ss', ss)
188
+
189
+ //ps
190
+ ps = map(ss, (v) => {
191
+ let [host, port] = v.split(':')
192
+ port = cint(port)
193
+ return {
194
+ proxy: v,
195
+ host,
196
+ port,
197
+ }
198
+ })
199
+ // console.log('ps', ps)
200
+
201
+ }
202
+ catch (err) {
203
+ console.log('_getProxiesCore catch', err.message)
204
+ }
205
+ // console.log('ps', ps)
206
+
207
+ return ps
208
+ }
209
+
210
+ let b_getProxies = false
211
+ async function _getProxies() {
212
+ // console.log('call getProxies...')
213
+
214
+ let core = async() => {
215
+
216
+ //get
217
+ prxsRaw = await _getProxiesCore(src)
218
+
219
+ //emit
220
+ ev.emit('getRawProxies', prxsRaw)
221
+
222
+ }
223
+
224
+ //core
225
+ if (b_getProxies) {
226
+ return
227
+ }
228
+ b_getProxies = true
229
+ await core()
230
+ .catch(() => {}) //吃掉錯誤
231
+ .finally(() => {
232
+ b_getProxies = false
233
+ })
234
+
235
+ }
236
+
237
+ async function _testProxyCore(host, port, url) {
238
+
239
+ //ret
240
+ let ret = (state, msg) => {
241
+ return {
242
+ state,
243
+ msg,
244
+ p: {
245
+ proxy: `${host}:${port}`,
246
+ host,
247
+ port,
248
+ },
249
+ }
250
+ }
251
+
252
+ //r
253
+ let r = {}
254
+ try {
255
+
256
+ //agent
257
+ let agent = new https.Agent({ rejectUnauthorized: false }) //避免證書錯誤中止
258
+
259
+ //get
260
+ let res = await axios.get(url, {
261
+ proxy: {
262
+ host,
263
+ port,
264
+ protocol: 'http',
265
+ },
266
+ httpsAgent: agent,
267
+ timeout: 5000,
268
+ headers: {
269
+ 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 Chrome/122.0.0.0 Safari/537.36',
270
+ 'Accept': 'application/json',
271
+ },
272
+ })
273
+
274
+ if (res.status === 200) {
275
+ r = ret('success', res.data)
276
+ }
277
+ else {
278
+ r = ret('error', `status[${res.status}] error`)
279
+ }
280
+
281
+ }
282
+ catch (err) {
283
+ r = ret('error', trim(err.message))
284
+ // if (r.msg.indexOf(`ssl3_get_record`) >= 0) {
285
+ // r.msg = `ssl3_get_record error`
286
+ // }
287
+ }
288
+ // console.log(r)
289
+
290
+ return r
291
+ }
292
+
293
+ async function _testProxiesCore(prxs) {
294
+
295
+ //pms
296
+ let pms = map(prxs, (p) => {
297
+ let pm = _testProxyCore(p.host, p.port, tar)
298
+ return pm
299
+ })
300
+
301
+ //rrs, allSettled
302
+ let rrs = await Promise.allSettled(pms)
303
+ // console.log('rrs', rrs)
304
+
305
+ //psValid, psInvalid
306
+ let psValid = []
307
+ let psInvalid = []
308
+ each(rrs, (v) => {
309
+
310
+ //be
311
+ let p = get(v, 'value.p', null)
312
+ let be = iseobj(p) &amp;&amp; isestr(get(p, 'proxy'))
313
+
314
+ //check
315
+ if (!be) {
316
+ return true //跳出換下一個
317
+ }
318
+
319
+ //b
320
+ let status = get(v, 'status', '')
321
+ let b1 = status === 'fulfilled'
322
+ let state = get(v, 'value.state', '')
323
+ let b2 = state === 'success'
324
+ let b = b1 &amp;&amp; b2
325
+
326
+ //push
327
+ if (b) {
328
+ psValid.push(p)
329
+ }
330
+ else {
331
+ psInvalid.push(p)
332
+ }
333
+
334
+ })
335
+
336
+ return {
337
+ psValid,
338
+ psInvalid,
339
+ }
340
+ }
341
+
342
+ let b_testProxies = false
343
+ async function _testProxies() {
344
+ // console.log('call testProxies...')
345
+
346
+ let core = async() => {
347
+
348
+ //get
349
+ let r = await _testProxiesCore(prxsRaw)
350
+
351
+ //emit add
352
+ each(r.psValid, (p) => {
353
+ kpPrx[p.proxy] = p
354
+ ev.emit('add', p, values(kpPrx))
355
+ })
356
+
357
+ //emit delete
358
+ each(r.psInvalid, (p) => {
359
+ delete kpPrx[p.proxy]
360
+ ev.emit('delete', p, values(kpPrx))
361
+ })
362
+
363
+ //emit change
364
+ ev.emit('change', values(kpPrx))
365
+
366
+ }
367
+
368
+ //core
369
+ if (b_testProxies) {
370
+ return
371
+ }
372
+ b_testProxies = true
373
+ await core()
374
+ .catch(() => {}) //吃掉錯誤
375
+ .finally(() => {
376
+ b_testProxies = false
377
+ })
378
+
379
+ }
380
+
381
+ function init() {
382
+
383
+ //取得代理清單
384
+ if (true) {
385
+ _getProxies()
386
+ setInterval(() => {
387
+ _getProxies()
388
+ }, timeGetProxies)
389
+ }
390
+
391
+ //過濾出有效代理清單, 延遲3s觸發, 給時間抓取
392
+ if (true) {
393
+ setTimeout(() => {
394
+ _testProxies()
395
+ setInterval(() => {
396
+ _testProxies()
397
+ }, timeTestProxies)
398
+ }, 3000)
399
+ }
400
+
401
+ }
402
+
403
+ async function getProxies() {
404
+ let vs
405
+ await waitFun(() => {
406
+ vs = values(kpPrx)
407
+ return size(vs) > 0
408
+ })
409
+ return vs
410
+ }
411
+
412
+ //ev
413
+ let ev = evem()
414
+
415
+ //withServer
416
+ if (withServer) {
417
+ provideServer(getProxies, {
418
+ port: serverPort,
419
+ apiName: serverApiName,
420
+ corsOrigins: serverCorsOrigins,
421
+ })
422
+ }
423
+
424
+ async function getProxiesOnce() {
425
+ await _getProxies()
426
+ await _testProxies()
427
+ let ps = await getProxies()
428
+ return ps
429
+ }
430
+
431
+ //save
432
+ ev.init = init
433
+ ev.getProxies = getProxies
434
+ ev.getProxiesOnce = getProxiesOnce
435
+
436
+ return ev
437
+ }
438
+
439
+
440
+ export default WIpProxy
441
+ </code></pre>
442
+ </article>
443
+ </section>
444
+
445
+
446
+
447
+
448
+
449
+
450
+ </div>
451
+
452
+ <br class="clear">
453
+
454
+ <footer>
455
+ Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 4.0.2</a> on Tue Mar 17 2026 21:42:27 GMT+0800 (台北標準時間) using the <a href="https://github.com/clenemt/docdash">docdash</a> theme.
456
+ </footer>
457
+
458
+ <script>prettyPrint();</script>
459
+ <script src="scripts/polyfill.js"></script>
460
+ <script src="scripts/linenumber.js"></script>
461
+
462
+
463
+
464
+ </body>
465
+ </html>