puppeteer填坑指南
前言
原文地址:https://zhangzippo.github.io/posts/2019/04/25/_25puppteererror.html
相信大家在使用puppeteer的時(shí)候會(huì)遇到各種各樣的問(wèn)題,比如原本在mac上跑的好好的卻發(fā)現(xiàn)在centos/docker上遭遇各種各樣的問(wèn)題, 這里把我所遇到的坑跟大家說(shuō)一下。
安裝
首當(dāng)其中就是安裝的問(wèn)題了,這個(gè)在mac上沒(méi)什么問(wèn)題,這里介紹在centos上的問(wèn)題,puppeteer含有兩個(gè)包puppeteer VS puppeteer-core,什么區(qū)別呢?簡(jiǎn)單來(lái)說(shuō)就是puppeteer = api+chromeium(最新),puppeteer-core = only Api,官方是這么說(shuō)的:
puppeteer-core與puppeteer不同的地方:
puppeteer-core在安裝時(shí)不會(huì)自動(dòng)下載 Chromium。puppeteer-core忽略所有的PUPPETEER_*env 變量.
當(dāng)你自己安裝chromeium的時(shí)候,在啟動(dòng)(puppeteer.launch())的時(shí)候需要指定chromeium的啟動(dòng)路徑,當(dāng)然自己安裝存在更新的問(wèn)題,可能由于更新不及時(shí)導(dǎo)致與puppeteer的api不匹配的情況,所以我們推薦直接安裝puppeteer。然后呢,當(dāng)你在centos上安裝的時(shí)候毫無(wú)疑問(wèn)的會(huì)報(bào)錯(cuò)。因?yàn)槿鄙賑hromeium啟動(dòng)的依賴,本人在centos6和7上都遇到了坑,下面是官方列舉的centos上的所需依賴:
pango.x86_64
libXcomposite.x86_64
libXcursor.x86_64
libXdamage.x86_64
libXext.x86_64
libXi.x86_64
libXtst.x86_64
cups-libs.x86_64
libXScrnSaver.x86_64
libXrandr.x86_64
GConf2.x86_64
alsa-lib.x86_64
atk.x86_64
gtk3.x86_64
ipa-gothic-fonts
xorg-x11-fonts-100dpi
xorg-x11-fonts-75dpi
xorg-x11-utils
xorg-x11-fonts-cyrillic
xorg-x11-fonts-Type1
xorg-x11-fonts-misc
只需要一頓 yum install 就好。當(dāng)然事情可能不是這樣的,當(dāng)你啟動(dòng)chromeium時(shí)(推薦在服務(wù)器上測(cè)試的時(shí)候先進(jìn)入到node_modules/puppeteer/.local-chromium/linux-496140/chrome-linux/chrome目錄下執(zhí)行./chrome進(jìn)行測(cè)試,能成功運(yùn)行代表通過(guò)puppeteer的api調(diào)用也能成功)你可能會(huì)遇到例如:
error while loading shared libraries: libpangocairo-1.0.so.0: cannot open shared object file: No such file or directory
這樣的錯(cuò)誤,提示你缺少的是一個(gè)so文件,你可以在執(zhí)行文件目錄下執(zhí)行這個(gè)命令進(jìn)行查看缺少哪些依賴:
ldd chrome | grep not
命令執(zhí)行后會(huì)顯示你當(dāng)前缺少的依賴,當(dāng)你不知道對(duì)應(yīng)的.so在哪個(gè)包中的時(shí)候執(zhí)行這個(gè)命令:
yum provides | grep xx.so.0
找到對(duì)應(yīng)的包進(jìn)行yum install 安裝,注意32還是64位的,不要裝錯(cuò)。當(dāng)ldd chrome | grep not 結(jié)果為空時(shí)代表所有依賴都已經(jīng)安裝,本人在centos6.5上測(cè)試時(shí),安裝了所有依賴依然提示缺少某個(gè)依賴,查了一下,竟然發(fā)現(xiàn)存在于firefox的包中,非常費(fèi)解,https://segmentfault.com/a/1190000015802337
這篇文章的作者與我遇到同樣的問(wèn)題解決了,然而我相同做法后依然沒(méi)有解決,還是無(wú)法啟動(dòng)chrome,而且chrome要依賴別的瀏覽器的包實(shí)在有點(diǎn)兒...后來(lái)google了一下好像是6.5版本對(duì)于chrome的支持有限,遂我換成了centos7.6,繼續(xù),安裝很順利..沒(méi)什么坑。其他可能遇到下載chromium失敗的情況,這個(gè)在.npmrc指定一下下載源
PUPPETEER_DOWNLOAD_HOST = https://npm.taobao.org/mirrors
啟動(dòng)
你以為安裝完就沒(méi)坑了?no,no,no。啟動(dòng)還能坑你一回,如果你直接啟動(dòng)會(huì)報(bào)這個(gè)錯(cuò)誤:
No usable sandbox! Update your kernel or see https://chromium.googlesource.com/chromium/src/+/master/docs/linux_suid_sandbox_development.md for more information on developing with the SUID sandbox. If you want to livedangerously and need an immediate workaround, you can try using --no-sandbox.
啥意思呢?就是你正常應(yīng)該將chrome運(yùn)行在一個(gè)沙盒中,但是你沒(méi)配置,對(duì)應(yīng)的網(wǎng)址和puppeteer的文檔中有寫怎么操作創(chuàng)建沙盒,下面這個(gè):https://github.com/GoogleChrome/puppeteer/blob/master/docs/troubleshooting.md
然而我照著做并不行,還是報(bào)錯(cuò),于是采用planB 加 --no-sandbox,官方的例子是:
const browser = await puppeteer.launch({args: ['--no-sandbox', '--disable-setuid-sandbox']});
我們測(cè)試的時(shí)候可以執(zhí)行 ./chrome --no-sandbox --disable-setuid-sandbox
然后如果你是直接執(zhí)行./chrome (js中的例子默認(rèn)headless=true )你又會(huì)看到這個(gè)錯(cuò)誤:
Gtk-WARNING **: 23:01:03.809: cannot open display
我不太熟悉linux,但這個(gè)意思就是說(shuō)你不能打開(kāi)一個(gè)圖形界面,別去百度了,如果你也是linux小白。我們?cè)诤竺婕由?--headless 就可以了,到此啟動(dòng)也沒(méi)問(wèn)題了。
運(yùn)行puppeteer
啟動(dòng)都沒(méi)問(wèn)題了還有什么坑呢?我這里在使用時(shí)遇到一些問(wèn)題,與大家共勉吧,如果你也遇到的話注意排查問(wèn)題。
- 遇到獲取頁(yè)面錯(cuò)誤的問(wèn)題
這個(gè)當(dāng)然有很多可能了,比如缺少cookie被攔截,這個(gè)好辦,還有一種情況是某些網(wǎng)站存在反爬機(jī)制判斷UA標(biāo)示不是瀏覽器端或者帶headless標(biāo)示(chromeium headless模式默認(rèn)UA會(huì)帶),所以你最終得到的并非想要的頁(yè)面,還有各種被重定向的情況都有可能得不到想要的頁(yè)面,這個(gè)時(shí)候最好在 page = await page.goto(); 之后調(diào)用page.text()方法檢查頁(yè)面是否符合預(yù)期 - timeout情況
這個(gè)大家可能遇到的最多,goto方法加載一個(gè)頁(yè)面默認(rèn)超時(shí)是30秒,你可以更改,也可以直接寫0代表一直等待。我遇到某些情況導(dǎo)致頁(yè)面很慢才加載結(jié)束,尤其是當(dāng)你設(shè)置waitUntil = networkidle0的時(shí)候,怎么排查這個(gè)問(wèn)題呢?使用 page.on('requestfailed')方法看看什么資源阻滯了頁(yè)面跳轉(zhuǎn),page.on('request')方法攔截對(duì)應(yīng)的請(qǐng)求abort()掉,我在應(yīng)用中碰到線下機(jī)器訪問(wèn)不了內(nèi)網(wǎng)域名的情況,苦苦跟了很久。
結(jié)尾
可能后面還會(huì)遇到很多坑,慢慢看吧.....
參考文章:
https://github.com/GoogleChrome/puppeteer/blob/master/docs/troubleshooting.md