RaspberryPi4でpuppeteerを使おうとしたら躓いた。
2020/03/28更新
2020-02-13にbusterが更新されましたね。
改めて「ラズパイ4(buster)+Node-RED+puppeteer」が使用できるか確認してみると、
エラー無く動きました!!!
- OS
- Raspbian Buster Lite
- Version:February 2020
- Release date:2020-02-13
- Kernel version:4.19
- Node.js
- 12.16.1
- npm
- 6.14.4
- Node-RED
- 1.0.4
- puppeteer
- 1.20.0
- chromium
- 78.0.3904.108
下記は一応備忘録として残しておきます。
はじめに
Qiita初投稿です。
記事作成のきっかけ
最近RaspberryPi4を購入し、RaspberryPi3B+で行っていたスクレイピングを移行した際、
ハマりましたので、同じ悩みを持つ人に共有出来ればと思い、投稿させて頂きました。
やりたい事
- RaspberryPi4
- Node-RED
- puppeteer
- puppeteer
とにかく上記を用いてスクレイピングを行う環境を構築する。
ハマったこと
https://www.raspberrypi.org/downloads/raspbian/
⇒ Raspbian Buster with desktop
⇒ Kernel version : 4.19
上記OSを用いて、puppeteerを実行出来ない。
※厳密には実行できるが、意図しない挙動をする。
Raspbian Busterで行える方法があれば、申し訳ありません。
そしてエラーログが残ってないのでログを載せられない。
問題の推測
- RaspberryPi3B+ stretch
- RaspberryPiZero stretch
上記の所持しているラズパイでは問題が起きたことが無かったため、Raspbian Busterからの影響度が大きいと決め打ち。
- nodejs
- chromium-browser
- puppeteerなど
上記のバージョンによる影響も大きいかもしれないが、一旦保留とし、OSを変更する作業へ移行する。
結論
そもそもRaspbian Busterが原因なのか分かりませんでしたが、
OSをRaspbian BusterからUbuntu Server19.10.1へ変更したことで、
RaspberryPi4でもpuppeteerが使えました!
下記では、その手順及び注意点を書いていきます。
1.OSの選択
Ubuntu Server 19.10からRaspberryPi4に対応した模様。
ひとまずこれを試します。
https://ubuntu.com/download/raspberry-pi
上記からubuntu-19.10.1-preinstalled-server-arm64+raspi3.img.xzをダウンロードします。
※もし、2019/12/9以前にダウンロードしたイメージがある場合、ダウンロードし直して下さい。
USBポートが使用できない重大な不具合が含まれています。
インストール作業については割愛させて頂きます。
下記URLを参考にして下さい。
https://qiita.com/NeK/items/849c6d1e05fb05314fc6
初期設定が終わり次第次へ
2.chromium-browserインストール
なんと、chromiumはubuntu19.10以降、aptでインストール行なえないみたいです。
snapコマンドを用いてインストールします。
# インストールを行なえるchromiumのバージョン確認
snap info chromium
# chromiumのインストール(stable)
snap install chromium
# インストール場所の確認(puppeteerで使用する)
which chromium
3.Node-REDインストール
https://nodered.jp/docs/getting-started/raspberrypi
公式に記載されているコードを脳死で実行します。
# npmがインストールする必要のあるバイナリコンポーネントをビルドできることを保証するため、build-essentialをインストール
sudo apt-get install build-essential
# Node-REDをインストール
bash <(curl -sL https://raw.githubusercontent.com/node-red/linux-installers/master/deb/update-nodejs-and-nodered)
# ラズパイ起動時に自動起動させる
sudo systemctl enable nodered.service
# 起動の確認
node-red
4.puppeteerインストール
https://pptr.dev/
公式ページの左上、バージョン部分をクリックするとpuppeteerの各バージョンがどのバージョンのChromiumに対応しているか見られます。
# カレントディレクトリの移動
cd ~/.node-red
# 私はchromium 79.0.3945.79 でしたが
# 今回はv1.20.0をインストール
sudo apt install [email protected]
上記でpuppeteerではなく、puppeteer-coreをインストールしているのは、
puppeteerではデフォルトでx86アーキテクチャ用のchromiumが勝手にインストールされる為、puppeteer-coreでインストールしています。
# Node-REDでpuppetter-coreを使用する為に、グローバル変数にpuppeteerを追加
nano ~/.node-red/settings.js
functionGlobalContext: {
puppeteer:require('puppeteer-core')
// os:require('os'),
// jfive:require("johnny-five"),
// j5board:require("johnny-five").Board({repl:false})
},
保存後はNode-REDの再起動を行って設定を反映させましょう。
5.Node-REDでpuppeteer実行
ようやくここまで来ました。
お疲れ様でした。
Node-REDのフローの作成方法などは割愛しますが、
おまけとして、スクレイピングのサンプルを示しておきます。
動かなくても怒らないでください...
たぶん、動かないときはセレクターのところを変えたら動きます。
サンプル内容
①googleに接続
②Node-REDと検索
③最上部のページへアクセス(Node-REDの公式ページを想定)
⇒ 上手く動かない時があるかもしれません...
④現在のNode-REDの最新バージョンを取得
下記、functionノードの中身を記載。
特に重要な部分(?)は★で囲ってます。
// ★グローバル変数の呼び出し★
var puppeteer = new global.get('puppeteer');
// URL指定
var url = "https://www.google.com/";
(async () => {
const browser = await puppeteer.launch({
// ★snapでインストールしたchromiumの場所★
executablePath: '/snap/bin/chromium',
headless: true
});
try {
const page = await browser.newPage()
await page.setViewport({width: 1200, height: 800})
// chromeを開く
await page.goto(url,{waitUntil: "networkidle2"}) // ページへ移動
// 検索窓に入力
await page.type('input[name=q]', 'node-red',{ delay: 5 } )
// 検索
await Promise.all([
page.waitForNavigation({waitUntil: "networkidle2"}),
await page.evaluate(() => {
document.querySelector('input[value^="Google"]').click();
})
]);
// var result = await page.evaluate(() => document.querySelector(`#rso > div > div > div:nth-child(1) > div > div > div.r > a > h3 > span`).textContent.trim())
var result = await page.evaluate(() => document.querySelector(`#rso > div > div > div:nth-child(1) > div > div > div.r > a > h3`).textContent.trim())
await Promise.all([
page.waitForNavigation({timeout: 20000, waitUntil: "networkidle2"}),
// page.click('#rso > div > div > div:nth-child(1) > div > div > div.r > a > h3 > span')
page.click('#rso > div > div > div:nth-child(1) > div > div > div.r > a > h3')
]);
result = await page.evaluate(() => document.querySelector('body > div.title > div > div > div > p > a > span').textContent.trim())
// ★非同期処理の為、後続のノードへの出力はnode.send()を使用する★
node.send({payload:result})
} catch(e) {
node.send({payload:`error:${e}`})
}finally{
await browser.close()
}
})();
return msg;
あとがき
ここまで読んでくれた方ありがとうございました。
初めて書きましたが非常に疲れました...。
最後、たぶん力尽きてます。
少しでも誰かの役に立ったなら幸いですが、混乱させただけなら申し訳ありません。
また機会があれば、何か書こうかと思います。
Author And Source
この問題について(RaspberryPi4でpuppeteerを使おうとしたら躓いた。), 我々は、より多くの情報をここで見つけました https://qiita.com/tomo643/items/e5705f3767931f9edd3d著者帰属:元の著者の情報は、元のURLに含まれています。著作権は原作者に属する。
Content is automatically searched and collected through network algorithms . If there is a violation . Please contact us . We will adjust (correct author information ,or delete content ) as soon as possible .