nodejs:使用puppeteer在服务器中构建一个获取电影电视剧剧集的接口

首先我们看下数据来源:

来源于这个网站:https://z1.m1907.cn/

可以说这个网站上能找到很多你想看的很多电影或电视剧,最重要的是很多电影电视剧在别的网站是收费的,但是在这里看是免费的,之前也经常在这个网站中看。

nodejs:使用puppeteer在服务器中构建一个获取电影电视剧剧集的接口

不过这个网站有些缺点:在微信中被屏蔽了网址。在夸克浏览器上如果播放到某集,夸克播放器就会覆盖掉原生播放器,导致切换下一集时不好切换过去,因此,希望能开发一个自己的网站,获取该网站的数据来呈现。

 

一般来说,我们只需要拿到这些数据的url接口就行了。但是看了这个网站的network请求,发现这个接口的某个参数是可变的,而且还是必须要的。

这个url就算获取视频列表的接口,但是中间的z参数是必填的,而且每过一段时间就需要更换参数。

nodejs:使用puppeteer在服务器中构建一个获取电影电视剧剧集的接口

这个参数它不来源于上一个接口的某个结果,它是通过js进行了md5之后生成的。这就难办了。怎么去获取这个值呢?

nodejs:使用puppeteer在服务器中构建一个获取电影电视剧剧集的接口

我们点击这里,然后点击这个小图标nodejs:使用puppeteer在服务器中构建一个获取电影电视剧剧集的接口

断点发现,生成z参数的就是这个p变量nodejs:使用puppeteer在服务器中构建一个获取电影电视剧剧集的接口

然后,因为内部代码已被压缩,所以不好理清楚里面的逻辑了,所以就采用了fiddler抓包工具,将这个js文件进行代理到本地js中。篡改js文件做一些外加功能。

我使用fiddler代理篡改了这段代码,就是将这个z参数显示在dom中nodejs:使用puppeteer在服务器中构建一个获取电影电视剧剧集的接口

因此,dom中就有了这么一个dom元素,那么这有什么用呢?这样我就能在自己的服务器中拿到这个值?

是的,我使用的是nodejs。前段时间在网上找到了一个有意思npm包,用来在服务器中模拟浏览器操作,自然在服务器中就能获取到浏览器中渲染的dom了。那就是标题里说的puppeteer。

因为之前用fiddler代理将这个只放在了dom中,因此我们也就可以使用puppeteer模块从dom中拿到这个值,曲线救国。

 

请看实现(使用koajs服务端,ctx.response.body即可输出这个z参数)

const puppeteer = require('puppeteer');
/**
 * 获取https://z1.m1907.cn/的动态z 需求开fiddler
 */
module.exports = async(ctx) => {
    const browser = await puppeteer.launch();
    const page = await browser.newPage();
    await page.goto('https://z1.m1907.cn/?jx=bilibili');
    //注入脚本
    const dimensions = await page.evaluate(async() => {
        let z = ''
        if (document.querySelector('#z')) {
            z = document.querySelector('#z').innerText;
        }
        return {
            z,
        }
    });
    await browser.close();
    ctx.response.body = dimensions;
    return dimensions;//这个return是给下一个接口调用的
}

 

page.evaluate可以将浏览器的js代码注入到dimensions的隐藏浏览器中。就能通过document.querySelector('#z').innerText拿到那个z参数,然后通过node返回了。

nodejs:使用puppeteer在服务器中构建一个获取电影电视剧剧集的接口拿到了。这个数据一般能使用几个小时,几个小时后又需要重新获取新的值了,重新执行接口即可。

 

拿到这样要获取数据就容易多了。

看后续写法:

const { loadPage } = require('../../utils/utils');
const getId = require('./getId');
const setting = require('./setting');

/**
 * 主程序
 */
const videos = async(ctx) => {
    const { title = 'bilibili', z = null } = ctx.query
        // console.log(setting.z)
    z && (setting.z = z); //手动输入z参数
    const content = await loadPage(`https://a1.m1907.cn/api/v/?z=${setting.z}&jx=${title}&s1ig=11402&g=`);
    if (content.includes('获取json版api地址')) {//获取数据错误 重新获取z参数
        const obj = await getId(ctx);
        console.log(obj)
        setting.z = obj.z
        await videos(ctx)
        return;
    }
    ctx.response.body = content;
}

module.exports = videos;

 

loadPage是封装的请求页面的方法,getId是之前用于返回z参数的方法,setting是用于储存获取到的z参数,失效了才重新获取。

这样就能返回数据了。

访问接口,拿到当前电视剧/电影的所有剧集的m3u8播放地址,这样在支持m3u8的播放器中就可以直接播放了。

nodejs:使用puppeteer在服务器中构建一个获取电影电视剧剧集的接口

(完)

 

 

上一篇:‘cnpm‘ 不是内部或外部命令,也不是可运行的程序 从根源解决问题


下一篇:nodejs更新package.json中的dependencies依赖到最新版本的方法