node.jsのpuppeteer(ブラウザ自動操作)を使って、スクレイピングしてみた
node.jsは非同期がデフォだけど、スクレイピングは同期的な方が良いよな~。
1, 適当なフォルダを作って、適当な名前(scraping.js)で保存。
2, package.jsonがないから、npm init -y で生成
3, package.jsonの中身が空なので、npm installでパッケージがインストールされないので手動でインストールする
npm install –save puppeteer sync-request fs path
4, 適当なファイル名で保存して実行。
上手く動いたけど、node.jsはすぐにバージョンが変わるので、すぐに修正が必要になりそう…。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 |
// npm install必要 const puppeteer = require('puppeteer'); //@1.11.0 var request = require('sync-request'); const fs = require('fs'); const path = require('path'); // ダウンロード設定 const LOGIN_USER = '自分のログインID'; const LOGIN_PASS = '自分のログインパスワード'; const LOGIN_URL = 'スクレイピングしたログイン画面のURL'; const LOGIN_USER_SELECTOR = 'ログインID入力テキストの要素名(CSSセレクタ指定。クラス名orID名)'; const LOGIN_PASS_SELECTOR = 'ログイン・パスワード入力テキストの要素名(CSSセレクタ指定。クラス名orID名)'; const LOGIN_SUBMIT_SELECTOR = 'ログインボタンの要素名(CSSセレクタ指定。クラス名orID名)'; const BASE_URL = 'ベースとなるURL。https://www.example.com/video みたいな感じで記述'; const video_url = [ // ....ダウンロードしたい動画などのURLを記述しておく 'archives/1', 'archives/2', 'archives/3', // ... ]; // 動画のタグを指定。右クリックの「検証」などで取得 const TARGET_ELEMENT = '要素名など動的に生成されるのでソースだと難しい'; (async () => { // ブラウザを開く const browser = await puppeteer.launch({ headless: false, // (デバッグの時は false にしたほうが画面が見えてわかりやすい }); const page = await browser.newPage(); // 新規ページ await page.setViewport({ width: 1440, height: 900 }); // ビューポート (ウィンドウサイズ) await page.setExtraHTTPHeaders({ // 必要な場合、HTTPヘッダを追加 'Accept-Language': 'ja' }); // ログイン画面が全部ダウンロードされるまで待つ await page.goto(LOGIN_URL, { waitUntil: 'domcontentloaded' }); await page.type(LOGIN_USER_SELECTOR, LOGIN_USER); // ユーザー名入力 await page.type(LOGIN_PASS_SELECTOR, LOGIN_PASS); // パスワード入力 await Promise.all([ // ログインボタンクリック // クリック後ページ遷移後通信が完了するまで待つ (ページによっては 'domcontentloaded' 等でも可) page.waitForNavigation({ waitUntil: 'networkidle0' }), page.click(LOGIN_SUBMIT_SELECTOR), ]); // ダウンロードしたい動画などのURLの分だけループ for(let i = 0; i < video_url.length; i++) { // エラーがあったら、次のURLに行く。 try { // urlが決定 let target_url = BASE_URL + video_url[i]; // ログイン後の画面に移動 await page.goto(target_url, { waitUntil: 'domcontentloaded' }); // 動画のsourceタグの取得 const source = await page.$(TARGET_ELEMENT); // 取得したタグのsrc属性を取得 const src = await source.getProperty('src'); // JSHandleオブジェクトの内容をjsonValueで取り出す const targetUrl = await src.jsonValue(); // パス名からファイル名を生成する。 const FileName = video_url[i].replace("/", "-"); console.log( i +'/'+ video_url.length +' '+ FileName); // 1URL,1ファイルずつ同期的に終わらせてから次に行く。 const response = await request('GET', targetUrl); if(response.statusCode === 200){ fs.writeFileSync( './download/' + FileName + '.webm', response.body, 'binary' ); } // 1URL,1ファイルずつ同期的に終わらせてから次に行く。 } catch (error) { console.log(error); } // sleep(1) await new Promise(r => setTimeout(r, 1000)); } // ブラウザを閉じる await browser.close(); })(); |