首先我们看下数据来源:

来源于这个网站: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. ecshop后台设置模板的地方显示自己新建模板的操作界面

    我建立了一个叫test.dwt文件怎样在后台设置模板里面出现呢.1首先找到ecshop目录下的languages\zh_cn\admin/template.php 这个php文件 当然如果这只是简体中 ...

  2. requests接口测试-requests的安装

    requests接口测试-requests的安装 安装常见问题 提示连接不上,443问题 一般是因为浏览器设置了代理,关闭代理. 网络加载慢,设置国内镜像地址 1.pip安装 2.pycharm安装 ...

  3. ELK实战部署

    环境 : 一台 centos 6.7 IP地址: 192.168.88.250 软件版本 : ElasticSearch 2.1.0    Logstash 2.1.1  Kibana 4.3.1   ...

  4. setTimeout 与setInterval的区别

    setTimeout(code,millisec) 方法用于在指定的毫秒数后调用函数或计算表达式 setInterval(code,millisec) 方法可按照指定的周期(以毫秒计)来调用函数或计算 ...

  5. mysql where in 数组解决小tips

    由于sql语法要求,不可在in后面直接连数组,若数组形式下,则需要转换成逗号隔开的字符串 <?php$arr = array(1,2,3,4,5);$arr_string= join(',', ...

  6. Expression Tree 遍历集合

    场景 从接口返回的数据是集合,却是 object 类型的.这个时候需要遍历这个集合.现提供两种方法. 方法一: 因为集合是可枚举的,所以可以尝试转为 IEnumerable 类型,然后遍历即可. st ...

  7. [gdoi2018 day1]小学生图论题【分治NTT】

    正题 题目大意 一张随机的\(n\)个点的竞赛图,给出它的\(m\)条相互无交简单路径,求这张竞赛图的期望强联通分量个数. \(1\leq n,m\leq 10^5\) 解题思路 先考虑\(m=0\) ...

  8. P3352-[ZJOI2016]线段树【dp】

    正题 题目链接:https://www.luogu.com.cn/problem/P3352 题目大意 \(n\)个数字的一个序列,每次随机选择一个区间让这个区间所有数等于这个区间的最大值,重复\(q ...

  9. Matrix Analysis and Application

    Chap 1: Linear Equations and Matrix Linear equations Gaussian elimination Pivot; Triangularize; Back ...

  10. Linux命令行:free

                  total        used        free      shared  buff/cache   availableMem:           251G   ...