首先我們看下數據來源:
來源於這個網站: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的播放器中就可以直接播放了。

(完)
