当前位置: 首页 > 后端技术 > Node.js

Node.js使用puppeteerjs提取网页中的视频地址

时间:2023-04-03 17:11:45 Node.js

项目需求是提供一个接口,通过输入一个网页地址来抓取网页中的视频地址!比如打开一个网页地址,需要提取网页中的视频地址。作为一个前端开发者的惯性思维,看到这个网页的html结构,是不是很简单,一行代码:document.querySelector('videosource').src嘻嘻,大功告成,准备好了钓鱼~等等!这只是为了在浏览器的控制台中获取视频的地址,但是如何将其转换为提供接口并通过接口返回这个地址呢?初步猜测,使用get请求获取网页的html,然后解析dom结构,解析出video标签。直接通过get请求页面的地址错误尝试获取到的内容并不是我们在浏览器中看到的。现在的网页大多是动态网页,即加载js后通过执行脚本动态拼接页面最终内容,所以页面中的video标签并不是直接从服务器拼接的。浏览器请求加载网页的截图并没有直接返回dom结构,而是加载了一堆js和css文件和!许多网站都实施了反爬虫措施。直接请求页面地址会返回一个中间页面,比如抖音和微博的视频详情页。直接请求会返回一个类似于认证的页面。初步分析这个页面,这个传输页面应该是判断是否有对应的cookie信息。如果没有对应的信息,就会给浏览器设置cookie等信息,最后取一个window.location.reload();刷新一次页面(微博会直接进入新浪访客系统页面,不会直接跳转到详情页面)。这个脚本是在浏览器中自动执行的,所以会重新加载一次才能看到最终的详情页。但是get请求只是获取了中转页面的html,并没有去到真正的详情页面。详情页获取请求https://www.douyin.com/video/7020764246476590339微博详情页获取请求https://weibo.com/tv/show/1034:4699424946061376?mid=4699425262272582糟糕!连最终的网页信息都拿不到,怎么可能拿到页面的视频地址呢?现在我不能快乐地钓鱼。经过研究,我决定使用Node.js+Puppeteer来实现这个功能。本文主要记录项目的实现思路,开发部署过程中遇到的困难及解决方法,仅供学习参考。Puppeteer是Chrome开发团队在2017年发布的一个Node.js包,用于模拟Chrome浏览器的运行。主要使用Puppeteer运行Chromium加载网页分析页面dom获取视频标签,抓取视频url。参考:Puppeteer中文文档https://github.com/puppeteer/puppeteer开发环境(Windows)决定在windows环境下使用puppeteerjs开发。windows环境是Nodev12.16.2,puppeteerjsv2.1.1puppeteerjs最新版本是13.1.1。但是puppeteerjsv3.0及以上版本需要Nodev10及以上版本,因为我本地的开发环境Node是v12,而服务器上的Node是v8,所以本地开发没问题,但是在服务器上一直部署不成功,还有服务器上很多其他项目都是基于nodev8版本的,所以服务器上的node版本应该不会升级。为了与服务器版本保持一致,windows环境下的puppeteerjs也使用2.1.1版本;直接上传代码server2.jsconstpuppeteer=require('puppeteer');asyncfunctiongetVideoUrl(){constbrowser=awaitpuppeteer.launch();//打开浏览器constpage=awaitbrowser.newPage();awaitpage.emulate(puppeteer.devices['iPhone6'])awaitpage.goto('https://www.douyin.com/video/7020764246476590339');//跳转到指定页面awaitpage.waitFor(2000)//延迟2s加载页面puppeteer2.1.1usewaitFor^13.0.1及以上使用waitForTimeoutconstpageHtml=awaitpage.content();//获取页面html获取页面的完整HTML内容,包括文档类型。console.log(pageHtml);}getVideoUrl()执行nodeserver2.js,输出结果为详情页的html代码。puppeteer.launch中headless默认为true,如果设置为false,会打开一个Chromium加载网页,可以直接调试网页!awaitpuppeteer.launch({headless:false,//无头浏览});获取到html代码后如何进一步获取video标签呢?直接使用dom解析video标签puppeteer给我们提供了相应的api,因为浏览器渲染dom和请求接口需要时间,因为第一次获取网页代码不完整,所以需要添加延迟。等待页面.waitForTimeout(2000);//延迟2s加载页面puppeteer2.1.1使用waitFor^13.0.1及更高版本使用waitForTimeoutconstvideoSrc=awaitpage.$eval('videosource',(el)=>{letsrc='';if(el&&el.src){src=el.src;}返回src;});拦截界面部分页面是通过请求界面直接获取的视频地址。对于这种网页,我们可以使用上面的方法,在页面加载后解析dom,但是在查阅puppeteer文档的时候发现可以直接截取接口,获取接口的返回信息。因此,如果我们知道指定详情的请求规则,就可以直接通过接口response获取相应的数据。//注册响应监听器事件page.on('response',async(response)=>{if(response.ok()){constrequest=response.request();constreqUrl=request.url();if(reqUrl.indexOf('/api/getHttpVideoInfo.do')>-1){//拦截/api/getHttpVideoInfo.do接口constrespData=awaitresponse.json();constvideo=respData.video;if(video&&video.validChapterNum>0){constcurrentChapter=video[`chapters${video.validChapterNum}`];if(currentChapter&¤tChapter.length>0&¤tChapter[0]&¤tChapter[0].url){resolve(currentChapter[0]].url)}}}}})该方法针对界面清晰的页面,可以获取相应的请求参数!添加前端页面,完善界面。完整代码已经提交到github,后面给出链接。打开本地网页访问:localhost:18000服务器部署(Linux)服务器环境为Linux环境,系统为CentOS-8,Node.js版本为V8.11.3,部署时Linux环境和windows环境略有不同,特别是安装puppeteer的时候需要注意下面的错误ERROR:Failedtodownwheninstallingpuppeteer加载Chromiumr722234!设置“PUPPETEER_SKIP_CHROMIUM_DOWNLOAD”环境变量以跳过下载。错误:EACCES:权限被拒绝,mkdir'/opt/video-url-analysis/node_modules/puppeteer/.local-chromium'因为安装puppeteer时会安装Chromium,它需要权限,所以在linux环境下使用如下命令安装npminstallpuppeteer@2.1.1--unsafe-perm=true--allow-root。安装完成后,启动程序,运行成功,抓取网页视频!其他linux下启动浏览器,headless需要设置为true,添加args参数constbrowser=awaitpuppeteer.launch({headless:true,//是否开启headless浏览,默认为trueargs:['--no-sandbox','--disable-setuid-sandbox']});其他异常错误:1.FailedtolaunchthebrowserprocessFailedtolaunchthebrowserprocess...errorwhileloadingsharedlibraries:libXss.so.1:cannotopensharedobjectfile:Nosuchfileordirectory应该是系统缺少一些库或组件(我用这里的命令解决了这个问题)sudoyum-yinstalllibXScrnSaver-1.2.2-6.1.el7.x86_64或者直接重新安装chromium,手动安装chromiumsudoyuminstall-ychromium2后解决问题。使用yum安装软件依赖报错,一直提示找不到包[root@localhostvideo-url-analysis]#sudoyuminstall-ychromiumlastmetadataexpirationcheck:0:00:47ago,executedonThursday,January20,202221:35:27Nomatchingparametersfound:chromiumError:Nomatch:chromium原因是CentOS8上没有安装epel的源的问题,安装epel源后问题解决:yuminstallepel-releasecode完整代码已经上传https://github.com/zhaosheng808/video-grab欢迎star,仅供学习参考,请勿以非法方式使用1.安装依赖npminstall2。本地开发npmrundev打开本地网页访问:localhost:18000总结在windows环境下开发还是比较顺利的。由于本人是前端切图,接触服务器较少,所以在部署linux服务器的过程中遇到了很多问题,所以把解决问题的过程记录下来,方便后续开发者顺利解决问题。服务端知识欠缺,如有不足,敬请见谅!