逆向爬虫32 某视频刷播放
目标:利用爬虫刷某视频播放量
思路:和某站一样,先抓包验证哪个数据包可以使播放量增加,这个过程就省略了,经过测试发现是下图这个数据包
观察请求参数
ctime: 动态时间
ua: 固定
hh_ua: 固定
platform: 固定
guid: 固定
Pwd: 固定
version: 固定
url: 当前url
hh_ref: 当前url
vid: 当前url中的参数
isfocustab: 固定
isvisible: 固定
idx: 固定
val: 动态变化
pid: 格式和guid很像,但是每次都会变化
bi: 固定
bt: 固定
vurl: 加密参数,很长
step: 固定
val1: 固定
val2: 固定
fact1: 空
fact2: 空
fact3: 空
fact4: 空
fact5: 空
需要处理的参数有
ctime: 动态时间
vid: 当前url中的参数
val: 动态变化
pid: 格式和guid很像,但是每次都会变化
vurl: 加密参数,很长
ctime:直接用python生成
def get_now_time():
now = datetime.datetime.now()
return str(now)[:-7]
pid:经过简单的跟值查找发现是这行代码生成的
createGUID: ()=>`${(new Date).getTime().toString(36)}_${Math.random().toString(36).replace(/^0./, "")}`
val:经过简单的跟值查找发现是这些代码生成的
const {startLoadTime: t, playingTime: e} = this
, i = {
step: 6,
val: e - t
};
是两个时间戳的差,因为是时间戳相关,只需要每次给个随机差值就行,随机一个四位证书即可
from random import randint
val = randint(1000,10000)
vid:直接从url连接中提取即可
vurl:本身是个url,里面又包含很多参数
url: 动态变化
sdtfrom: 固定
guid: 固定
vkey: 动态变化
需要处理的参数有
url: 动态变化
vkey: 动态变化
vkey:通过全局搜索发现vkey在一个 playvinfo请求包
的响应中,并且url的变化部分也在里面
因此接下来要分析 playvinfo数据包
怎么发送,改数据包的请求参数有
callback: 固定
guid: 固定
platform: 固定
vid: url中提取
defn: 固定
charge: 固定
defaultfmt: 固定
otype: 固定
defnpayver: 固定
appVer: 固定
sphttps: 固定
sphls: 固定
spwm: 固定
dtype: 固定
defsrc: 固定
encryptVer: 固定
sdtfrom: 固定
cKey: 动态变化
flowid: 和前面的pid一样
需要处理的参数有
vid: url中提取
cKey: 动态变化
flowid: 和前面的pid一样
vid:直接从url连接中提取即可
flowid:直接和前面的pid用一个参数即可
ckey:经过简单的跟值发现在 ysplayer.modern.js文件
的307行生成
getRequestCkey(e) {
const {guid: t=e.guid, platform: r=e.platform} = this.context;
return _(e.vid, e.svrtick || C.a.getTimeStampStr(), "1.1.1", t, r)
}
_(e.vid, e.svrtick || C.a.getTimeStampStr(), "1.1.1", t, r)
这行代码的参数基本都是明文,因此只需要把 _函数
扣出来调用就可以了。
接下来的步骤:
- 在浏览器中导出
_函数
传入参数生成ckey - 在node环境中补充相关环境,使代码可以运行
先把该文件拷贝到本地,然后找到 _函数
定义或赋值的地方,将函数导出
然后把代码复制到浏览器中
然后就是本地node运行,补环境了,代码最终如下
//v30.js
const jsdom = require("jsdom");
const { JSDOM } = jsdom;//导入jsdom模块
//页面内容
const html = "<!DOCTYPE html><p>Hello world</p>";
//UA伪装(不是头信息伪装)
const resourceLoader = new jsdom.ResourceLoader({
userAgent: "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.55 Safari/537.36",
});
const dom = new JSDOM(html,{
//伪装的内容
url: "https://www.toutiao.com",
referrer: "https://example.com/",
contentType: "text/html",
resources: resourceLoader, //UA伪装
})
window = global // window 对象 全局对象
document = dom.window.document //全局对象
//存储了location和navigator的值,这些值都可以从网站的开发者工具的console中获取
const params = {
location: {
hash: "",
host: "www.toutiao.com",
hostname: "www.toutiao.com",
href: "https://www.toutiao.com",
origin: "https://www.toutiao.com",
pathname: "/",
port: "",
protocol: "https:",
search: "",
},
navigator: {
appCodeName: "Mozilla",
appName: "Netscape",
appVersion: "5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/93.0.4577.82 Safari/537.36",
cookieEnabled: true,
deviceMemory: 8,
doNotTrack: null,
hardwareConcurrency: 4,
language: "zh-CN",
languages: ["zh-CN", "zh"],
maxTouchPoints: 0,
onLine: true,
platform: "MacIntel",
product: "Gecko",
productSub: "20030107",
userAgent: "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/93.0.4577.82 Safari/537.36",
vendor: "Google Inc.",
vendorSub: "",
webdriver: false
}
};
//将params加入到全局变量中,变身为全局变量
Object.assign(global,params);
self = window;
var HTMLElement = function(){}
var CSSStyleSheet = function(){}
window.customElements = {
define: function(){}
}
/*
之前放在浏览器中运行的代码
*/
console.log(window.__('c00001502ax',"1650964664","1.1.1","l2fvcg3z_y6db6t2siff",4330701));
/* 结果输出
--017F8DF6D88F901AC50FF61CA2607A33AD2CE7737B97C046D9E753DCF54A9C5AB5F6F192641D62B6974251894C3932EBC7B50ED2BC85FCCCFB46ABCC0D654F34DC2EBB0FEA26A1550D75D0096BE6814C7501C4487D524B484B5518E70513A28030E93763A7961796F6B98B9FB4A5078BB192629F3A1F10D77B679863DC19D20D7A06E34382A3D9403942A8391B439331DE60882E879F99398D5A30AB19160F3F716CF67F0A7727675A5C3F502D334839C8DE4E163D4F9FAF348E57FB3F51BA6755
*/
这里的补环境在头条案例的jsdom的基础上,又添加了以下几行,基本都是那里报错就补哪里,有的是百度到的,反正就是缺什么补什么,少什么填什么。
self = window;
var HTMLElement = function(){}
var CSSStyleSheet = function(){}
window.customElements = {
define: function(){}
}
接下来就是把上面所有的都串起来,即可实现刷某视频播放的功能。这相比改写js为python要容易得多。