js抓取网页内容(浏览器接口通过输入一个网页地址抓取网页中的视频地址)

优采云 发布时间: 2022-01-22 05:01

  js抓取网页内容(浏览器接口通过输入一个网页地址抓取网页中的视频地址)

  项目要求是提供一个接口,通过输入网页地址来抓取网页中的视频地址!例如,打开一个网址

  

  需要提取网页中的视频地址。作为前端开发者的惯性思维,看到这个网页的html结构,这不是很简单,就一行代码:document.querySelector('video source').src

  

  嘻嘻,大功告成,准备钓鱼~

  等等!这只是在浏览器的控制台中获取视频的地址,但是如何转换为提供接口,通过接口返回这个地址呢?初步猜测,使用get request获取网页的html,然后分析dom结构,解析出video标签。

  错误的尝试

  直接通过get请求页面的地址获取的内容并不是我们在浏览器中看到的。目前的网页大多是动态网页,即页面的最终内容是通过加载js后执行脚本来动态拼接的,所以页面中的video标签并不是直接从服务器拼接出来的。

  浏览器请求加载网页的屏幕截图。它不直接返回 DOM 结构,而是加载了一堆 js 和 css 文件。

  

  和!许多网站都采取了反爬虫措施。直接请求页面地址会返回一个中间页面,比如抖音和微博的视频详情页面。直接请求会返回一个类似于认证的页面。分析完这个页面后,应该判断这个传输页面是否有相应的cookie信息。如果没有对应的信息,就会给浏览器设置cookie等信息,最后去一个window.location.reload();让页面刷新一次(微博会直接进入新浪访客系统页面,不会直接跳转到详情页面)。该脚本会在浏览器中自动执行,因此它会重新加载一次以查看最终的详细信息页面。但是get请求只获取到转账页面的html,并没有去到真正的详情页面。

  抖音详情页获取请求

  

  微博详情页获取请求

  :4699424946061376?mid=4699425262272582

  

  哎呀!如果连最终的网页信息都无法获取,那如何获取页面的视频地址呢?我现在不能享受钓鱼的乐趣。

  经过研究,我决定使用 Node.js + Puppeteer 来实现这个功能。本文主要记录项目的实现思路,开发部署中遇到的困难及其解决方法,仅供学习参考。

  Puppeteer 是 Chrome 开发团队 2017 年发布的一个 Node.js 包,用于模拟 Chrome 浏览器的操作。主要通过Puppeteer运行Chromium加载网页分析页面dom获取视频标签,实现视频地址抓取

  参考:

  Puppeteer 中文文档

  开发环境(Windows)

  决定使用puppeteerjs在windows环境下开发后,

  windows环境为Node v12.16.2, puppeteerjs v2.1.1

  puppeteerjs 的最新版本是 13.1.1。但是puppeteerjs v3.0及以上版本需要Node v10及以上,因为我本地开发环境Node是v12,而服务器上的Node是v8,所以本地开发没有问题,但是部署在服务器一直不成功,而且服务器上其他很多项目都是基于node v8版本的,所以服务器上的node版本不应该升级。为了和服务器版本保持一致,windows环境下的puppeteerjs也使用2.1.1版本;

  直接编码

  服务器2.js

  const puppeteer = require('puppeteer');

async function getVideoUrl () {

const browser = await puppeteer.launch();// 打开浏览器

const page = await browser.newPage();

await page.emulate(puppeteer.devices['iPhone 6'])

await page.goto('https://www.douyin.com/video/7020764246476590339'); // 跳转到指定页面

await page.waitFor(2000) // 延时2s加载页面 puppeteer2.1.1使用 waitFor ^13.0.1以上使用 waitForTimeout

const pageHtml = await page.content(); // 获取页面html Gets the full HTML contents of the page, including the doctype.

console.log(pageHtml);

}

getVideoUrl()

  执行node server2.js,输出结果为详情页的html代码

  

  puppeteer.launch 中的 headless 默认为 true。如果设置为false,会打开一个Chromium加载网页,可以直接调试网页!

  await puppeteer.launch({

headless: false, // 是否无头浏览

});

  

  得到html代码后,如何进一步得到video标签呢?

  使用dom直接分析视频标签

  puppeteer为我们提供了相应的api,因为浏览器渲染dom和请求接口需要时间,因为我们第一时间拿到的网页的代码不完整,所以需要加一个延迟。

  await page.waitForTimeout(2000); // 延时2s加载页面 puppeteer2.1.1使用 waitFor ^13.0.1以上使用 waitForTimeout

const videoSrc = await page.$eval('video source', (el) => {

let src = '';

if (el && el.src) {

src = el.src;

}

return src;

});

  拦截接口

  有些页面是直接通过请求接口获取的视频地址。对于这种网页,我们可以使用上面的方法来分析页面加载后的DOM。但是在查看puppeteer的文档时,我们发现可以直接拦截接口,获取接口的返回信息。

  因此,如果我们知道指定细节的请求规则,就可以直接通过接口响应获取相应的数据。

  // 注册响应*敏*感*词*事件

page.on('response', async (response) => {

if (response.ok()) {

const request = response.request();

const reqUrl = request.url();

if (reqUrl.indexOf('/api/getHttpVideoInfo.do') > -1) { // 拦截 /api/getHttpVideoInfo.do 接口

const respData = await response.json();

const video = respData.video;

if (video && video.validChapterNum > 0){

const currentChapter = video[`chapters${video.validChapterNum}`];

if (currentChapter && currentChapter.length > 0 && currentChapter[0] && currentChapter[0].url) {

resolve(currentChapter[0].url)

}

}

}

}

})

  这种方式是指使用界面清晰,可以获取相应请求参数的页面!

  增加前端页面,改善界面

  完整代码已经提交到github,后面给出链接

  打开本地网页访问:localhost:18000

  

  服务器部署 (Linux)

  服务器环境为linux环境,系统为CentOS-8,Node.js版本为v8.11.3。Linux环境和windows环境有一些区别,尤其是安装puppeteer的时候需要注意

  安装puppeteer时会报如下错误

  ERROR: Failed to download Chromium r722234! Set "PUPPETEER_SKIP_CHROMIUM_DOWNLOAD" env variable to skip download.

Error: EACCES: permission denied, mkdir '/opt/video-url-analysis/node_modules/puppeteer/.local-chromium'

  

  因为在安装puppeteer的时候就安装了Chromium,需要权限,所以在linux环境下使用如下命令安装

  npm install puppeteer@2.1.1 --unsafe-perm=true --allow-root

  安装完成后,启动程序,运行成功,抓取网页视频!

  其他

  linux下无头启动浏览器需要设置为true并添加args参数

  const browser = await puppeteer.launch({

headless: true, // 是否启用无头浏览 默认为true

args: [

'--no-sandbox',

'--disable-setuid-sandbox'

]

});

  其他异常错误:

  1.启动浏览器进程失败

  Failed to launch the browser process

...

error while loading shared libraries: libXss.so.1: cannot open shared object file: No such file or directory

  应该是系统缺少一些库或者组件(我这里使用命令后解决了这个问题)

  sudo yum -y install libXScrnSaver-1.2.2-6.1.el7.x86_64

  或者直接重装chromium,手动安装chromium后解决问题

  sudo yum install -y chromium

  2.yum安装软件依赖出错,一直提示找不到软件包

  [root@localhost video-url-analysis]# sudo yum install -y chromium

上次元数据过期检查:0:00:47 前,执行于 2022年01月20日 星期四 21时35分27秒。

未找到匹配的参数: chromium

错误:没有任何匹配: chromium

  原因是CentOS 8没有安装epel源。安装epel源后问题解决:

  yum install epel-release

  代码

  完整代码已上传至欢迎star,仅供学习参考,请勿用于非法用途

  1.安装依赖

  npm install

  2.本地开发

  npm run dev

  打开本地网页访问:localhost:18000

  总结

  windows环境下的开发比较顺利。由于本人是前端切图师,与服务器接触较少,所以在Linux服务器的部署中遇到了很多问题。所以我将解决问题的过程记录下来,方便后续开发者顺利解决问题。.

  服务器端缺乏相关知识。如有不足,还请海涵!

0 个评论

要回复文章请先登录注册


官方客服QQ群

微信人工客服

QQ人工客服


线