yolo-scraper
Version:
A simple way to structure your web scraper.
77 lines (68 loc) • 2.59 kB
JavaScript
var cheerio = require('cheerio')
var axios = require('axios')
var Ajv = require('ajv')
var ValidationError = require('./ValidationError')
var utils = require('./utils')
module.exports = function (options) {
if (!utils.isFunction(options.request)) {
throw new Error('Expect options.request to be a function')
}
if (!utils.isFunction(options.extract)) {
throw new Error('Expect options.extract to be a function')
}
if (!utils.isObject(options.schema)) {
throw new Error('Expect options.schema to be an object')
}
if (Object.prototype.hasOwnProperty.call(options, 'validateList') && !utils.isBoolean(options.validateList)) {
throw new Error('Expect options.validateList to be a boolean')
}
if (Object.prototype.hasOwnProperty.call(options, 'paramsSchema') && !utils.isObject(options.paramsSchema)) {
throw new Error('Expect options.paramsSchema to be an object')
}
var cheerioOptions = {}
if (utils.isObject(options.cheerioOptions)) {
cheerioOptions = options.cheerioOptions
}
var ajvOptions = { validateSchema: true, allErrors: true, schemaId: 'auto' }
if (utils.isObject(options.ajvOptions)) {
ajvOptions = options.ajvOptions
}
// compile the JSON schema
var ajv = new Ajv(ajvOptions)
var validateParamsSchema
// Add support for JSON schema draft 4.
if (options.schema.$schema && options.schema.$schema.indexOf('draft-04') !== -1) {
ajv.addMetaSchema(require('ajv/lib/refs/json-schema-draft-04.json'))
}
var validateSchema = ajv.compile(options.schema)
if (options.paramsSchema) {
validateParamsSchema = ajv.compile(options.paramsSchema)
}
return function (params) {
return new Promise(function (resolve, reject) {
if (validateParamsSchema && !validateParamsSchema(params)) {
var paramsError = ajv.errorsText(validateParamsSchema.errors, { dataVar: 'params' })
reject(new Error(paramsError))
}
var requestOption = options.request(params)
axios(requestOption)
.then(function (response) {
var $ = null
try {
$ = cheerio.load(response.data, cheerioOptions)
} catch (error) {
console.error(error)
}
var extractedData = options.extract(response, response.data, $)
if (validateSchema(extractedData)) {
resolve(extractedData)
} else {
reject(new ValidationError(ajv.errorsText(validateSchema.errors), validateSchema.errors))
}
})
.catch(function (error) {
reject(error)
})
})
}
}