1. 程式人生 > >node抓取王者榮耀英雄資料庫

node抓取王者榮耀英雄資料庫

用node寫的爬蟲,抓取王者榮耀英雄資料庫,只是為了學習,侵刪

主要包括(基本上相關的都抓取):

  • 召喚師技能
  • 銘文
  • 裝備
  • 英雄
  • 面板
  • 英雄故事
  • 英雄技能
  • 推薦銘文
  • 推薦裝備
  • 技能加點

沒有搞懂如何動態抓取內容,我覺得抓取之前你要知道網頁的js邏輯,emmmm....

這裡我已經下載所需要的json檔案到專案裡面,如何下載:node下載檔案

資料庫的配置:

module.exports = {
    host: 'localhost',
    database: 'glory_of_kings',
    user: 'root',
    password: 'root'
};

也可以直接配置,不那麼麻煩,只是為了學習新的方式。

// mysql的包 很多安利easymysql的,暫時還沒改
let mysql = require('mysql');
// 檔案操作
let fs = require('fs');
// mysql配置
let mysqlConfig = require('./mysql.config');

// 爬蟲所需要的庫
let http = require('http');
let cheerio = require('cheerio');
let iconv = require('iconv-lite');


//建立連線,資料操作完成之後要關閉連線
let connection = mysql.createConnection(mysqlConfig);

//連線mysql
connection.connect(function (err) {
    if (err) {
        console.log('資料庫連線失敗');
        throw err;
    }
});

// json檔案的基礎路徑
const BASE_PATH = '../assets/jsons/';
// 檔案編碼方式
const FILE_TYPE = 'utf-8';


// 英雄資料頁面基礎路徑
const HERO_DETAIL_PATH = `http://pvp.qq.com/web201605/herodetail/`;
//英雄圖片的基礎路徑
const HERO_IMG_PATH = `http://game.gtimg.cn/images/yxzj/img201606/heroimg/`;
// 英雄面板大圖的基礎路徑
const HERO_BIGSKIN_PATH = `http://game.gtimg.cn/images/yxzj/img201606/skin/hero-info/`;
// 裝備圖片的基礎路徑
const EQUIP_IMG_PATH = `http://game.gtimg.cn/images/yxzj/img201606/itemimg/`;
//技能圖片的基礎路徑
const SUMMONER_PATH = `http://game.gtimg.cn/images/yxzj/img201606/summoner/`;
// 銘文圖片的基礎路徑
const INSCRIPTION_PATH = `http://game.gtimg.cn/images/yxzj/img201606/mingwen/`;


// 召喚師技能的插入語句
const SUMMONER_SQL = `insert into summoner(summoner_id,name,rank,cd,description,img_url,big_img_url) values(?,?,?,?,?,?,?)`;

// 銘文的插入語句
const INSCRIPTION_INSERT = `insert into inscription(inscription_id,type,grade,name,description,img_url) values(?,?,?,?,?,?)`;

// 英雄的插入語句
const HERO_INSERT = `insert into hero(hero_id,name,pay_type,new_type,hero_type,hero_type2,skin_name,img_url,live,attack,skill,difficulty) values (?,?,?,?,?,?,?,?,?,?,?,?)`;

//英雄面板的插入語句
const HERO_SKIN_INSERT = `insert into skin(skin_id,hero_id,skin_name,small_img_url,big_img_url) values (?,?,?,?,?)`;

// 裝備的插入語句
const EQUIP_INSERT = `insert into equip(equip_id,name,type,sale_price,total_price,des1,des2,img_url) values (?,?,?,?,?,?,?,?)`;

//英雄故事插入語句
const STORY_INSERT = `insert into story(hero_id,story) values (?,?)`;

// 英雄技能插入語句
const SKILL_INSERT = `insert into skill(skill_id,hero_id,name,cool,waste,description,tips,img_url) values (?,?,?,?,?,?,?,?)`;

// 推薦銘文的插入語句
const HERO_INSCRIPTION_INSERT = `insert into hero_inscription(hero_id,inscription_ids,tips) values (?,?,?)`;

// 推薦裝備的插入語句
const HERO_EQUIP_INSERT = `insert into hero_equip(hero_id,equip_ids1,tips1,equip_ids2,tips2) values (?,?,?,?,?)`;

// 英雄關係的插入語句
// 網頁中每個項都是兩個英雄,所以這裡一次插入兩條資料
const LINKS_INSERT = `insert into links(hero_id,hero_id1,type,tips) values (?,?,?,?),(?,?,?,?)`;

// 技能加點的建議
const SKILL_SUMMONER_INSERT = `insert into skill_summoner(ename,skill_id1,skill_id2,summoner_id1,summoner_id2) values (?,?,?,?,?)`;

/**
 * 更新召喚師技能
 */
function updateSummoner() {
    fs.readFile(`${BASE_PATH}summoner.json`, FILE_TYPE, function (err, data) {
        if (err) {
            console.log(`檔案讀取失敗`)
        } else {
            if (JSON.parse(data).length === 0) {
                console.log(`暫無資料`);
            } else {
                let params = [];
                JSON.parse(data).forEach(function (it, index) {
                    params = [
                        it.summoner_id,
                        it.summoner_name,
                        parseInt(it.summoner_rank.substring(3)),
                        parseInt(it.summoner_description),
                        it.summoner_description.split(':')[1],
                        `${SUMMONER_PATH}${it.summoner_id}.jpg`,
                        `${SUMMONER_PATH}${it.summoner_id}-big.jpg`
                    ];
                    connection.query(SUMMONER_SQL, params, function (error, res) {
                        if (error) {
                            console.log(error);
                            throw error;
                        }
                        console.log(`技能${it.summoner_name}插入成功!`);
                    });
                });
            }
        }
    });
}

/**
 * 更新銘文
 */
function updateInscription() {
    fs.readFile(`${BASE_PATH}ming.json`, FILE_TYPE, function (err, data) {
        if (err) {
            console.log(`檔案讀取失敗`)
        } else {
            if (JSON.parse(data).length === 0) {
                console.log(`暫無資料`);
            } else {
                let params = [];
                JSON.parse(data).forEach(function (it, index) {
                    params = [
                        it.ming_id,
                        it.ming_type,
                        it.ming_grade,
                        it.ming_name,
                        it.ming_des,
                        `${INSCRIPTION_PATH}${it.ming_id}.png`
                    ];
                    connection.query(INSCRIPTION_INSERT, params, function (error, res) {
                        if (error) {
                            console.log(error);
                            throw error;
                        }
                        console.log(`銘文${it.ming_name}插入成功!`);
                    });
                });
            }
        }
    });
}

/**
 * 更新裝備
 */
function updateEquipments() {
    fs.readFile(`${BASE_PATH}item.json`, FILE_TYPE, function (err, data) {
        if (err) {
            console.log(`檔案讀取失敗`)
        } else {
            if (JSON.parse(data).length === 0) {
                console.log(`暫無裝備資料`);
            } else {
                let params = [];
                JSON.parse(data).forEach(function (it, index) {
                    params = [
                        it.item_id,
                        it.item_name,
                        it.item_type,
                        it.price,
                        it.total_price,
                        it.des1,
                        it.des2,
                        `${EQUIP_IMG_PATH}${it.item_id}.jpg`
                    ];
                    connection.query(EQUIP_INSERT, params, function (error, res) {
                        if (error) {
                            console.log(error);
                            throw error;
                        }
                        console.log(`裝備:${it.item_name} 插入成功!`);
                    });
                });
            }
        }
    });
}

/**
 * 更新英雄
 */
function updateHero() {
    fs.readFile(`${BASE_PATH}heros.json`, FILE_TYPE, function (err, data) {
        if (err) {
            console.log(`檔案讀取失敗`)
        } else {
            if (JSON.parse(data).length === 0) {
                console.log(`暫無資料`);
            } else {
                let params = [];
                JSON.parse(data).forEach(function (it, index) {
                    // 測試
                    http.get(`${HERO_DETAIL_PATH}${it.ename}.shtml`, function (res) {
                        let chunks = [];
                        res.on('data', function (item) {
                            chunks.push(item);
                        });
                        res.on('end', function () {
                            // 解碼頁面,防止亂碼
                            let html = iconv.decode(Buffer.concat(chunks), 'gbk');
                            let $ = cheerio.load(html, {decodeEntities: false});
                            let list = $('.ibar');
                            params = [
                                it.ename,
                                it.cname,
                                it.pay_type,
                                it.new_type,
                                it.hero_type,
                                it.hero_type2,
                                it.skin_name,
                                `${HERO_IMG_PATH}${it.ename}/${it.ename}.jpg`,
                                parseInt(list[0].attribs.style.substring(6)),
                                parseInt(list[1].attribs.style.substring(6)),
                                parseInt(list[2].attribs.style.substring(6)),
                                parseInt(list[3].attribs.style.substring(6))
                            ];
                            connection.query(HERO_INSERT, params, function (error, res) {
                                if (error) {
                                    console.log(error);
                                    throw error;
                                }
                                console.log(`英雄${it.ename}插入成功!`);
                            });
                        })
                    }).on('error', function () {
                        console.log(`獲取頁面資料出錯`);
                    });
                });
            }
        }
    });
}

/**
 * 更新面板
 */
function updateSkin() {
    fs.readFile(`${BASE_PATH}heros.json`, FILE_TYPE, function (err, data) {
        if (err) {
            console.log(`檔案讀取失敗`)
        } else {
            if (JSON.parse(data).length === 0) {
                console.log(`暫無資料`);
            } else {
                let params = [];
                let names = [];
                JSON.parse(data).forEach(function (it, index) {
                    names = it.skin_name.split('|');
                    names.forEach(function (item, ind) {
                        params = [
                            it.ename + '' + (ind + 1),
                            it.ename,
                            item,
                            `${HERO_IMG_PATH}${it.ename}/${it.ename}-smallskin-${ind + 1}.jpg`,
                            `${HERO_BIGSKIN_PATH}${it.ename}/${it.ename}-bigskin-${ind + 1}.jpg`
                        ];
                        connection.query(HERO_SKIN_INSERT, params, function (error, res) {
                            if (error) {
                                console.log(error);
                                throw error;
                            }
                        });
                        console.log(`面板${item}插入成功!`);
                    });
                });
            }
        }
    });
}

/**
 * 更新故事
 */
function updateStory() {
    fs.readFile(`${BASE_PATH}heros.json`, FILE_TYPE, function (err, data) {
        if (err) {
            console.log(`檔案讀取失敗`);
        } else {
            let datas = JSON.parse(data);
            if (datas.length === 0) {
                console.log(`暫無英雄故事`);
            } else {
                let params = [];
                datas.forEach(function (it, index) {
                    http.get(`${HERO_DETAIL_PATH}${it.ename}.shtml`, function (res) {
                        let chunks = [];
                        res.on('data', function (item) {
                            chunks.push(item);
                        });
                        res.on('end', function () {
                            // 解碼頁面,防止亂碼
                            let html = iconv.decode(Buffer.concat(chunks), 'gbk');
                            let $ = cheerio.load(html, {decodeEntities: false});
                            params = [
                                it.ename,
                                $('.pop-story .pop-bd p').html()
                            ];
                            connection.query(STORY_INSERT, params, function (error, res) {
                                if (error) {
                                    console.log(error);
                                    throw error;
                                }
                                console.log(`${it.ename}的故事插入成功`);
                            });
                        })
                    }).on('error', function () {
                        console.log(`獲取頁面資料出錯`);
                    });
                });
            }
        }
    });
}

/**
 * 更新技能
 */
function updateSkill() {
    fs.readFile(`${BASE_PATH}heros.json`, FILE_TYPE, function (err, data) {
        if (err) {
            console.log(`檔案讀取失敗`);
        } else {
            if (JSON.parse(data).length === 0) {
                console.log(`暫無資料`);
            } else {
                let params = [];
                JSON.parse(data).forEach(function (it, index) {
                    // 測試
                    http.get(`${HERO_DETAIL_PATH}${it.ename}.shtml`, function (res) {
                        let chunks = [];
                        res.on('data', function (item) {
                            chunks.push(item);
                        });
                        res.on('end', function () {
                            // 解碼頁面,防止亂碼
                            let html = iconv.decode(Buffer.concat(chunks), 'gbk');
                            let $ = cheerio.load(html, {decodeEntities: false});
                            let skills = $('.skill-show .show-list');
                            skills.each(function (ind, el) {
                                let name = $(el).find('.skill-name b').html();
                                if (name) {
                                    params = [
                                        it.ename + '' + ind,
                                        it.ename,
                                        name,
                                        parseInt($($(el).find('.skill-name span')[0]).html().substring(4)),
                                        parseInt($($(el).find('.skill-name span')[1]).html().substring(3)),
                                        $(el).find('.skill-desc').html(),
                                        $(el).find('.skill-tips').html(),
                                        `${HERO_IMG_PATH}${it.ename}/${it.ename}${ind}0.png`,
                                    ];
                                    connection.query(SKILL_INSERT, params, function (error, res) {
                                        if (error) {
                                            console.log(error);
                                            throw error;
                                        }
                                    });
                                    console.log(`技能${name}插入成功!`);
                                }
                            });
                        })
                    }).on('error', function () {
                        console.log(`獲取頁面資料出錯`);
                    });
                });
            }
        }
    });

}

/**
 * 獲取搭配銘文
 */
function updateHeroInscription() {
    fs.readFile(`${BASE_PATH}heros.json`, FILE_TYPE, function (err, data) {
        if (err) {
            console.log("檔案讀取失敗");
        } else {
            if (JSON.parse(data).length === 0) {
                console.log('暫無資料');
            } else {
                let params = [];
                JSON.parse(data).forEach(function (it, index) {
                    http.get(`${HERO_DETAIL_PATH}${it.ename}.shtml`, function (res) {
                        let chunks = [];
                        res.on('data', function (item) {
                            chunks.push(item);
                        });
                        res.on('end', function () {
                            // 解碼頁面,防止亂碼
                            let html = iconv.decode(Buffer.concat(chunks), 'gbk');
                            let $ = cheerio.load(html, {decodeEntities: false});
                            params = [
                                it.ename,
                                $('.sugg-info ul').attr('data-ming').split('|').join(','),
                                $('.sugg-tips').text().substring('5')
                            ];
                            connection.query(HERO_INSCRIPTION_INSERT, params, function (err, result) {
                                if (err) {
                                    console.log(err);
                                    throw err;
                                }
                                console.log(`第${index}條資料插入成功!`);
                            })
                        })
                    }).on('error', function () {
                        console.log("獲取頁面資料出錯");
                    })
                });
            }
        }
    });
}

/**
 * 獲取推薦裝備
 */
function updateHeroEquip() {
    fs.readFile(`${BASE_PATH}heros.json`, FILE_TYPE, function (err, data) {
        if (err) {
            console.log("檔案讀取失敗");
        } else {
            if (JSON.parse(data).length === 0) {
                console.log('暫無資料');
            } else {
                let params = [];
                JSON.parse(data).forEach(function (it, index) {
                    http.get(`${HERO_DETAIL_PATH}${it.ename}.shtml`, function (res) {
                        let chunks = [];
                        res.on('data', function (item) {
                            chunks.push(item);
                        });
                        res.on('end', function () {
                            // 解碼頁面,防止亂碼
                            let html = iconv.decode(Buffer.concat(chunks), 'gbk');
                            let $ = cheerio.load(html, {decodeEntities: false});
                            params = [
                                it.ename,
                                $($('.equip-info ul')[0]).attr('data-item').split('|').join(','),
                                $($('.equip-tips')[0]).text().substring('5'),
                                $($('.equip-info ul')[1]).attr('data-item').split('|').join(','),
                                $($('.equip-tips')[1]).text().substring('5')
                            ];
                            // console.log(params);
                            connection.query(HERO_EQUIP_INSERT, params, function (err, result) {
                                if (err) {
                                    console.log(err);
                                    throw err;
                                }
                                console.log(`第${index}條資料插入成功!`);
                            })
                        })
                    }).on('error', function () {
                        console.log("獲取頁面資料出錯");
                    })
                });
            }
        }
    });
}

/**
 * 獲取英雄關係
 */
function updateLinks() {
    fs.readFile(`${BASE_PATH}heros.json`, FILE_TYPE, function (err, data) {
        if (err) {
            console.log("檔案讀取失敗");
        } else {
            if (JSON.parse(data).length === 0) {
                console.log('暫無資料');
            } else {
                let params = [];
                JSON.parse(data).forEach(function (it, index) {
                    http.get(`${HERO_DETAIL_PATH}${it.ename}.shtml`, function (res) {
                        let chunks = [];
                        res.on('data', function (item) {
                            chunks.push(item);
                        });
                        res.on('end', function () {
                            // 解碼頁面,防止亂碼
                            let html = iconv.decode(Buffer.concat(chunks), 'gbk');
                            let $ = cheerio.load(html, {decodeEntities: false});
                            $('.hero-info').each(function (ind, el) {
                                params = [
                                    it.ename,
                                    $($(el).find('ul a')[0]).attr('href').substr(0, 3),
                                    ind,
                                    $($(el).find('p')[0]).html(),
                                    it.ename,
                                    $($(el).find('ul a')[1]).attr('href').substr(0, 3),
                                    ind,
                                    $($(el).find('p')[1]).html(),
                                ];
                                connection.query(LINKS_INSERT, params, function (err, result) {
                                    if (err) {
                                        console.log(err);
                                        throw err;
                                    }
                                })
                            });
                            console.log(`第${index}條資料插入成功!`);
                        })
                    }).on('error', function () {
                        console.log("獲取頁面資料出錯");
                    })
                });
            }
        }
    });
}

/**
 * 英雄技能加點推薦
 */
function updateSkillSummoner() {
    fs.readFile(`${BASE_PATH}heros.json`, FILE_TYPE, function (err, data) {
        if (err) {
            console.log("檔案讀取失敗");
        } else {
            if (JSON.parse(data).length === 0) {
                console.log('暫無資料');
            } else {
                let params = [];
                JSON.parse(data).forEach(function (it, index) {
                    http.get(`${HERO_DETAIL_PATH}${it.ename}.shtml`, function (res) {
                        let chunks = [];
                        res.on('data', function (item) {
                            chunks.push(item);
                        });
                        res.on('end', function () {
                            // 解碼頁面,防止亂碼
                            let html = iconv.decode(Buffer.concat(chunks), 'gbk');
                            let $ = cheerio.load(html, {decodeEntities: false});
                            params = [
                                it.ename,
                                $($('.sugg-skill img')[0]).attr('src').substring(50, 54),
                                $($('.sugg-skill img')[1]).attr('src').substring(50, 54),
                                $($('.sugg-info2 p')[5]).attr('data-skill').substring(0, 5),
                                $($('.sugg-info2 p')[5]).attr('data-skill').substring(6)
                            ];
                            connection.query(SKILL_SUMMONER_INSERT, params, function (err, result) {
                                if (err) {
                                    console.log(err);
                                    throw err;
                                }
                                console.log(`第${index}條資料插入成功!`);
                            });
                        })
                    }).on('error', function () {
                        console.log("獲取頁面資料出錯");
                    })
                });
            }
        }
    });
}

// 關閉資料庫連線
connection.end(function (e) {
    if (e) {
        console.log(`關閉資料庫失敗`);
        throw e;
    }
});

exports.updateSummoner = updateSummoner;
exports.updateInscription = updateInscription;
exports.updateHero = updateHero;
exports.updateSkin = updateSkin;
exports.updateEquipments = updateEquipments;
exports.updateStory = updateStory;
exports.updateSkill = updateSkill;
exports.updateHeroInscription = updateHeroInscription;
exports.updateHeroEquip = updateHeroEquip;
exports.updateLinks = updateLinks;
exports.updateSkillSummoner = updateSkillSummoner;

 所有英雄的herolist.json檔案有點問題,解析json物件,老是報錯,然後手動修改成了heros.json,兩個檔案內容是一樣的,但是heros可以,herolist不可以,很尷尬,如果你解決了,可以和我說下,謝謝

周免英雄這裡也有點意思,動態插入的,不方便直接獲取,然後費了老大勁才發現,抓取的所有英雄的json檔案中,pay_type=10的英雄就是周免,pay_type=11的英雄是新手推薦,header.js裡面處理了,emmmm........(傳送:周免英雄,程式碼在339-347

var freeHeroData = [],
    freeHeroHtml = "";
for (var i = 0; i < data.length; i++) {
    var payarr = [],
        payarr = ('' + data[i].pay_type).split(',');
    // 如果pay_type=10,插入的freeHeroData
    if (payarr == 10 || payarr[0] == 10 || payarr[1] == 10) {
        freeHeroData.push(data[i]);
    }
}
// console.log(freeHeroData);

OK!