みなさんは、
スクレイピングってなんだろう?
クローラーを作ってみたい!
スクレイピングをしてみたい!
と思っているのではないでしょうか?
本記事では、「クローラーやスクレイピングってなんだろう?」という疑問から、Pythonを使用したクローラーの作成方法やスクレイピングの方法まで解説していますので、しっかりマスターしていきましょう!
本記事を読む前に、Pythonがどんなプログラミング言語なのかをおさらいしておきたい人は次の記事を参考にしてください。
→ Pythonとは?特徴やできること、活用例をわかりやすく簡単に解説
なお、その他のPythonの記事についてはこちらにまとめています。
クローラー、スクレイピングとは
クローラーとは
ここで説明しているクローラーとは、インターネット上のコンテンツをクローリングするためのWEBクローラのことを指しています。元々クローリングとは英単語のクロール(crawl)「はう、腹ばっていく」という意味からきているのです。
水泳のクロールも同じ単語から来ているので、こちらをイメージすると多少わかりやすいかもしれません。つまり、様々なウェブ上のリンクを巡回(クロール)し、対象ページのデータを収集をするものがクローラーとなります。
スクレイピングとは
スクレイピングとは元々英単語のscrape「こすり落とす、削り取る」という意味からきています。つまり、インターネット上のHTMLなどのコンテンツをこすり落として、必要なデータを取得することをスクレイピングと言います。
requestsでスクレイピングをしてみよう!
requestsライブラリとは
Pythonには元々標準ライブラリのurllib2があるのですが、非常に多機能なためちょっとした作業をするには少し面倒だったりもします。
requestsライブラリは、人間のためのHTTPと呼ばれるほど使いやすく設計されていて、簡単にスクレイピングを試すことができるため、こちらを使ってスクレイピングをしていきましょう!
requestsのインストール
requestsのインストールはpipで行うことができます。
$ pip install requests
HTMLを取得して表示してみよう!
それでは、まず侍エンジニアブログのトップページをスクレイピングしてみましょう!
import requests url = "https://www.sejuku.net/blog/" response = requests.get(url) response.encoding = response.apparent_encoding print(response.text)
実行すると取得したHTMLが表示されたかと思います。例えば以下のような感じです。
ちなみに、responseに指定しているapparent_encodingを指定することで、できるだけ文字化けが起こらないようにコンテンツを取得できます。requestsを使用したスクレイピング方法はこちらでも解説されていますので参考にしてください。
複数のURLから取得して表示してみよう!
次は、URLを複数指定して、HTMLを取得してみたいと思います。HTMLの取得方法は先程と同じです。注意したいのは、複数のコンテンツをスクレイピングをするときのルールとして最低でも1秒以上の間隔を開けるようにするということです。
以下のサンプルコードでもtime.sleep(1)を指定してHTML取得の間隔を開けています。連続のアクセスはサーバに負荷をかけるため気をつけるようにしてください。
import requests import time # 取得するURL url_top = "https://www.sejuku.net/blog/" url_python = "https://www.sejuku.net/blog/curriculums-python" # 侍エンジニアブログ トップページ取得 response = requests.get(url_top) response.encoding = response.apparent_encoding # スリープ time.sleep(1) # 侍エンジニアブログ Pythonページ取得 response2 = requests.get(url_python) response2.encoding = response.apparent_encoding print("--- 侍エンジニアブログ トップページ ---") print(response.text) print("--- 侍エンジニアブログ Pythonページ ---") print(response2.text)
※上のコードを実行するとターミナルにだだーっと膨大なHTMLが表示されるので注意してください。
URLから取得したデータをファイルに保存してみよう!
今度は、取得したHTMLをファイルに保存してみましょう!
import requests # 取得するURL url_top = "https://www.sejuku.net/blog/" # 侍エンジニアブログ トップページ取得 response = requests.get(url_top) response.encoding = response.apparent_encoding response_html = response.text # 例えばresult.htmlに保存するなら… with open('result.html', 'w', encoding='utf-8') as f: f.write(response_html) print('ファイルに保存')
Pythonを実行して、以下の出力がされるとHTMLが保存されているので確認してみましょう!
実行結果
ファイルに保存
Beautiful Soupでスクレイピングをしてみよう!
Beautiful Soupとは
Beautiful Soupとは、requestsで取得したHTMLデータを解析するためのライブラリです。HTMLを解析するための様々なメゾットやセレクタがあるためより効率的に解析することができるのです!
それでは早速インストールをして、HTMLを解析してみましょう!
Beautiful Soupのインストール
pipを使用してBeautiful Soupをインストールしてください!
$ pip install beautifulsoup4
スクレイピングで特定の値を表示してみよう!
それでは、Beautiful SoupでHTMLを解析していきます。URLの指定からHTMLを取得するまでのコーディングは、requestsを使用するため先程と全く同じようにできます。
HTMLの取得ができたら、まずfindメゾットでページのulタグを取得します。そして、その中にあるliタグのテキストを取得してプリントしています。
import requests from bs4 import BeautifulSoup url = "https://www.sejuku.net/" response = requests.get(url) response.encoding = response.apparent_encoding bs = BeautifulSoup(response.text, 'html.parser') bs_ul = bs.find('ul') for bs_li in bs_ul.find_all('li'): bs_text = bs_li.text print(bs_text)
実行結果
| 卒業生エピソード | サービス内容 | コース料金表 | 無料カウンセリングとは? | Q&A | お問い合わせ |
実行結果は上記のように、ナビバーのテキストが表示されます。
CSSセレクタを使用して値を表示してみよう!
次はCSSセレクタを使って、ページ内のカリキュラム名とURLを取得してみましょう!CSSセレクタのbs.select()の指定方法は、通常のHTMLでの指定と同じため直感的にとてもわかりやすいかと思います。
div.curriculum_bannerの指定で、「<div class=”curriculum_banner”>」のものを取得するという意味になります。
import requests from bs4 import BeautifulSoup url = "https://www.sejuku.net/blog/" response = requests.get(url) response.encoding = response.apparent_encoding bs = BeautifulSoup(response.text, 'html.parser') div_curriculums = bs.select('div.curriculum_banner') for div_curriculum in div_curriculums: a_tag = div_curriculum.find('a') curriculum_name = a_tag['title'] href = a_tag['href'] print('カリキュラム: {}, URL: {}'.format(curriculum_name, href))
実行結果
カリキュラム: プログラミング入門カリキュラム, URL: /blog/curriculums カリキュラム: Ruby入門カリキュラム, URL: /blog/curriculums-ruby カリキュラム: Swift入門カリキュラム, URL: /blog/curriculums-swift カリキュラム: Java入門カリキュラム, URL: /blog/curriculums-java カリキュラム: Python入門カリキュラム, URL: /blog/curriculums-python カリキュラム: JavaScript入門カリキュラム, URL: /blog/curriculums-javascript
スクレイピングした結果から集計結果を表示してみよう!
次は、スクレイピングをして集計してみましょう。より本格的なスクレイピングに近づいてきたかと思います。殿堂入り記事一覧を取得して、タイトルにpythonの文字列がある記事を見つけています!
また、pythonの文字列が何個見つかったかの合計数も表示するようにしています!
import requests from bs4 import BeautifulSoup url = "https://www.sejuku.net/blog/recommends" search_word = 'python' count = 0 response = requests.get(url) response.encoding = response.apparent_encoding bs = BeautifulSoup(response.text, 'html.parser') articles = bs.select('article.vce-lay-b-child') for article in articles: a_tag = article.find('a') article_title = a_tag['title'] if search_word in article_title.lower(): count += 1 href = a_tag['href'] print('タイトル: {}, nURL: {}'.format(article_title, href)) print('#'*50) print('検索ワード: {}, 該当記事: {}個'.format(search_word, count)) print('#'*50)
実行結果(※時期によって結果は変わります。)
タイトル: 本当は教えたくない!Python/パイソン入門書籍おすすめ7選, URL: https://www.sejuku.net/blog/3319 タイトル: 専門知識いらず!Pythonとは?言語の特徴から網羅的に徹底解説, URL: https://www.sejuku.net/blog/7720 タイトル: Pythonでできることって!?大注目プログラミング言語徹底解説, URL: https://www.sejuku.net/blog/3863 ################################################## 検索ワード: python, 該当記事: 3個 ##################################################
だんだんとスクレイピングがわかってきたのではないでしょうか?Beautiful Soupを使用したスクレイピング方法は以下の記事にも解説されていますので、基礎から確認したい場合は以下の記事も見てみてください!
Scrapyでクローラーを作成してみよう!
Scrapyとは
これまでrequestsやBeautifulSoupを使用してURLコンテンツを取得、解析の方法をご紹介してきました。このコンテンツの取得、解析やクローリングの各種設定などをより簡単に実装するためのものがScrapyとなります!
Scrapyのインストール
Scrapyもインストールはpipで簡単に行うことができます!
$ pip install scrapy
プロジェクトの作成
Scrapyを実行するには、まず実行するための環境(プロジェクト)を作成する必要があります。以下のコマンドを実行して作成してください!
$ scrapy startproject samurai_tutorial
クローリングする際の注意点と設定について
先程スクレイピングをする際のルールについてお伝えしましたが、Scrapyを使用する際も同様に負荷を掛けないための仕組みが必要です。先程お伝えした方法は、sleepをコードの中に入れてスクレイピング間隔を広げていました。
実はScrapyには、クローリングやスクレイピングをする際に便利な機能がたくさんあります。Scrapyを使用すると、クローリングやスクレイピングを簡単にできるだけでなく、様々な設定値を設定ファイルから簡単に行うことができるのです。
それでは今回はスクレイピングする上での最低限の設定として、複数URLをクロールする際のスクレイピング間隔を指定していきます。こちらデフォルトでは0となっていますが、サーバに負荷を掛けないためのマナーとして必ず1秒以上の値を設定するようにしましょう。
今回は3秒を指定します。先程作成したScrapyプロジェクト内のsamurai_tutorial/settings.pyを参照してください。「DOWNLOAD_DELAY」の値がコメントアウトされているかと思うので、有効化しましょう。
※コメントアウトが見つからない場合は、新しく設定を追加してください!
samurai_tutorial/settings.py
DOWNLOAD_DELAY = 3
ScrapyでHTMLを表示してみよう!
それではまずScrapyを使用してHTMLを表示してみましょう!まず先程作成したScrapyプロジェクトに移動して、スクレイピングを実行するためのプログラムを生成してみましょう!
cd samurai_tutorial scrapy genspider samurai www.sejuku.net
コマンド実行が完了すると、以下のディレクトリ構造で、「samurai.py」というファイルが生成されているかと思いますので確認してみてください!
samurai_tutorial/ └── samurai_tutorial └── samurai.py
Scrapyでは、Spiderというクラスを定義して、その中のparseメゾットでクローリングを行っていきます。またクラス内のnameは、プログラムを実行する際に指定する名前になります。
allowed_domainsは、クローリングを許可するドメインを入力してください。start_urlsは、スクレイピング対象のURLを定義します。
samurai.py
# -*- coding: utf-8 -*- import scrapy class SamuraiSpider(scrapy.Spider): name = 'samurai' allowed_domains = ['www.sejuku.net'] start_urls = ['http://www.sejuku.net/'] def parse(self, response): pass
Scrapyで複数のURLをクローリングしてみよう!
それでは先程コマンドで作成した「samurai.py」を以下の様に修正してください!複数のURLをクローリングする場合は、start_urlsに複数URLを指定することで可能となります。
# -*- coding: utf-8 -*- import scrapy class SamuraiSpider(scrapy.Spider): name = 'samurai' allowed_domains = ['www.sejuku.net'] start_urls = [ 'https://www.sejuku.net/blog/', 'https://www.sejuku.net/blog/recommends', ] def parse(self, response): print('#'*50) print(response.url) print(response.text)
実行結果
scrapy crawl samurai
上記のコマンドを実行して、出力結果を確認してください!指定したURLと、取得したHTMLが表示されたかと思います。
yieldで取得したリンクから複数のページをクローリングしてみよう!
最後に本格的なクローラーを作成していきましょう!侍エンジニアブログページのカリキュラム項目から個々のカリキュラムのURLを取得し、yieldへ渡すことにより、今度は個々のカリキュラムのURLをスクレピングしています。
個々のカリキュラムページの記事中身にpythonという文字列が含まれているかを判定し、結果を出力しています!このようにScrapyでは、取得したURLをyieldに渡してクローリングできるため、より層を深くすれば簡単にたくさんのページをクローリングしていくことができるのです!
# -*- coding: utf-8 -*- import scrapy class SamuraiSpider(scrapy.Spider): name = 'samurai' allowed_domains = ['www.sejuku.net'] start_urls = [ 'https://www.sejuku.net/blog/', ] def parse(self, response): root_url = self.start_urls[0].replace('/blog/', '') div_main_box = response.css('div#main-box-2')[0] for div_cur in div_main_box.css('div.curriculum_banner'): url = div_cur.css('a::attr(href)').extract_first() url = root_url + url yield scrapy.Request(url, callback=self.parse_word) def parse_word(self, response): search_word = 'python' main_contents = response.css('main').extract_first() if search_word in main_contents.lower(): print('{}という文字列を発見しました。nURL: {}'.format(search_word, response.url))
実行結果
$ scrapy crawl samurai pythonという文字列を発見しました。 URL: https://www.sejuku.net/blog/curriculums-python pythonという文字列を発見しました。 URL: https://www.sejuku.net/blog/curriculums
まとめ
いかがでしたでしょうか。今回は、Pythonのクローラーについて紹介しました。スクレイピングの基礎からクローリングの応用的な内容まで学習することができましたね。
スクレイピングやクローリングの学習は、Pythonのプログラミング能力が向上するだけでなく、HTMLやCSS、基本的なHTTPの仕組みを理解する上でも役立ちますので、しっかりとマスターしていきましょう!!
なお、この記事ではPythonのについて紹介しましたが、これ以外にもPythonの基礎知識などが知りたい方は以下記事をどうぞ!
Pythonをはじめて学ぶ方のために、Pythonでできることや学習法を中心にご紹介していますので、きっと参考になるかと思います。
【Python入門 完全攻略ガイド】