見出し画像

0からのJavaScriptスクレイピング 0章

この記事で試せること

このようなデモプログラムを動かせます。今回は、分かりやすさを優先して、この記事のタイトルを取得する、シンプルなデモにしました。

この記事はコピペで動かせるプログラムコードがついています。

この企画の目的と内容

スクレイピングという技術に興味がある方が、試しにプログラムを動かしてみてスクレイピングを体験して、簡単な範囲で改造を行っていきながらプログラミングへの知見を増やしていくことを目的としています。

今回は新しい試みとして、英語学習のようにプログラミングを文法として解説する事で、どこを書きければ良いかの感覚を掴みやすくなるのではないかと考えています。

第0章では、プログラミングを行うための環境を作り、試しにスクレイピングのプログラムを動かして体験してみます。また、体験したプログラムの簡単な解説を行います。

第1章以降では、実際に改造していく方法について解説していきます。

なお0章の内容は、実際にオフラインイベントで実地した内容で一定の評価を頂いたコンテンツになります。その際の知見もこの記事にフィードバックされています。ご協力頂いております皆様には大変感謝しております。

主に言語としてはJavaScriptを扱います。スクレピングを行うためのツールとしてPuppeteerを使用します。

前準備

まず、プログラミングは非常に高い自由度があるためにディスクトップのファイルを削除してしまう事があるかもしれません。またパソコンはこわれますからプログラミングに関わらずデータのバックアップを取ることをオススメします。

次に、出来る範囲でパソコンをアップデートして、OSを最新の状態にしてください。

今回は、スクレイピングを行うためのプログラミング言語としてJavaScriptを使用します。JavaScriptを動かすためにNode.jsというものをインストールしていきます。なお、この作業はプログラミングの環境構築と呼ばれていて、そこそこ難易度が高いので上手く行かなくても落ち着いて進めてみましょう。難しければ質問してください。

なお、ここからの作業はインターネット回線が安定していないと、不明なエラーが出やすいので回線が安定している場所で行ってください。

プログラミングを行う上で、上記のようなコマンドラインと呼ばれる画面を操作する必要があり、一定知識が必要なのでProgateで勉強してみましょう。

Node.jsのインストール Mac版

Windowsの方は、次のNode.jsのインストール Windows版に進んでください。

コマンドラインを起動しましょう。Macではよくコマンドラインとしてターミナルを使います。

コマンドラインを使って、brewをインストールしてください。

次にNode.jsをインストールします。なお、$は習慣的にコマンドラインへの入力文を表す記号で実際には「brew install node」の部分を入力してください。

$ brew install node

以上で完了です。

実際にインストール出来ているか確認してみましょう。

$ node --version
v10.9.0

このようにバージョンが表示されていれば成功です。

$ node --version
node: command not found

このようにnodeなんてコマンドはないよと言われていれば失敗しています。

Node.jsのインストール Windows版

Windowsは公式よりインストーラーを入手して、インストールを行ってください。

以上で完了です。

実際にインストール出来ているか確認してみましょう。

コマンドラインを起動しましょう。Windowsではよくコマンドラインとしてコマンドプロンプトを使います。

$ node --version
v10.9.0

このようにバージョンが表示されていれば成功です。

$ node --version
node: command not found

このようにnodeなんてコマンドはないよと言われていれば失敗しています。

エディタの導入

試しに動かしてみましょう

ここからは実際にプログラムを動かしてみて、スクレイピングの間隔を掴んでいきましょう。

プログラムを保存する

プログラムを保存するフォルダとしてnoteというフォルダを作って下さい。この作業は最終的にこのようなフォルダ構成を目指します。

.
└── note
    ├── index.js
    └── package.json

index.jsというファイル名で、次のコードを保存してください。

const puppeteer = require('puppeteer');

const main = async () => {
  const browser = await puppeteer.launch({
    headless: false,
    slowMo: 250,
    defaultViewport: null
  });

  const page = await browser.newPage();
  await page.goto('https://note.mu/yoneapp/n/n1a4ee4c5fe52');

  const h1s = await page.$$('h1');
  const h1 = h1s[1];
  const title = await page.evaluate(el => el.innerText, h1);

  console.log(title);

  browser.close();
}

main();

package.jsonというファイル名で、次のコードを保存してください。

{
  "name": "scraping",
  "version": "1.0.0",
  "main": "index.js",
  "license": "MIT",
  "dependencies": {
    "puppeteer": "^1.8.0"
  }
}

プログラムを実行する

Puppeteerを読み込むためにライブラリをインストールします。notoフォルダにコマンドラインで移動して、次のコマンドを実行して下さい。

$ npm install

ライブラリがインストールされて、このようなフォルダ構成になります。

.
├── index.js
├── node_modules
   ...
│   ├── puppeteer
│   │   ├── CONTRIBUTING.md
│   │   ├── DeviceDescriptors.js
│   │   ├── Errors.js
│   │   ├── LICENSE
│   │   ├── README.md
│   │   ├── index.js
   ...
├── package-lock.json
└── package.json

さあ、プログラムを実行しましょう。

$ node index.js

これで、記事最初の動画のようにプログラムが動けば成功です。

解説

ここからは、プログラムについて解説を行っていきます。

まず、以下の部分に関する理解は後回しにしましょう。色々な要素があって最初は理解が難しいためです。

const puppeteer = require('puppeteer');

const main = async () => {
  const browser = await puppeteer.launch({
    headless: false,
    slowMo: 250,
    defaultViewport: null
  });

  const page = await browser.newPage();

  // ここにやりたいことを書く

  browser.close();
}

main();

特に、安全に実行するための設定も入っているので上記のプログラムの部分は変更しないようにしてください。

さて、index.jsを上記のようにプログラムを削った状態で実行したらどうなるか分かりますか?

予想する事は大切ですが、プログラミング学習では何度でも試しに動かしてみることが出来ます。動かしてみましょう。

ここで、プログラミングに関する秘密を打ち明けましょう。実は10年プログラマをしている私にとってもこのサンプルプログラムを一発で作ることは難しいことでした。

しかし、一発でなければ簡単なのです。プログラマを学んでいる最中は、一発で作るイメージを持ってしまいがちだと思います。少し書き換えつつ、動かしてみて動いている状態をキープして前に勧めていくと難易度が下がります。

というわけでやってみましょう。

const puppeteer = require('puppeteer');

const main = async () => {
  const browser = await puppeteer.launch({
    headless: false,
    slowMo: 250,
    defaultViewport: null
  });

  const page = await browser.newPage();

  await page.goto('https://note.mu/yoneapp/n/n1a4ee4c5fe52');

  browser.close();
}

main();

動かしてみましょう!どうなりましたか?うまくいかない場合は、ファイルの保存が行われてない場合も多いですよ

ここで書いたプログラムを見てみましょう。

  await page.goto('https://note.mu/yoneapp/n/n1a4ee4c5fe52');

予想がついている方も多いと思いますが https://note.mu/yoneapp/n/n1a4ee4c5fe52 のURLを書き換えると、別のページを表示することが出来ます。やってみましょう。'を消さないように注意してください。

await page.goto('URL');

この文法で、特定のページに移動する事ができます。

最後のコードを見ていきましょう。

const puppeteer = require('puppeteer');

const main = async () => {
  const browser = await puppeteer.launch({
    headless: false,
    slowMo: 250,
    defaultViewport: null
  });

  const page = await browser.newPage();
  await page.goto('https://note.mu/yoneapp/n/n1a4ee4c5fe52');

  const h1s = await page.$$('h1');
  const h1 = h1s[1];
  const title = await page.evaluate(el => el.innerText, h1);
  console.log(title);

  browser.close();
}

main();

await page.$$('h1'); というコードを使うことで、現在表示しているページのh1タグを全て取得しています。例えば await page.$$('h2'); にすればh2タグを全て取得します。

await page.$$('HTML TAG');

という感じです。ここでHTMLとCSSについての知識が必要なのでProgateで勉強してみましょう。

await page.$$('CSS CLASS NAME');

というふうにCSSのクラス名で指定する事も可能です。

さて、次に const h1s = ○;という部分について見ていきます。これは h1s という単語を作って、○を指すことにします。ちょっと不可解な話かもしれないのでたとえ話をします。

例えば、これは英語で言うところの Charlie is dog.です。つまり h1s is ○ です。つまり○という存在に名前をつけてあげています。Charlie も名前がないと呼んであげられませんし、プログラムにおいても人間が作り出したものには名前をつけてあげるというだけのことです。

const △ = ○;

さて、三角の部分は英単語であればだいたい何でもつけることが出来ます。catでもいいです。ただ、できるだけ○にあった内容を命名してあげるほうが良いとされています。

await page.$$('h1'); のプログラムは、現在のページのh1タグをすべて持ってくることでした。実はこのページにはh1タグが2つあります、確かめてみましょう。

const puppeteer = require('puppeteer');

const main = async () => {
  const browser = await puppeteer.launch({
    headless: false,
    slowMo: 250,
    defaultViewport: null
  });

  const page = await browser.newPage();
  await page.goto('https://note.mu/yoneapp/n/n1a4ee4c5fe52');

  const h1s = await page.$$('h1');
  console.log(h1s.length);

  browser.close();
}

main();

2という結果が表示されましたか?

console.log(h1s.length);

この文を見ていきましょう。

console.log(○);

console.lolg(○); を使うことによって、○をコンソールに表示することが出来ます。

const puppeteer = require('puppeteer');

const main = async () => {
  const browser = await puppeteer.launch({
    headless: false,
    slowMo: 250,
    defaultViewport: null
  });

  console.log('好きな文章を表示することが出来るよ!');

  browser.close();
}

main();

例えば、こんな感じです。実行してみてくださいね。

h1sにh1が何個あるか聞くにはlengthと聞いてあげます。

const puppeteer = require('puppeteer');

const main = async () => {
  const browser = await puppeteer.launch({
    headless: false,
    slowMo: 250,
    defaultViewport: null
  });

  const page = await browser.newPage();
  await page.goto('https://note.mu/yoneapp/n/n1a4ee4c5fe52');

  const h1s = await page.$$('h1');
  h1s.length;

  browser.close();
}

main();

動かしてみて下さい。何もおきませんね。聞いただけでは、私達が確認する事ができないのでconsole.log();を使います。

const puppeteer = require('puppeteer');

const main = async () => {
  const browser = await puppeteer.launch({
    headless: false,
    slowMo: 250,
    defaultViewport: null
  });

  const page = await browser.newPage();
  await page.goto('https://note.mu/yoneapp/n/n1a4ee4c5fe52');

  const h1s = await page.$$('h1');
  console.log(h1s.length);

  browser.close();
}

main();

と言うふうにh1タグが2つである事を確認できます。

ちなみにですね、1個目のh1タグはここです。

2個目のh1タグはここです。

1個目じゃなくて、2個目のh1内のテキストが欲しいです。というわけで

  const h1 = h1s[1];

とします。

h1s[○];

という文法があります。○番目のh1sを下さいという文です。ここで、2番目がほしいのに、何故1番目を指定しているのか?と思ってほしいです。

プログラミングの特徴として、数は0番目から数えます。なので、私達が認識している2個目とはプログラミングの文脈上は1個目となる事があります。

const title = await page.evaluate(el => el.innerText, h1);

最後に、この文法を見ていきましょう。

await page.evaluate(el => el.innerText, ○);

この文法は○タグ内のテキストを下さいという文です。

const title = await page.evaluate(el => el.innerText, h1);
console.log(title);

それに title という名前をつけて console.log で表示しています。

まとめ

スクレイピングに必要な環境構築を行い、デモプログラムを動かしてみました。デモプログラムの挙動についての簡単な解説を行いました。

この記事で行ったように、プログラムを理解するために最も重要なことは動作を確認しながらプログラムを増やしていき、少しずつ動かしまくることです。

今でも私はプログラミングは目に見えないというのが、とてもむずかしいと思っています。それでも動かした結果と、増やしたコードは対応しています。この対応付けに脳をなれさせることで、見えないものが見えるようになるかもしれません。

この記事は、可能な範囲で書いては居ますが、読まれている方全てに対応出来てはいないと思います。そこに関しては是非、ご質問を頂くことで解決したいと思っています。ですので、ご質問・ご感想など何なりと @yoneapp までご連絡下さい。

次の章からは、実際に改造していく方法などを解説していきます。もし宜しければ、感想・応援ツイートやいいね頂けると幸いです。

サポート頂けたらめっちゃ喜びます!