cheerio: 則可以對請求結果進行解析,解析方式和jquery的解析方式幾乎徹底相同 cheerio中文文檔 開發參考node - cheerio模塊css
superagent: 可以實現主動發起get/post/delete等請求html
superagent-charset: 解決爬蟲數據中文亂碼問題,早期版本單獨使用,現配合superagent使用node
koa2: 搭建服務器環境等等mysql
koa-router: koa路由,用於根據路由訪問對應代碼塊,邏輯編寫等做用(把他理解爲像平常API接口就好)jquery
knex: 操做數據庫,支持多種數據庫,這裏使用mysql,須要mysql中間件 開發參考knex筆記git
npm init
一路回車,初始化項目環境,出現package.json文件,而後執行如下命令安裝項目依賴npm i --save cheerio superagent superagent-charset koa-router koa knex mysql
const Koa = require('koa'), Router = require('koa-router'), cheerio = require('cheerio'), charset = require('superagent-charset'), superagent = charset(require('superagent')), app = new Koa(), router = new Router();
router.get('/', function(ctx, next) { ctx.body = "搭建好了,開始吧"; }); app .use(router.routes()) .use(router.allowedMethods()); app.listen(3010, () => { console.log('[服務已開啓,訪問地址爲:] http://127.0.0.1:3010/'); });
node app.js
, 打開瀏覽器http://127.0.0.1:3010/ 就能夠訪問了 如看到 搭建好了,開始吧
就意味着搭建環境success博雅特產網github
const Koa = require('koa'), Router = require('koa-router'), cheerio = require('cheerio'), charset = require('superagent-charset'), superagent = charset(require('superagent')), app = new Koa(), router = new Router(); let arr; router.get('/', (ctx, next) => { url = 'http://shop.bytravel.cn/produce/index226.html'; //target地址 superagent.get(url) .charset('gbk') // 當前頁面編碼格式 .buffer(true) .end((err, data) => { //頁面獲取到的數據 if (err) { // return next(err); console.log('頁面不存在', err) } let html = data.text, $ = cheerio.load(html, { decodeEntities: false, ignoreWhitespace: false, xmlMode: false, lowerCaseTags: false }), //用cheerio解析頁面數據 obj = {}; arr = []; // cheerio的使用相似jquery的操做 $("table tbody").each((index, element) => { let $element = $(element); $element.find('#tctitle').next().find('a').addClass('link').attr('class', 'link').text('') arr.push({ 'title': $element.find('a.blue14b').text(), 'image': $element.find('#bright img').attr('src'), 'summary': $element.find('#tctitle').next().text(), 'is_cgiia': $element.find('#tctitle font').attr('color') === 'green' ? 1 : 0 }) }) }) ctx.body = arr // console.log(arr) }) app .use(router.routes()) .use(router.allowedMethods()); app.listen(3010, () => { console.log('[服務已開啓,訪問地址爲:] http://127.0.0.1:3010/'); });
命令行重啓服務
node app.js
, 頁面出現一個數組,有大量數據,success;sql
superagent.get(url) .charset('gbk') // 當前頁面編碼格式 .buffer(true) .end(async (err, data) => { //頁面獲取到的數據 ······ })
$("table tbody").each((index, element) => { let $element = $(element); $element.find('#tctitle').next().find('a').addClass('link').attr('class', 'link').text(''); //去掉簡介中連接接【詳情】 arr.push({ 'title': $element.find('a.blue14b').text(), 'image': $element.find('#bright img').attr('src'), 'summary': $element.find('#tctitle').next().text(), 'is_cgiia': $element.find('#tctitle font').attr('color') === 'green' ? 1 : 0 }) })
sudo npm install knex mysql --save
當前自定義數據庫
native_symbol
,數據表products
數據庫
CREATE DATABASE native_symbol; CREATE TABLE `products` ( `id` int(11) NOT NULL AUTO_INCREMENT COMMENT '編號', `title` varchar(100) NOT NULL COMMENT '名稱', `image` varchar(100) NOT NULL COMMENT '圖片', `summary` varchar(1000) NOT NULL COMMENT '簡介', `tags` varchar(100) DEFAULT NULL COMMENT '標籤', `is_cgiia` tinyint(1) DEFAULT NULL COMMENT '是不是地標特產', PRIMARY KEY (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=20 DEFAULT CHARSET=utf8;
var knex = require('knex')({ client: 'mysql', //指明數據庫類型,還能夠是pg,sqlite3等等 connection: { //指明鏈接參數 host: '127.0.0.1', user: 'root', password: 'root', database: 'native_symbol' }, debug: true, //指明是否開啓debug模式,默認爲true表示開啓 pool: { //指明數據庫鏈接池的大小,默認爲{min: 2, max: 10} min: 0, max: 7, }, acquireConnectionTimeout: 10000, //指明鏈接計時器大小,默認爲60000ms migrations: { tableName: 'migrations' //數據庫遷移,可選 } });
把數據庫類型和鏈接相關的參數配置好以後,才能夠正確的鏈接到數據庫,connection的配置信息一般寫到config文件中。npm
目前node開發服務端最優解決異步回調是
koa2 + es7(async/await)
// 寫入庫 knex('users') .returning('id') .insert({ name: 'charblus', age: 18, sex: 1 }) .then(res => { console.log('success', res) }) }
$("table tbody").each((index, element) => { let $element = $(element); $element.find('#tctitle').next().find('a').addClass('link').attr('class', 'link').text('') arr.push({ 'title': $element.find('a.blue14b').text(), 'image': $element.find('#bright img').attr('src'), 'summary': $element.find('#tctitle').next().text(), 'is_cgiia': $element.find('#tctitle font').attr('color') === 'green' ? 1 : 0 }) }) for (let i of arr) { const findRes = await knex('products').select().where('title', i.title) if (findRes.length) { console.log('數據已存在') } else { // 寫入庫 await knex('products') .returning('id') .insert(i) .then(res => { console.log('success', res) }) } }
這裏讀寫數據庫是異步操做 使用
async/await
, 如上knex讀寫數據庫時都用了await
,須要在當前函數前加async
const Koa = require('koa'), Router = require('koa-router'), cheerio = require('cheerio'), charset = require('superagent-charset'), superagent = charset(require('superagent')), app = new Koa(), router = new Router(); let arr; var knex = require('knex')({ client: 'mysql', //指明數據庫類型,還能夠是pg,sqlite3等等 connection: { //指明鏈接參數 host: '127.0.0.1', user: 'root', password: 'root', database: 'native_symbol' }, debug: true, //指明是否開啓debug模式,默認爲true表示開啓 pool: { //指明數據庫鏈接池的大小,默認爲{min: 2, max: 10} min: 0, max: 7, }, acquireConnectionTimeout: 10000, //指明鏈接計時器大小,默認爲60000ms migrations: { tableName: 'migrations' //數據庫遷移,可選 } }); var idx = 100; router.get('/', (ctx, next) => { var timer = setInterval(() => { idx++; if (idx > 10000) { clearInterval(timer) return } url = `http://shop.bytravel.cn/produce/index${idx}.html`; //爬蟲地址 timePlay(url) console.log('頁面抓包記錄', idx) }, 100); timePlay = (url) => { superagent.get(url) .charset('gbk') .buffer(true) .end(async (err, data) => { //頁面獲取到的數據 // if (err) { // // return next(err); // console.log('頁面不存在', err) // } let html = data.text, $ = cheerio.load(html, { decodeEntities: false, ignoreWhitespace: false, xmlMode: false, lowerCaseTags: false }), //用cheerio解析頁面數據 obj = {}; arr = []; $("table tbody").each((index, element) => { let $element = $(element); $element.find('#tctitle').next().find('a').addClass('link').attr('class', 'link').text('') arr.push({ 'title': $element.find('a.blue14b').text(), 'image': $element.find('#bright img').attr('src'), 'summary': $element.find('#tctitle').next().text(), 'is_cgiia': $element.find('#tctitle font').attr('color') === 'green' ? 1 : 0 }) }) for (let i of arr) { const findRes = await knex('products').select().where('title', i.title) if (findRes.length) { console.log('數據已存在') } else { // 寫入庫 await knex('products') .returning('id') .insert(i) .then(res => { console.log('success', res) }) } } }); } ctx.body = arr; // console.log(arr) }); app .use(router.routes()) .use(router.allowedMethods()); app.listen(3010, () => { console.log('[服務已開啓,訪問地址爲:] http://127.0.0.1:3010/'); });