首先我们看下数据来源:

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

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

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

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

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

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

我们点击这里,然后点击这个小图标

断点发现,生成z参数的就是这个p变量

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

我使用fiddler代理篡改了这段代码,就是将这个z参数显示在dom中

因此,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返回了。

拿到了。这个数据一般能使用几个小时,几个小时后又需要重新获取新的值了,重新执行接口即可。

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

看后续写法:

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在服务器中构建一个获取电影电视剧剧集的接口的更多相关文章

  1. Nodejs课堂笔记-第三课 构建一个nodejs的Docker镜像

    本文由Vikings(http://www.cnblogs.com/vikings-blog/) 原创,转载请标明.谢谢! 因为一直做Linux有关的开发工作,所以不习惯在Windows平台编译和测试 ...

  2. 《Entity Framework 6 Recipes》中文翻译系列 (20) -----第四章 ASP.NET MVC中使用实体框架之在MVC中构建一个CRUD示例

    翻译的初衷以及为什么选择<Entity Framework 6 Recipes>来学习,请看本系列开篇 第四章  ASP.NET MVC中使用实体框架 ASP.NET是一个免费的Web框架 ...

  3. nodejs应用在linux服务器中的部署

    1.(可选)添加用户: addgroup wmui添加用户组useradd -d /home/wmui -s /bin/bash -m wmui创建wmui用户passwd wmui设置密码,如果忘记 ...

  4. 系统用户在Samba服务器中起一个别名

    (1)通过/etc/samba/smbusers文件设置用户映射关系 如实列: # cat /etc/samba/smbusers # Unix_name = SMB_name1 SMB_name2 ...

  5. 在JAVASCRIPT中构建一个复杂的对象,并用JSON进行转换

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...

  6. MFC中打开一个获取路径的对话框

    不废话,上代码 CString m_FileDir; BROWSEINFO bi; ZeroMemory(&bi, sizeof(BROWSEINFO)); bi.hwndOwner = m_ ...

  7. 使用.net core在Ubuntu构建一个TCP服务器

    介绍和背景 TCP编程是网络编程领域最有趣的部分之一.在Ubuntu环境中,我喜欢使用.NET Core进行TCP编程,并使用本机Ubuntu脚本与TCP服务器进行通信.以前,我在.NET框架本身写了 ...

  8. Xamarin XAML语言教程Xamarin.Forms中构建进度条

    Xamarin XAML语言教程Xamarin.Forms中构建进度条 ProgressBar被称为进度条,它类似于没有滑块的滑块控件.进度条总是水平放置的.本节将讲解如何使用进度条. 注意:进度条在 ...

  9. RabbitMQ(四):使用Docker构建RabbitMQ高可用负载均衡集群

    本文使用Docker搭建RabbitMQ集群,然后使用HAProxy做负载均衡,最后使用KeepAlived实现集群高可用,从而搭建起来一个完成了RabbitMQ高可用负载均衡集群.受限于自身条件,本 ...

随机推荐

  1. PHP网上商城

    页面展示: 代码参考:Php实现简易购物商城系统 - 邵文 - 博客园 (cnblogs.com)

  2. git撤销文件的修改

    git撤销某个文件的修改,分为两种情况:1.在工作区修改,但并未提交到暂存区(即并没有add).对于单个文件的撤销修改而言,使用下面方法. git checkout -- 文件名 若想撤销工作区中所有 ...

  3. flex 简单设置

    /*弹性盒子 start*/ /* ============================================================ flex:定义布局为盒模型 flex-v: ...

  4. TP5用join进行查询出来后的循环id都是一样的

    这是因为join将两个表的所有字段都查询,id冲突了,所以需要设置名,或指定选择一个表的id 用field('a.*')

  5. Java基础系列(40)- Arrays类

    Arrays类 数据的工具类java.util.Arrays 由于数组对象本身并没有什么方法可以供我们调用,但API中提供了一个工具类Arrays供我们使用,从而可以对数据对象进行一些基本的操作 查看 ...

  6. Linux系列(14) - grep

    简述 grep是在文件当中匹配符合条件的字符串,作用是查找文件内容 格式 grep [选项] 字符串 文件名 选项 -i:忽略大小写 -v:排除指定字符串 -n:显示行号 例子 grep " ...

  7. 自制Chrome扩展插件:用于重定向js

    前言 作为一个前端开发, 在调试生产环境的代码时,是否苦于生产环境代码被压缩,没有sourcemap? 有没有想过将生产环境的js直接重定向为本地开发环境的js? 玩微前端时,有没有想过用本地的子应用 ...

  8. php pdo 参数绑定

    * 数据表 -- MySQL dump 10.16 Distrib 10.1.31-MariaDB, for osx10.6 (i386) -- -- Host: localhost Database ...

  9. 测试验收标准checklist

    需求实现功能清单 功能实现目的 需求改造功能清单 关联功能清单 关联系统 端到端全流程场景 业务联系性场景 业务全流程场景 上下需求关联规则 业务角度在流程中关注项 财报.评级 授信方案 反洗钱 面向 ...

  10. python实现rtsp取流并截图

    import cv2 def get_img_from_camera_net(folder_path): cap = cv2.VideoCapture("rtsp://admin:admin ...