This commit is contained in:
spiduler
2020-10-24 22:27:14 +09:00
parent 78c7f90947
commit 967eb5c9cc
2 changed files with 136 additions and 51 deletions

View File

@@ -22,9 +22,7 @@ class SeleniumBrowser {
}, },
destroy: (driver) => { destroy: (driver) => {
logger.info('Quitting driver') logger.info('Quitting driver')
return driver.quit() return driver.quit().then(() => {
},
validate: (driver) => {
logger.debug({ logger.debug({
spare: this.pool.spareResourceCapacity, spare: this.pool.spareResourceCapacity,
size: this.pool.size, size: this.pool.size,
@@ -32,9 +30,9 @@ class SeleniumBrowser {
borrowed: this.pool.borrowed, borrowed: this.pool.borrowed,
pending: this.pool.pending pending: this.pool.pending
}, 'Pool info') }, 'Pool info')
if(this.pool.borrowed > 8) { })
this.pool.clear() },
} validate: (driver) => {
return driver.getSession().then(s => { return driver.getSession().then(s => {
logger.info('Driver session validation checked (id: %s)', s.getId()) logger.info('Driver session validation checked (id: %s)', s.getId())
return true return true
@@ -55,19 +53,6 @@ class SeleniumBrowser {
this.pool.on('factoryDestroyError', function (err) { this.pool.on('factoryDestroyError', function (err) {
logger.error({ message: err.message }, 'pool error') logger.error({ message: err.message }, 'pool error')
}) })
// this.pool.use(driver => {
// return new Promise((resolve, reject) => {
// if (this.pool.available == 0) this.config.browserFullCount++
// if (this.config.browserFullCount > 100) {
// this.pool.clear()
// this.config.browserFullCount = 0
// reject(new Error('browser full count more than 100 times'))
// } else {
// resolve(driver)
// }
// })
// })
} }
getDriver() { getDriver() {
@@ -92,7 +77,7 @@ class SeleniumBrowser {
.then(body => body.getAttribute('innerHTML')) .then(body => body.getAttribute('innerHTML'))
let htmlPromise = this.isCaptchaPage(html) ? this.resolveCaptcha(driver) : this.getHtml(driver, html, params) let htmlPromise = this.isCaptchaPage(html) ? this.resolveCaptcha(driver) : this.getHtml(driver, html, params)
html = await htmlPromise html = await htmlPromise
this.pool.release(driver) this.pool.destroy(driver)
return html return html
}) })
} else { } else {
@@ -163,10 +148,8 @@ class SeleniumBrowser {
}) })
} }
async close() { close() {
this.pool.drain().then(function () { return this.pool.drain()
this.pool.clear();
})
} }
} }

144
test.js
View File

@@ -12,38 +12,69 @@ class Test {
constructor() { constructor() {
this.config = { this.config = {
stopping: false,
browserFullCount: 0,
useHub: true, browser: 'chrome', useHub: true, browser: 'chrome',
browserArgs: ['--no-sandbox', '--headless', '--disable-dev-shm-usage', '--proxy-server=spiduler-tor:8118'] browserArgs: ['--no-sandbox', '--headless', '--disable-dev-shm-usage', '--proxy-server=spiduler-tor:8118']
} }
this.capabilities = Capabilities.chrome() this.capabilities = Capabilities.chrome()
this.sleep = m => new Promise(r => setTimeout(r, m))
this.getDriver().then(driver => { this.pool = pool.createPool({
driver.get('https://www.naver.com/') create: () => {
.then(() => driver.findElement(By.css('body'))) logger.info('Create new driver instance')
.then(body => body.getAttribute('innerHTML')) return this.getDriver();
driver.getSession().then(s => { },
let id = s.getId() destroy: (driver) => {
console.log(id) logger.info('Quitting driver')
// driver.close() return driver.quit()
// driver.quit() },
driver.get('https://www.naver.com/') validate: (driver) => {
.then(() => driver.findElement(By.css('body'))) logger.debug({
.then(body => body.getAttribute('innerHTML')) spare: this.pool.spareResourceCapacity,
.finally(() => { size: this.pool.size,
// driver.close().then(a => console.log(a)) available: this.pool.available,
driver.quit().then(q => console.log(q)) borrowed: this.pool.borrowed,
}) pending: this.pool.pending
// driver.quit() }, 'Pool info')
return '' if(this.pool.borrowed > 8) {
this.pool.clear()
}
return driver.getSession().then(s => {
logger.info('Driver session validation checked (id: %s)', s.getId())
return true
}).catch(err => { }).catch(err => {
console.log(err.message) this.pool.destroy(driver)
logger.debug({ message: err.message }, 'Driver session expired and destroy it')
return false
}) })
}
}, {
max: 2, min: 1, testOnBorrow: true, acquireTimeoutMillis: 1000
});
this.pool.on('factoryCreateError', function (err) {
logger.error({ message: err.message }, 'pool error')
}) })
this.pool.on('factoryDestroyError', function (err) {
logger.error({ message: err.message }, 'pool error')
})
// this.pool.use(driver => {
// return new Promise((resolve, reject) => {
// if (this.pool.available == 0) this.config.browserFullCount++
// if (this.config.browserFullCount > 100) {
// this.pool.clear()
// this.config.browserFullCount = 0
// reject(new Error('browser full count more than 100 times'))
// } else {
// resolve(driver)
// }
// })
// })
} }
async getDriver() { getDriver() {
let opts = new Options; let opts = new Options;
opts.addArguments(this.config.browserArgs) opts.addArguments(this.config.browserArgs)
return new Builder() return new Builder()
@@ -53,7 +84,78 @@ class Test {
.setChromeOptions(opts) .setChromeOptions(opts)
.build(); .build();
} }
async request(params) {
let uri = params.uri
logger.info('URL %s', uri)
if (uri.indexOf('://') > 3) {
return this.pool.acquire()
.then(async driver => {
let html = await driver.get(uri)
.then(() => driver.findElement(By.css('body')))
.then(body => body.getAttribute('innerHTML'))
let htmlPromise = this.isCaptchaPage(html) ? this.resolveCaptcha(driver) : this.getHtml(driver, html, params)
html = await htmlPromise
this.pool.release(driver)
return html
})
} else {
throw new Error('Invalid URI - ' + uri)
}
}
isCaptchaPage(html) {
return html.indexOf('grecaptcha') > -1 || html.indexOf('www.google.com/recaptcha/api2/anchor') > -1
}
getCaptchaRequestUri(id) {
return 'https://2captcha.com/res.php?key=62fc5ef52fd4befe266d224796a7ea6f&json=1&action=get&id=' + id
}
getHtml(driver, html, params) {
if (params.waitElements) {
return driver.get(params.uri)
.then(() => Promise.all(params.waitElements.map(s => driver.wait(until.elementLocated(By.css(s))))))
.then(() => driver.findElement(By.css('body')))
.then(body => body.getAttribute('innerHTML'))
.then(html => {
return html
})
} else {
return html
}
}
close() {
clearTimeout(intervals)
return this.pool.drain().then(function () {
this.pool.clear();
})
}
} }
const test = new Test const test = new Test
const intervals = setInterval(() => {
test.request({uri : 'https://www.naver.com'}).then(html => console.log(html.length))
}, 2000)
exitHandler = (options, exitCode) => {
if (options.cleanup) logger.info('cleanup')
if (exitCode || exitCode === 0) logger.info('exit code :', exitCode)
test.close().then(() => process.exit());
}
/**
* Process shutdown events handling
*/
//do something when app is closing
process.on('exit', exitHandler.bind(null, { cleanup: true }));
//catches ctrl+c event
process.on('SIGINT', exitHandler.bind(null, { exit: true }));
process.on('SIGTERM', exitHandler.bind(null, { cleanup: true }));