数据采集实战(三)-
短信预约 信息系统项目管理师 报名、考试、查分时间动态提醒
王者荣耀是一直都挺喜欢的一个手游,玩了好几年,最近一段开始喜欢看比赛,所以想着采集点数据看看各个战队或者选手的情况。
顺便也练习练习 puppeteer 的使用。
数据来源于:尚牛电竞 。
王者荣耀最近正在进行的最大比赛就是 2021世冠杯,所以就选择采集这个赛事的数据。
在 尚牛电竞 网站上,已经按照战队,选手和英雄分好类了,并且网站不需要登录就能看到数据。
三组数据直接对应不同的URL进行采集即可,没有复杂的流程,唯一需要注意的地方是对Logo和头像的小图片的保存。
2.1 各个数据的采集
积分榜的数据是空的,战队榜,选手榜和英雄榜的数据可以获取。
3种数据的URL分别为:
const urls = [
{
url: "https://www.shangniu.cn/gdall/kog?tab=0&pid=40008&tid=45",
name: "战队榜",
},
{
url: "https://www.shangniu.cn/gdall/kog?tab=1&pid=40008&tid=45",
name: "选手榜",
},
{
url: "https://www.shangniu.cn/gdall/kog?tab=2&pid=40008&tid=45",
name: "英雄榜",
},
];
2.1.1 战队数据的采集和解析
// 战队数据
const teamData = async (browser, page, url) => {
await page.goto(url);
// 解析页面
const data = [];
const rows = await page.$$("#scroll-table > .tbody > .row");
for (const row of rows) {
let line = [];
const cols = await row.$$(".td");
line[0] = await cols[1].$eval("a > img", (node) =>
node.getAttribute("class="lazy" data-src")
);
line[1] = await cols[1].$eval(
".right-name > .item-name",
(node) => node.innerText
);
line[2] = await page.evaluate((node) => node.innerText, cols[2]);
line[3] = await page.evaluate((node) => node.innerText, cols[3]);
line[4] = await page.evaluate((node) => node.innerText, cols[4]);
line[5] = await page.evaluate((node) => node.innerText, cols[5]);
line[6] = await page.evaluate((node) => node.innerText, cols[6]);
line[7] = await page.evaluate((node) => node.innerText, cols[7]);
line[8] = await cols[8].$eval("div > .kda", (node) => node.innerText);
line[9] = await page.evaluate((node) => node.innerText, cols[9]);
line[10] = await page.evaluate((node) => node.innerText, cols[10]);
line[11] = await page.evaluate((node) => node.innerText, cols[11]);
line[12] = await page.evaluate((node) => node.innerText, cols[12]);
line[13] = await page.evaluate((node) => node.innerText, cols[13]);
line[14] = await page.evaluate((node) => node.innerText, cols[14]);
line[15] = await page.evaluate((node) => node.innerText, cols[15]);
line[16] = await page.evaluate((node) => node.innerText, cols[16]);
line[17] = await page.evaluate((node) => node.innerText, cols[17]);
line[18] = await page.evaluate((node) => node.innerText, cols[18]);
line[19] = await page.evaluate((node) => node.innerText, cols[19]);
line[20] = await page.evaluate((node) => node.innerText, cols[20]);
line[21] = await page.evaluate((node) => node.innerText, cols[21]);
line[22] = await page.evaluate((node) => node.innerText, cols[22]);
data.push(line.join(","));
await downloadImage(
browser,
"./output/wzry/team-logo",
`${line[1]}.png`,
line[0]
);
}
await saveContent(
`./output/wzry`,
`world_cup_2021_team.csv`,
data.join("
")
);
};
2.1.2 选手数据的采集和解析
// 选手数据
const memberData = async (browser, page, url) => {
await page.goto(url);
// 解析页面
const data = [];
const rows = await page.$$("#scroll-table > .tbody > .row");
for (const row of rows) {
let line = [];
const cols = await row.$$(".td");
line[0] = await cols[1].$eval("a > img", (node) =>
node.getAttribute("class="lazy" data-src")
);
line[1] = await cols[1].$eval(
".right-name > .item-name",
(node) => node.innerText
);
line[2] = await page.evaluate((node) => node.innerText, cols[2]);
line[3] = await page.evaluate((node) => node.innerText, cols[3]);
line[4] = await page.evaluate((node) => node.innerText, cols[4]);
line[5] = await cols[5].$eval("div > .kda", (node) => node.innerText);
line[6] = await page.evaluate((node) => node.innerText, cols[6]);
line[7] = await page.evaluate((node) => node.innerText, cols[7]);
line[8] = await page.evaluate((node) => node.innerText, cols[8]);
line[9] = await page.evaluate((node) => node.innerText, cols[9]);
line[10] = await page.evaluate((node) => node.innerText, cols[10]);
line[11] = await page.evaluate((node) => node.innerText, cols[11]);
line[12] = await page.evaluate((node) => node.innerText, cols[12]);
line[13] = await page.evaluate((node) => node.innerText, cols[13]);
line[14] = await page.evaluate((node) => node.innerText, cols[14]);
line[15] = await page.evaluate((node) => node.innerText, cols[15]);
data.push(line.join(","));
await downloadImage(
browser,
"./output/wzry/member-logo",
`${line[1]}.png`,
line[0]
);
}
await saveContent(
`./output/wzry`,
`world_cup_2021_member.csv`,
data.join("
")
);
};
2.1.3 英雄数据的采集和解析
// 英雄数据
const heroData = async (browser, page, url) => {
await page.goto(url);
// 解析页面
const data = [];
const rows = await page.$$("#scroll-table > .tbody > .row");
for (const row of rows) {
let line = [];
const cols = await row.$$(".td");
line[0] = await cols[1].$eval("a > img", (node) =>
node.getAttribute("class="lazy" data-src")
);
line[1] = await cols[1].$eval(
".right-name > .item-name",
(node) => node.innerText
);
line[2] = await page.evaluate((node) => node.innerText, cols[2]);
line[3] = await page.evaluate((node) => node.innerText, cols[3]);
line[4] = await page.evaluate((node) => node.innerText, cols[4]);
line[5] = await cols[5].$eval(".winRate > span", (node) => node.innerText);
line[6] = await page.evaluate((node) => node.innerText, cols[6]);
line[7] = await page.evaluate((node) => node.innerText, cols[7]);
line[8] = await page.evaluate((node) => node.innerText, cols[9]);
data.push(line.join(","));
await downloadImage(
browser,
"./output/wzry/hero-logo",
`${line[1]}.png`,
line[0]
);
}
await saveContent(
`./output/wzry`,
`world_cup_2021_hero.csv`,
data.join("
")
);
};
2.2 logo和头像的保存
在html页面中,logo和头像都是图片的url,为了下载实际的图片,封装了个小函数 downloadImage。
// 下载图片
const downloadImage = async (browser, dirname, filename, imgclass="lazy" data-src) => {
console.log("image class="lazy" data-src: ", imgclass="lazy" data-src);
const page = await browser.newPage();
try {
const imgResp = await page.goto(imgclass="lazy" data-src);
const buffer = await imgResp.buffer();
const imgBase64 = buffer.toString("base64");
if (!mkdirsSync(dirname)) {
console.error("mkdir save page dir ERROR!");
return;
}
fs.writeFileSync(path.join(dirname, filename), imgBase64, "base64");
} catch (e) {
console.error("download image error: ", e);
} finally {
await page.close();
}
};
以上通过 puppeteer 采集2021世冠比赛数据的实战中,技术要点主要有:
- 解析页面元素中的值
- 循环获取html table 中 tr/td 中的内容
- 下载网页中图片
爬取数据只是为了研究学习使用,本文中的代码遵守:
- 如果网站有 robots.txt,遵循其中的约定
- 爬取速度模拟正常访问的速率,不增加服务器的负担
- 只获取完全公开的数据,有可能涉及隐私的数据绝对不碰
免责声明:
① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。
② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341