Недавний проект нуждается в некоторой информации, потому чтопроектиспользуется
Node.js
писать, так что естественно использоватьNode.js
Давайте напишем рептилий
адрес проекта:GitHub.com/Daily Tan Weijie…, залез в проектReadhub,Китай с открытым исходным кодом,Заголовки разработчиков,36KrИнформационное содержание этих веб-сайтов пока не обрабатывается на нескольких страницах, потому что краулер будет запускаться один раз в день, и теперь он может удовлетворять потребности каждый раз, когда он получает последнюю версию, и она будет улучшена позже.
Процесс сканирования можно охарактеризовать как загрузку HTML-кода целевого веб-сайта на локальный сервер и последующее извлечение данных.
1. Страница загрузки
Node.js
Существует множество библиотек http-запросов, здесь используйтеrequest
, основной код выглядит следующим образом:
requestDownloadHTML () {
const options = {
url: this.url,
headers: {
'User-Agent': this.randomUserAgent()
}
}
return new Promise((resolve, reject) => {
request(options, (err, response, body) => {
if (!err && response.statusCode === 200) {
return resolve(body)
} else {
return reject(err)
}
})
})
}
использоватьPromise
упаковать для последующего использованияasync/await
. Поскольку многие веб-сайты отображаются на стороне клиента, загруженная страница не обязательно содержит желаемый HTML-контент, мы можем использоватьGoogleизpuppeteer
для загрузки клиентских страниц веб-сайта. По известным причинам вnpm i
когдаpuppeteer
Установка может завершиться неудачей из-за необходимости загрузки ядра Chrome, просто попробуйте еще несколько раз :)
puppeteerDownloadHTML () {
return new Promise(async (resolve, reject) => {
try {
const browser = await puppeteer.launch({ headless: true })
const page = await browser.newPage()
await page.goto(this.url)
const bodyHandle = await page.$('body')
const bodyHTML = await page.evaluate(body => body.innerHTML, bodyHandle)
return resolve(bodyHTML)
} catch (err) {
console.log(err)
return reject(err)
}
})
}
Конечно, лучше всего использовать метод запроса интерфейса непосредственно для отрендеренной клиентом страницы, чтобы не требовался последующий парсинг HTML.После простой инкапсуляции можно использовать так: # Забавно :)
await new Downloader('http://36kr.com/newsflashes', DOWNLOADER.puppeteer).downloadHTML()
Во-вторых, извлечение содержимого HTML.
Извлечение содержимого HTML, конечно, использует артефактcheerio
в настоящее время,cheerio
подвергается иjQuery
Тот же интерфейс очень прост в использовании. браузер открыть страницуF12Просмотрите извлеченный узел элемента страницы, а затем извлеките содержимое по мере необходимости.
readHubExtract () {
let nodeList = this.$('#itemList').find('.enableVisited')
nodeList.each((i, e) => {
let a = this.$(e).find('a')
this.extractData.push(
this.extractDataFactory(
a.attr('href'),
a.text(),
'',
SOURCECODE.Readhub
)
)
})
return this.extractData
}
Три задания на время
cron
бегать каждый день
function job () {
let cronJob = new cron.CronJob({
cronTime: cronConfig.cronTime,
onTick: () => {
spider()
},
start: false
})
cronJob.start()
}
В-четвертых, сохранение данных
Теоретически постоянство данных не должно относиться к сфере заботы краулеров.mongoose
, создать модель
import mongoose from 'mongoose'
const Schema = mongoose.Schema
const NewsSchema = new Schema(
{
title: { type: 'String', required: true },
url: { type: 'String', required: true },
summary: String,
recommend: { type: Boolean, default: false },
source: { type: Number, required: true, default: 0 },
status: { type: Number, required: true, default: 0 },
createdTime: { type: Date, default: Date.now }
},
{
collection: 'news'
}
)
export default mongoose.model('news', NewsSchema)
Основная операция
import { OBJ_STATUS } from '../../Constants'
class BaseService {
constructor (ObjModel) {
this.ObjModel = ObjModel
}
saveObject (objData) {
return new Promise((resolve, reject) => {
this.ObjModel(objData).save((err, result) => {
if (err) {
return reject(err)
}
return resolve(result)
})
})
}
}
export default BaseService
Информация
import BaseService from './BaseService'
import News from '../models/News'
class NewsService extends BaseService {}
export default new NewsService(News)
Сохраняйте данные с удовольствием
await newsService.batchSave(newsListTem)
Для получения дополнительных материалов перейдите на Github и клонируйте проект, чтобы увидеть его.