You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
pxskm4tvn adf64a8c4b
Update README.md
5 months ago
README.md Update README.md 5 months ago

README.md

102201124

const axios = require('axios');
const cheerio = require('cheerio');
const fs = require('fs');
const { JSDOM } = require('jsdom');

// 初始化空数组用于存储BV号、CID号和弹幕内容
let bvList = [];
let cidList = [];
let chatList = [];

2.2.3 几个重要的函数

// 第一个函数是获取BV号这一部分代码是整体代码中最关键的一步下面两个函数的基本思想也是建立在最开始的这个函数上即通过开发者工具获取url,找到可使用的变量在这段代码中笔者决定在每一页B站搜索页面爬取三十个视频共需要三百个故采取page作为函数的参数同时在url上进行改写最后通过对应的正则去筛选想要的信息。

async function getBv(page) {
    const url = `https://api.bilibili.com/x/web-interface/wbi/search/type?category_id=&search_type=video&ad_resource=5654&__refresh__=true&_extra=&context=&page=${page}&page_size=30&pubtime_begin_s=0&pubtime_end_s=0&from_source=&from_spmid=333.337&platform=pc&highlight=1&single_column=0&keyword=2024%E5%B7%B4%E9%BB%8E%E5%A5%A5%E8%BF%90%E4%BC%9A`;
    const headers = { "user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/128.0.0.0 Safari/537.36 Edg/128.0.0.0" };
    const response = await axios.get(url, { headers: headers });
    const data = response.data;
    const bvListTemp = data.match(/"bvid":"(.*?)"/g);
    if (bvListTemp) {
        bvList = [...bvList, ...bvListTemp.map(item => item.replace(/"bvid":"(.*?)"/, '$1'))];
    }
    console.log(`第${page}页爬取到bv号成功`);
}

// 第二个函数是获取cid号这个id是弹幕文件的id也是通过开发者工具去通过给定网络请求在网络栏中找的url但是前提是已知某个视频的bv号bv号如同视频的身份证所以在第一个函数的基础上才能寻得cid也因此第二个函数的参数是bv。和第一个函数较为不同的是正则的使用第二个函数采用的是Json解析分析发现cid在data里面同时值得一提的是一个bv号能爬出多个cid由于视频存在多P的情况而任务需要的是第一个cid。

async function getCid(bv) {
    const url = `https://api.bilibili.com/x/player/pagelist?bvid=${bv}&jsonp=jsonp`;
    const headers = { "user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/128.0.0.0 Safari/537.36 Edg/128.0.0.0" };
    const response = await axios.get(url, { headers: headers });
    const data = response.data;
    if (data && data.data && data.data[0] && data.data[0].cid) {
        const cid = data.data[0].cid;
        cidList.push(cid);
    }
    console.log(`${bv}的cid获取成功`);
}

// 第三个函数是已经对应的cid号去爬取弹幕内容通过解析xml数据使用正则去爬取弹幕整体思路和前两个函数基本一致。

async function getChat(cid) {
    const url = `https://comment.bilibili.com/${cid}.xml`;
    const headers = { "user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/128.0.0.0 Safari/537.36 Edg/128.0.0.0" };
    const response = await axios.get(url, { headers: headers });
    const xml = response.data;
    const dom = new JSDOM(xml);
    const document = dom.window.document;
    document.querySelectorAll('d').forEach(item => {
        const text = item.textContent;
        chatList.push(text);
    });
    console.log(`爬取${chatList.length}条弹幕。`);
}

2.2.4打印所需数据

async function main() {
    // 爬取第1页到第10页的视频BV号
    for (let i = 1; i <= 10; i++) {
        await getBv(i);
    }
    console.log("BV列表长度:", bvList.length);

    // 将BV号写入本地文件
    fs.writeFileSync('bv.txt', bvList.join('\n'), 'utf-8');

    // 对于每个BV号爬取CID号
    bvList.forEach(bv => {
        getCid(bv);
    });
    console.log("CID列表长度:", cidList.length);

    // 将CID号写入本地文件
    fs.writeFileSync('cid.txt', cidList.join('\n'), 'utf-8');

    // 对于每个

CID号爬取弹幕内容
cidList.forEach(cid => {
getChat(cid);
});
console.log("弹幕内容列表长度:", chatList.length);

// 将弹幕内容写入本地文件
fs.writeFileSync('chat.txt', chatList.join('\n'), 'utf-8');
}

main();