Gözetimsiz Chrome, Windows'da başlatılmıyor
Bazı Chrome politikaları, Chrome'un veya Chromium'un belirli Uzantılarla çalışmasını zorunlu kılabilir.
Puppeteer varsayılan olarak --disable-extensions
işaretini iletir ve bu nedenle, bu tür politikalar etkin olduğunda başlatılamaz.
Bu sorunu çözmek için bayrak olmadan koşmayı deneyin:
const browser = await puppeteer.launch({
ignoreDefaultArgs: ['--disable-extensions'],
});
İçerik: issue 3681.
Gözetimsiz Chrome UNIX'te başlatılmıyor
Gerekli tüm bağımlılıkların yüklendiğinden emin olun. Hangi bağımlılıkların eksik olduğunu kontrol etmek için ldd chrome | grep not
uygulamasını bir Linux makinesinde çalıştırabilirsiniz.
Debian (Ubuntu) bağımlılıkları
ca-certificates
fonts-liberation
libappindicator3-1
libasound2
libatk-bridge2.0-0
libatk1.0-0
libc6
libcairo2
libcups2
libdbus-1-3
libexpat1
libfontconfig1
libgbm1
libgcc1
libglib2.0-0
libgtk-3-0
libnspr4
libnss3
libpango-1.0-0
libpangocairo-1.0-0
libstdc++6
libx11-6
libx11-xcb1
libxcb1
libxcomposite1
libxcursor1
libxdamage1
libxext6
libxfixes3
libxi6
libxrandr2
libxrender1
libxss1
libxtst6
lsb-release
wget
xdg-utils
CentOS Bağımlılıkları
alsa-lib.x86_64
atk.x86_64
cups-libs.x86_64
gtk3.x86_64
ipa-gothic-fonts
libXcomposite.x86_64
libXcursor.x86_64
libXdamage.x86_64
libXext.x86_64
libXi.x86_64
libXrandr.x86_64
libXScrnSaver.x86_64
libXtst.x86_64
pango.x86_64
xorg-x11-fonts-100dpi
xorg-x11-fonts-75dpi
xorg-x11-fonts-cyrillic
xorg-x11-fonts-misc
xorg-x11-fonts-Type1
xorg-x11-utils
Bağımlılıkları yükledikten sonra bu komutu kullanarak nss kitaplığını güncellemeniz gerekir
yum update nss -y
Tartışmalara göz atın:
- #290 - Debian sorun giderme
- #391 - CentOS ile ilgili sorunları giderme
- #379 - Alpler'de sorun giderme
Gözetimsiz Chrome, GPU birleştirmeyi devre dışı bırakır
Chrome ve Chromium, gözetimsiz modda GPU hızlandırmayı etkinleştirmek için --use-gl=egl
eklentisini gerektirir.
const browser = await puppeteer.launch({
headless: true,
args: ['--use-gl=egl'],
});
Chrome indirildi ancak Node.js'de başlatılamıyor
Chromium'u başlatmaya çalışırken aşağıdakine benzer bir hata alırsanız:
(node:15505) UnhandledPromiseRejectionWarning: Error: Failed to launch the browser process!
spawn /Users/.../node_modules/puppeteer/.local-chromium/mac-756035/chrome-mac/Chromium.app/Contents/MacOS/Chromium ENOENT
Bu, tarayıcının indirildiği ancak düzgün şekilde çıkartılamadığı anlamına gelir.
Bunun en yaygın nedeni Node.js v14.0.0'da extract-zip
bozan bir hatadır. Puppeteer modülünün tarayıcı indirmelerini doğru yere çıkarmak için kullandığı bir modül. Hata, Node.js v14.1.0'da düzeltildi. Bu nedenle, söz konusu sürümü veya daha üstünü kullandığınızdan emin olun.
Chrome Linux korumalı alanı oluşturma
Chrome, ana makine ortamını güvenilir olmayan web içeriğinden korumak için birden fazla korumalı alan katmanı kullanır.
Bunun düzgün bir şekilde çalışması için öncelikle ana makinenin yapılandırılması gerekir. Chrome'un kullanabileceği iyi bir korumalı alan yoksa No usable sandbox!
hatasıyla kilitlenir.
Chrome'da açtığınız içeriğe kesinlikle güveniyorsanız Chrome'u --no-sandbox
bağımsız değişkeniyle başlatabilirsiniz:
const browser = await puppeteer.launch({
args: ['--no-sandbox', '--disable-setuid-sandbox'],
});
Chromium'da korumalı alanı yapılandırmanın 2 yolu vardır.
[önerilir] Kullanıcı ad alanı klonlamayı etkinleştirin
Sser ad alanı klonlama yalnızca modern çekirdekler tarafından desteklenir. Ayrıcalığa sahip olmayan kullanıcı ad alanları genellikle etkinleştirilebilir ancak çekirdek ayrıcalıklarını yükseltmek amacıyla kök olmayan (korumalı olmayan) işlemler için daha fazla çekirdek saldırı yüzeyi açabilir.
sudo sysctl -w kernel.unprivileged_userns_clone=1
[alternatif] Setuid korumalı alanı kurulumu
setuid korumalı alanı bağımsız bir yürütülebilir dosya olarak gelir ve Kuklacı'nın indirdiği Chromium'un yanında bulunur. Aynı korumalı korumalı alanı farklı Chromium sürümleri için yeniden kullanabilirsiniz. Bu nedenle aşağıdaki işlemler ana makine ortamı başına yalnızca bir kez yapılabilir:
# cd to the downloaded instance
cd <project-dir-path>/node_modules/puppeteer/.local-chromium/linux-<revision>/chrome-linux/
sudo chown root:root chrome_sandbox
sudo chmod 4755 chrome_sandbox
# copy sandbox executable to a shared location
sudo cp -p chrome_sandbox /usr/local/sbin/chrome-devel-sandbox
# export CHROME_DEVEL_SANDBOX env variable
export CHROME_DEVEL_SANDBOX=/usr/local/sbin/chrome-devel-sandbox
Varsayılan olarak CHROME_DEVEL_SANDBOX
env değişkenini dışa aktarmak isteyebilirsiniz. Bu durumda, aşağıdaki kodu ~/.bashrc
veya .zshenv
öğesine ekleyin:
export CHROME_DEVEL_SANDBOX=/usr/local/sbin/chrome-devel-sandbox
Travis CI'da Puppeteer'ı Çalıştır
Puppeteer için Travis CI'da 6.0.0 sürümüne kadar testler yaptık ve sonrasında GitHub Actions'a geçiş yaptık. Referans için .travis.yml
(v5.5.0) sayfasını inceleyebilirsiniz.
Aşağıda bazı en iyi uygulamaları görebilirsiniz:
- Chromium'u gözetimsiz modda çalıştırmak için xvfb hizmeti başlatılmalıdır
- Varsayılan olarak Travis üzerindeki Xenial Linux'ta çalışır
- Varsayılan olarak
npm install
çalışır node_modules
varsayılan olarak önbelleğe alınır
.travis.yml
şöyle görünebilir:
language: node_js
node_js: node
services: xvfb
script:
- npm run test
CircleCI'da Puppeteer'ı Çalıştır
- Yapılandırmanıza bir NodeJS görüntüsü ekleyerek başlayın.
yaml docker: - image: circleci/node:14 # Use your desired version environment: NODE_ENV: development # Only needed if puppeteer is in `devDependencies`
libXtst6
gibi bağımlılıkların muhtemelenapt-get
ile yüklenmesi gerekir. Bu nedenle threetreeslight/puppeteer orb'u (instructions) kullanın veya kaynağının parçalarını kendi yapılandırmanıza yapıştırın.- Son olarak, Jest üzerinden Puppeteer kullanıyorsanız alt işlemlerde hata oluşmasıyla karşılaşabilirsiniz:
shell [00:00.0] jest args: --e2e --spec --max-workers=36 Error: spawn ENOMEM at ChildProcess.spawn (internal/child_process.js:394:11)
Bu durum büyük olasılıkla Jest'in container'ınıza (2
) izin verilen sayı yerine makinenin tamamındaki (36
) işlem sayısını otomatik olarak algılamasından kaynaklanmaktadır. Bunu düzeltmek için test komutunuzdajest --maxWorkers=2
değerini ayarlayın.
Docker'da Puppeteer'ı Çalıştır
Gözetimsiz Chrome'u Docker'da çalışır duruma getirmek zor olabilir. Puppeteer'ın yüklediği paket halinde sunulan Chromium'da gerekli paylaşılan kitaplık bağımlılıkları yok.
Düzeltmek için eksik bağımlılıkları ve en son Chromium paketini Dockerfile dosyanıza yüklemeniz gerekir:
FROM node:14-slim
# Install latest chrome dev package and fonts to support major charsets (Chinese, Japanese, Arabic, Hebrew, Thai and a few others)
# Note: this installs the necessary libs to make the bundled version of Chromium that Puppeteer
# installs, work.
RUN apt-get update \
&& apt-get install -y wget gnupg \
&& wget -q -O - https://dl-ssl.google.com/linux/linux_signing_key.pub | apt-key add - \
&& sh -c 'echo "deb [arch=amd64] http://dl.google.com/linux/chrome/deb/ stable main" >> /etc/apt/sources.list.d/google.list' \
&& apt-get update \
&& apt-get install -y google-chrome-stable fonts-ipafont-gothic fonts-wqy-zenhei fonts-thai-tlwg fonts-kacst fonts-freefont-ttf libxss1 \
--no-install-recommends \
&& rm -rf /var/lib/apt/lists/*
# If running Docker >= 1.13.0 use docker run's --init arg to reap zombie processes, otherwise
# uncomment the following lines to have `dumb-init` as PID 1
# ADD https://github.com/Yelp/dumb-init/releases/download/v1.2.2/dumb-init_1.2.2_x86_64 /usr/local/bin/dumb-init
# RUN chmod +x /usr/local/bin/dumb-init
# ENTRYPOINT ["dumb-init", "--"]
# Uncomment to skip the chromium download when installing puppeteer. If you do,
# you'll need to launch puppeteer with:
# browser.launch({executablePath: 'google-chrome-stable'})
# ENV PUPPETEER_SKIP_CHROMIUM_DOWNLOAD true
# Install puppeteer so it's available in the container.
RUN npm init -y && \
npm i puppeteer \
# Add user so we don't need --no-sandbox.
# same layer as npm install to keep re-chowned files from using up several hundred MBs more space
&& groupadd -r pptruser && useradd -r -g pptruser -G audio,video pptruser \
&& mkdir -p /home/pptruser/Downloads \
&& chown -R pptruser:pptruser /home/pptruser \
&& chown -R pptruser:pptruser /node_modules \
&& chown -R pptruser:pptruser /package.json \
&& chown -R pptruser:pptruser /package-lock.json
# Run everything after as non-privileged user.
USER pptruser
CMD ["google-chrome-stable"]
Kapsayıcıyı oluşturun:
docker build -t puppeteer-chrome-linux .
node -e "<yourscript.js content as a string>"
komutunu komut olarak geçirerek kapsayıcıyı çalıştırın:
docker run -i --init --rm --cap-add=SYS_ADMIN \
--name puppeteer-chrome puppeteer-chrome-linux \
node -e "`cat yourscript.js`"
Bu Dockerfile'ın App Engine Flex (Node) üzerinde çalışan bir web sunucusundan nasıl çalıştırılacağını gösteren tam bir örneği https://github.com/ebidel/try-puppeteer adresinde bulabilirsiniz.
Alpler'de koş
Alpine'de desteklenen en yeni Chromium paketi 100'dür ve bu paket, Puppeteer v13.5.0'a karşılık gelir.
Örnek Dockerfile:
FROM alpine
# Installs latest Chromium (100) package.
RUN apk add --no-cache \
chromium \
nss \
freetype \
harfbuzz \
ca-certificates \
ttf-freefont \
nodejs \
yarn
...
# Tell Puppeteer to skip installing Chrome. We'll be using the installed package.
ENV PUPPETEER_SKIP_CHROMIUM_DOWNLOAD=true \
PUPPETEER_EXECUTABLE_PATH=/usr/bin/chromium-browser
# Puppeteer v13.5.0 works with Chromium 100.
RUN yarn add puppeteer@13.5.0
# Add user so we don't need --no-sandbox.
RUN addgroup -S pptruser && adduser -S -G pptruser pptruser \
&& mkdir -p /home/pptruser/Downloads /app \
&& chown -R pptruser:pptruser /home/pptruser \
&& chown -R pptruser:pptruser /app
# Run everything after as non-privileged user.
USER pptruser
...
Docker ile ilgili en iyi uygulamalar
Varsayılan olarak Docker, 64 MB boyutunda /dev/shm
paylaşılan bellek alanına sahip bir container çalıştırır.
Bu boyut, Chrome için genellikle çok küçük olup büyük sayfalar oluşturulurken Chrome'un kilitlenmesine neden olur. Bu sorunu düzeltmek için kapsayıcıyı docker run --shm-size=1gb
ile çalıştırarak /dev/shm
boyutunu artırın. Chrome 65'ten itibaren buna gerek yoktur. Bunun yerine, tarayıcıyı --disable-dev-shm-usage
işaretiyle başlatın:
const browser = await puppeteer.launch({
args: ['--disable-dev-shm-usage'],
});
Bu işlem, paylaşılan anı dosyalarını /dev/shm
yerine /tmp
dosyasına yazar. crbug.com/736452 adresini inceleyin.
Chrome'u başlatırken başka tuhaf hatalarla karşılaşıyor musunuz? Yerel olarak geliştirme yaparken container'ınızı docker run --cap-add=SYS_ADMIN
ile çalıştırmayı deneyin. Dockerfile bir pptr
kullanıcısını ayrıcalıklı olmayan kullanıcı olarak eklediğinden gerekli tüm ayrıcalıklara sahip olmayabilir.
dumb-init ifadesi, sürekli olarak çok sayıda zombi
ile karşılaşıp karşılaşmadığınızı kontrol etmenizi sağlar. PID=1
ile yapılan işlemlerde özel işlemler vardır. Bu da bazı durumlarda (örneğin Docker'da) Chrome'un doğru şekilde sonlandırılmasını zorlaştırır.
Puppeteer'ı bulutta çalıştırın
Google App Engine'de
App Engine standart ortamının Node.js çalışma zamanı, gözetimsiz Chrome'u çalıştırmak için gereken tüm sistem paketleriyle birlikte gelir.
puppeteer
kullanmak için modülü package.json
dosyanızda bağımlılık olarak listeleyin ve Google App Engine'e dağıtın. Resmi eğiticiyi izleyerek puppeteer
App Engine'de kullanma hakkında daha fazla bilgi edinin.
Google Cloud Functions'da
Google Cloud Functions'ın Node.js 10 çalışma zamanı, gözetimsiz Chrome'u çalıştırmak için gereken tüm sistem paketleriyle birlikte gelir.
puppeteer
kullanmak için modülü package.json
dosyanızda bağımlılık olarak listeleyin ve nodejs10
çalışma zamanını kullanarak işlevinizi Google Cloud Functions'a dağıtın.
Google Cloud Run'da Puppeteer'ı Çalıştır
Google Cloud Run'ın varsayılan Node.js çalışma zamanı, gözetimsiz Chrome'u çalıştırmak için gereken sistem paketleriyle birlikte verilmez. Kendi Dockerfile
öğenizi kurun ve eksik bağımlılıkları ekleyin.
Heroku'da
Heroku'da Puppeteer'ı çalıştırmak, Heroku'nun sizin için hazırladığı Linux kutusunda bulunmayan bazı ek bağımlılıklar gerektirir. Dağıtım sırasında bağımlılıkları eklemek için Puppeteer Heroku derleme paketini, Ayarlar > Derleme Paketleri altında uygulamanızın derleme paketleri listesine ekleyin.
Derleme paketinin URL'si: https://github.com/jontewks/puppeteer-heroku-buildpack
Puppeteer'ı başlatırken '--no-sandbox'
modunu kullandığınızdan emin olun. Bu işlem, .launch()
çağrınıza bağımsız değişken olarak iletilerek yapılabilir: puppeteer.launch({ args: ['--no-sandbox'] });
.
Buildpack'i ekle'yi tıkladığınızda URL'yi girişe yapıştırın ve Kaydet'i tıklayın. Bir sonraki dağıtımda uygulamanız, Puppeteer'ın çalıştırması gereken bağımlılıkları da yükler.
Çince, Japonca veya Korece karakterler oluşturmanız gerekiyorsa https://github.com/CoffeeAndCode/puppeteer-heroku-buildpack gibi ek yazı tipi dosyaları içeren bir derleme paketi kullanmanız gerekebilir
Ayrıca örnek bir proje içeren başka bir @timleland rehberi daha var.
AWS Lambda'da
AWS Lambda, dağıtım paketi boyutlarını yaklaşık 50 MB ile sınırlar. Bu durum, Chrome'u (ve dolayısıyla Puppeteer'ı) Lambda'da gözetimsiz çalıştırmanın zorluğunu da beraberinde getirir. Topluluk, bu sorunlara çözüm bulmak için birkaç kaynak bir araya getirdi:
- AWS Lambda ve Google Cloud Functions için Chromium Binary (Puppeteer'ın en son kararlı sürümüyle güncellenir)
- Marco Lüthy tarafından sağlanan AWS Lambda'da Chrome/Chromium sunucusuz bir eklentidir ve eskidir.
Amazon-Linux çalıştıran AWS EC2 örneği
CI/CD ardışık düzeninizde amazon-linux çalıştıran bir EC2 örneğiniz varsa ve amazon-linux'da Puppeteer testlerini çalıştırmak istiyorsanız aşağıdaki adımları uygulayın.
Chromium'u yüklemek için önce EPEL (Enterprise Linux İçin Ek Paketler) kapsamında olan
amazon-linux-extras
özelliğini etkinleştirmeniz gerekir:sudo amazon-linux-extras install epel -y
Ardından Chromium'u yükleyin:
sudo yum install -y chromium
Puppeteer artık testlerinizi çalıştırmak için Chromium'u başlatabilir. EPEL'i etkinleştirmez ve Chromium'u npm install
kapsamında yüklemeye devam ederseniz Puppeteer, libatk-1.0.so.0
ve daha birçok paketin kullanılamaması nedeniyle Chromium'u başlatamaz.
Kod çevirme sorunları
Babe veya TypeScript gibi bir JavaScript aktarıcı kullanıyorsanız eşzamansız işlevle evaluate()
çağrısı yapılamayabilir. Çünkü puppeteer
, işlevleri serileştirmek için Function.prototype.toString()
kullanırken aktarıcılar çıkış kodunu puppeteer
ile uyumsuz bir şekilde değiştirebilir.
Bu sorunu çözmek için uygulanabilecek bazı geçici çözümler, aktarıcıya kodu karıştırmamasını söylemek olabilir. Örneğin, TypeScript'i en son ecma sürümünü ("target": "es2018"
) kullanacak şekilde yapılandırabilirsiniz.
await page.evaluate(`(async() => {
console.log('1');
})()`);