はじめに
ウェブスクレイピングとは、ウェブサイト上に公開されているデータを自動で収集する手法のことを指します。たとえば、商品価格やレビュー、ニュース記事のヘッドラインなど、手動で集めると膨大な時間がかかる情報も、ウェブスクレイピングを使えば効率的に収集可能です。
Pythonには、ウェブスクレイピングのためのさまざまなライブラリが用意されています。その中でもScrapyは、高速で効率的なクローリングを実現する強力なフレームワークとして人気があります。
他の有名なウェブスクレイピングライブラリとしては、BeautifulSoupやSeleniumが挙げられますが、Scrapyは以下のような特徴があります。
本記事では、Scrapyのインストールから基本的な使い方、さらに実践的な活用方法までをステップごとに解説していきます。

Webサイトからデータを自動で集めたい!と思ったことはありませんか?そんなあなたに、PythonとScrapyを使ったWebスクレイピングのガイドを用意しました。初めてでもわかりやすく、ステップごとに進められる内容なので、ぜひ気軽にチェックしてみてくださいね!
Scrapyのインストールとセットアップ

Scrapyを使用するためには、まずPython環境を整える必要があります。以下の手順でインストールとセットアップを進めていきましょう。
Pythonの環境設定
ScrapyはPythonで動作するため、Pythonがインストールされていない場合は、まずPythonをインストールします。Pythonのバージョンは3.6以上を推奨しています。公式サイト(python.org)からインストーラーをダウンロードしてインストールしてください。
インストールが完了したら、以下のコマンドを実行して、Pythonが正しくインストールされているか確認します。
python --versionScrapyのインストール方法
Pythonがインストールされたら、次はScrapyをインストールします。ScrapyはPythonのパッケージ管理ツールであるpipを使用してインストールできます。以下のコマンドを実行してください。
pip install scrapyインストールが完了したら、Scrapyが正しくインストールされているか確認するために、次のコマンドを実行します。
scrapy versionバージョンが表示されれば、インストールは正常に完了しています。
プロジェクトの作成手順
Scrapyではプロジェクトベースでクローリングを行います。新しいプロジェクトを作成するには、ターミナルやコマンドプロンプトで以下のコマンドを実行します。
scrapy startproject myprojectmyprojectの部分には、任意のプロジェクト名を指定します。このコマンドを実行すると、以下のようなディレクトリ構造が作成されます。
myproject/
scrapy.cfg
myproject/
__init__.py
items.py
middlewares.py
pipelines.py
settings.py
spiders/
__init__.pyこれでScrapyプロジェクトの基本的なセットアップは完了です。次に、Scrapyの主要なコンポーネントについて見ていきましょう。
Scrapyの基本構造と主要コンポーネント
Scrapyのプロジェクトは、複数のコンポーネントから構成されており、それぞれの役割があります。この章では、Scrapyの主要な構造とコンポーネントについて解説します。
スパイダー(Spider)
スパイダーは、Scrapyの中心的なコンポーネントで、ウェブサイトをクロールしてデータを収集する役割を担います。スパイダーは、ターゲットとなるウェブサイトのURLや、データの抽出方法を定義します。
スパイダーは、spiders/ディレクトリ内に保存されます。スパイダーを作成するには、ScrapyのSpiderクラスを継承してカスタマイズします。
以下は、基本的なスパイダーの例です。
import scrapy
class MySpider(scrapy.Spider):
name = 'myspider'
start_urls = ['http://example.com']
def parse(self, response):
title = response.xpath('//h1/text()').get()
yield {'title': title}アイテム(Item)
アイテムは、収集したデータを定義するためのコンポーネントです。items.pyファイル内で、どのようなデータを収集するかを定義します。
以下のように、scrapy.Itemクラスを継承してアイテムを定義します。
import scrapy
class MyItem(scrapy.Item):
title = scrapy.Field()
price = scrapy.Field()ここで定義されたフィールドは、スパイダーの中でデータを収集する際に使用されます。
パイプライン(Pipeline)
パイプラインは、スパイダーで収集されたデータを処理する役割を持ちます。たとえば、データベースへの保存や、データのクリーニング、フィルタリングを行います。
パイプラインは、pipelines.pyに定義し、settings.pyで有効にします。
以下は、データをファイルに保存する簡単なパイプラインの例です。
class MyPipeline:
def process_item(self, item, spider):
with open('output.txt', 'a') as f:
f.write(f"{item['title']}\n")
return itemprocess_itemメソッド内で、アイテムごとに処理を行い、最後にアイテムを返します。
ミドルウェア(Middleware)
ミドルウェアは、リクエストやレスポンスの処理をカスタマイズするためのコンポーネントです。たとえば、特定のヘッダーを追加したり、クッキーを操作したりすることができます。
ミドルウェアはmiddlewares.pyに定義し、settings.pyで設定します。
以下は、リクエストにユーザーエージェントを追加するミドルウェアの例です。
class MyMiddleware:
def process_request(self, request, spider):
request.headers['User-Agent'] = 'MyCustomUserAgent/1.0'これにより、すべてのリクエストにカスタムのユーザーエージェントが追加されます。
以上がScrapyの基本構造と主要コンポーネントの概要です。これらのコンポーネントを理解することで、Scrapyの柔軟なカスタマイズが可能になります。
最初のスパイダーを作成してみよう
ここでは、実際に簡単なスパイダーを作成し、ウェブサイトからデータを収集する流れを解説します。Scrapyを使えば、複雑なスクレイピング処理もシンプルなコードで実行できるため、初心者でも理解しやすいです。
スパイダーの作成
まず、spidersディレクトリ内にスパイダーを作成します。今回は、example_spider.pyという名前のスパイダーを作成します。
次に、以下のコードをスパイダーに追加します。このスパイダーは、指定したURLからHTMLページの<h1>タグ内のテキストを抽出して表示します。
import scrapy
class ExampleSpider(scrapy.Spider):
name = 'example'
start_urls = ['http://example.com']
def parse(self, response):
title = response.xpath('//h1/text()').get()
yield {'title': title}スパイダーの実行
作成したスパイダーを実行するには、以下のコマンドをターミナルで入力します。
scrapy crawl exampleこれにより、Scrapyは指定したURL(この場合はhttp://example.com)をクロールし、指定されたデータ(<h1>タグ内のテキスト)を取得して出力します。
データの保存
スクレイピングしたデータをファイルに保存したい場合、次のようにコマンドを修正します。データをJSON形式で保存する場合、次のコマンドを使用します。
scrapy crawl example -o output.jsonこれにより、スクレイピング結果がoutput.jsonというファイルに保存されます。CSVやXML形式で保存したい場合も、拡張子を変えるだけで簡単に対応可能です。
scrapy crawl example -o output.csvこれで最初のスパイダーを作成し、ウェブページからデータを抽出する基本的なプロセスを理解できました。次の章では、クローリングの速度制御やロボット排除規則(robots.txt)への対応方法について説明します。
クローリングの制御

Scrapyでは、クローリングの速度やリクエストの頻度を制御することが重要です。これにより、ターゲットサイトへの負荷を軽減し、サーバーからブロックされるリスクを回避できます。また、サイトが持つ「robots.txt」というファイルに従うことで、許可されている範囲内でクローリングを行うことも推奨されます。
クローリング速度の調整
Scrapyでは、クローリングの速度をいくつかの設定で簡単に制御できます。たとえば、リクエスト間の待機時間を設定することで、サーバーに負担をかけずにクロールすることができます。
- DOWNLOAD_DELAY: 各リクエストの間に挿入する遅延時間(秒数)を指定します。たとえば、1秒の遅延を設定するには、次のように
settings.pyに追加します。
# settings.py
DOWNLOAD_DELAY = 1.0この設定により、Scrapyは各リクエスト間に1秒の待機時間を設けるため、過度にサーバーに負荷をかけないようになります。
- CONCURRENT_REQUESTS: 同時に処理するリクエストの数を指定します。デフォルトでは16ですが、これを減らすことでサーバーへの負荷を軽減できます。
# settings.py
CONCURRENT_REQUESTS = 8ロボット排除規則(robots.txt)の対応
ウェブサイトの多くは、robots.txtというファイルを使用して、どのページがクロール可能かを指定しています。Scrapyはデフォルトでこのファイルに従うように設定されているため、クローリングを行う前にターゲットサイトのrobots.txtを確認し、適切なリクエストを送信します。
- ROBOTSTXT_OBEY:
settings.pyでTrueに設定されている場合、Scrapyはrobots.txtに従います。
# settings.py
ROBOTSTXT_OBEY = Trueもし、特定の理由でrobots.txtを無視してクロールしたい場合は、Falseに設定しますが、これはサイト運営者の意図に反する行為になるため、慎重に行う必要があります。
リトライとフェイルセーフメカニズム
クローリング中にリクエストが失敗することがあります。サーバーが応答しない、もしくは一時的にアクセスが制限される場合に備えて、Scrapyにはリクエストをリトライする機能が備わっています。
- RETRY_ENABLED: この設定を
Trueにすると、リクエストが失敗した際に自動的に再試行されます。
# settings.py
RETRY_ENABLED = True- RETRY_TIMES: 再試行する回数を指定します。たとえば、3回再試行するには次のように設定します。
# settings.py
RETRY_TIMES = 3- HTTPERROR_ALLOWED_CODES: 特定のHTTPステータスコード(たとえば404エラーなど)に対して、処理を続行するかを指定することも可能です。
# settings.py
HTTPERROR_ALLOWED_CODES = [404]これにより、404エラーを返すページでもスパイダーが停止せず、処理を続行できるようになります。
クローリングの速度やリクエストの頻度、エラー処理の設定を行うことで、Scrapyのクローリングプロセスをより効率的に制御できます。次の章では、収集したデータをさまざまな形式で保存し、処理する方法を紹介します。
データの保存とエクスポート
Scrapyでは、ウェブサイトから収集したデータをさまざまな形式で保存することが可能です。JSON、CSV、XMLなどのフォーマットにデータをエクスポートできる他、カスタムパイプラインを使ってデータベースに保存することもできます。この章では、データの保存方法とエクスポートの手順を解説します。
データをCSVやJSON形式で保存
Scrapyのデフォルト機能を使うことで、収集したデータを簡単にCSVやJSONファイルにエクスポートできます。スパイダーを実行する際に、出力ファイル形式と保存先を指定することで、必要な形式でデータを保存できます。
例えば、JSON形式でデータを保存するには、以下のようにスパイダーを実行します。
scrapy crawl example -o output.jsonCSV形式の場合は、次のコマンドを使用します。
scrapy crawl example -o output.csvこれにより、Scrapyはスパイダーによって抽出されたデータを指定したファイル(output.jsonまたはoutput.csv)に保存します。
データベースへの保存
より高度なデータ処理が必要な場合、データをデータベースに保存することができます。データベースに保存するには、Scrapyのパイプライン機能を使います。pipelines.pyに保存処理を実装し、settings.pyでパイプラインを有効化します。
以下は、MySQLデータベースにデータを保存するためのサンプルコードです。まず、必要なPythonモジュール(pymysql)をインストールします。
pip install pymysql次に、pipelines.pyに以下のコードを追加して、データをMySQLに保存します。
import pymysql
class MySQLPipeline:
def open_spider(self, spider):
self.connection = pymysql.connect(
host='localhost',
user='yourusername',
password='yourpassword',
db='yourdatabase',
charset='utf8mb4',
cursorclass=pymysql.cursors.DictCursor
)
self.cursor = self.connection.cursor()
def close_spider(self, spider):
self.connection.close()
def process_item(self, item, spider):
sql = "INSERT INTO yourtable (title, price) VALUES (%s, %s)"
self.cursor.execute(sql, (item['title'], item['price']))
self.connection.commit()
return item上記のコードでは、スパイダーが起動するときにデータベース接続が開かれ、データの保存が行われます。スパイダーの終了時に接続が閉じられます。
カスタムパイプラインを使ったデータ処理
データを加工して保存したい場合、カスタムパイプラインを作成することでデータの処理を柔軟にカスタマイズできます。たとえば、データをクリーニングしたり、データの一部をフィルタリングすることが可能です。
以下は、データをクリーンアップするパイプラインの例です。
class CleanDataPipeline:
def process_item(self, item, spider):
item['title'] = item['title'].strip().lower()
return itemこのパイプラインは、タイトルの余分な空白を取り除き、文字を小文字に変換してからデータを保存します。
パイプラインの有効化
作成したパイプラインを有効にするには、settings.pyにパイプラインを登録します。以下のように、ITEM_PIPELINESの設定を追加します。
# settings.py
ITEM_PIPELINES = {
'myproject.pipelines.MySQLPipeline': 300,
'myproject.pipelines.CleanDataPipeline': 400,
}数値はパイプラインの実行順序を指定します。数値が小さいほど先に実行されます。
これで、Scrapyを使って収集したデータをさまざまな形式で保存・エクスポートする方法を理解できました。次の章では、より高度なScrapyの使い方、ログインが必要なサイトのスクレイピング方法やクッキーの取り扱いについて解説します。
高度なScrapyの使い方

Scrapyを使いこなすことで、より高度なウェブスクレイピングやクローリングが可能になります。この章では、ログインが必要なサイトのスクレイピングや、クッキー、セッションの扱い方、クローリングの最適化について解説します。
ログインが必要なサイトのスクレイピング
ウェブサイトによっては、ログインをしないとデータにアクセスできないことがあります。Scrapyでは、ログインを自動化するためにフォームデータを送信し、クッキーを保持しながらデータを取得することが可能です。
以下は、ログインを必要とするサイトへのログインリクエストの例です。
import scrapy
class LoginSpider(scrapy.Spider):
name = 'loginspider'
start_urls = ['http://example.com/login']
def parse(self, response):
return scrapy.FormRequest.from_response(
response,
formdata={'username': 'yourusername', 'password': 'yourpassword'},
callback=self.after_login
)
def after_login(self, response):
# ログイン後にアクセスするページのデータを取得
if b"ログイン失敗" in response.body:
self.logger.error("ログイン失敗")
return
else:
return scrapy.Request(url='http://example.com/after_login', callback=self.parse_after_login)
def parse_after_login(self, response):
# ログイン後のデータを処理
yield {'data': response.xpath('//h1/text()').get()}このスパイダーは、ログイン後にhttp://example.com/after_loginからデータを抽出します。
クッキーとセッションの扱い
Scrapyは自動的にクッキーを管理しますが、特定のクッキーを手動で設定したり、クッキーの管理をカスタマイズすることもできます。
以下は、特定のクッキーを設定してリクエストを送る例です。
class CookieSpider(scrapy.Spider):
name = 'cookiespider'
start_urls = ['http://example.com']
def start_requests(self):
cookies = {'sessionid': '1234567890'}
for url in self.start_urls:
yield scrapy.Request(url, cookies=cookies, callback=self.parse)
def parse(self, response):
# クッキーを使ってアクセスしたデータを処理
yield {'data': response.xpath('//h1/text()').get()}クローリングの最適化
Scrapyのクローリングパフォーマンスを向上させるためのいくつかの設定とテクニックを紹介します。
- 並列リクエストの最適化: 同時に処理するリクエスト数を増減させることで、クローリング速度を調整できます。
CONCURRENT_REQUESTSで設定します。
# settings.py
CONCURRENT_REQUESTS = 32- メモリ使用量の管理: 大量のデータをスクレイピングする場合、メモリの使用量が増加します。Scrapyでは、メモリを効率よく管理するために**
scrapy.extensions.closespider.CloseSpider**拡張を利用し、特定の条件でクローリングを停止することができます。
# settings.py
EXTENSIONS = {
'scrapy.extensions.closespider.CloseSpider': 500,
}
CLOSESPIDER_PAGECOUNT = 1000 # 1000ページクロール後に停止- AutoThrottleの使用: AutoThrottle拡張機能を有効にすると、Scrapyが自動的にサーバーの負荷に応じてクローリング速度を調整します。
# settings.py
AUTOTHROTTLE_ENABLED = True
AUTOTHROTTLE_START_DELAY = 1 # 最初のリクエスト間の遅延時間
AUTOTHROTTLE_MAX_DELAY = 10 # サーバーが遅い場合の最大遅延
AUTOTHROTTLE_TARGET_CONCURRENCY = 1.0 # 同時にリクエストを処理する数AutoThrottleを使用することで、サーバーに過度の負荷をかけずに効率的にデータを収集することができます。
これで、ログインが必要なサイトのスクレイピング、クッキーとセッションの管理、クローリングの最適化について学びました。次の章では、Scrapyを使った具体的な実践例と、よくあるトラブルシューティングについて説明します。
Scrapyを使った実践例
ここでは、Scrapyを使った具体的なプロジェクト例を紹介します。さらに、スクレイピング中に発生する可能性のあるトラブルやエラーの解決方法も併せて解説します。
eコマースサイトの商品情報収集
eコマースサイトの商品情報を収集することは、価格比較やマーケット調査などに有用です。以下は、オンラインストアから商品の名前と価格をスクレイピングするスパイダーの例です。
import scrapy
class EcommerceSpider(scrapy.Spider):
name = 'ecommerce'
start_urls = ['https://example-ecommerce.com/products']
def parse(self, response):
products = response.xpath('//div[@class="product"]')
for product in products:
name = product.xpath('.//h2/text()').get()
price = product.xpath('.//span[@class="price"]/text()').get()
yield {'name': name, 'price': price}
# 次のページがあればリクエストを続行
next_page = response.xpath('//a[@class="next-page"]/@href').get()
if next_page:
yield scrapy.Request(url=next_page, callback=self.parse)トラブルシューティングとよくあるエラー
スクレイピング中にはさまざまな問題やエラーが発生することがあります。ここでは、よくあるエラーとその対処法をいくつか紹介します。
エラー 1: 403 Forbidden
原因: サイトがあなたのクローリングをブロックしている可能性があります。これは、リクエストに適切なヘッダー(特にUser-Agent)が含まれていない場合によく発生します。
対策: リクエストにUser-Agentを追加して、ブラウザからのアクセスであるかのように見せかけることができます。
# settings.py
USER_AGENT = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.36'エラー 2: 404 Not Found
原因: リンク切れやページが存在しない場合に発生します。特に、次のページが存在しない場合にこのエラーが出ることがあります。
対策: next_pageリンクが取得できているか確認し、ページが存在する場合にのみリクエストを送るようにします。
# リクエストの前にチェック
if next_page:
yield scrapy.Request(url=next_page, callback=self.parse)エラー 3: メモリの使用量が増えすぎる
原因: 大量のデータをスクレイピングする際にメモリが枯渇することがあります。これは、クローリングが長時間続いた場合や大量のリクエストが並行して行われるときに発生します。
対策: CloseSpider拡張機能やAutoThrottleを使用して、クローリングの頻度や終了条件を設定することで、メモリの使用量を管理します。また、保存済みのデータを定期的に削除することも有効です。
# settings.py
CLOSESPIDER_ITEMCOUNT = 1000 # 1000件のアイテムを取得後にクローラーを停止エラー 4: スクレイピング対象がJavaScriptで生成される
原因: サイトのコンテンツがJavaScriptで動的に生成される場合、Scrapyのデフォルト機能だけではデータを取得できません。
対策: こうした場合、Scrapyに加えてSeleniumやSplashといったツールを組み合わせることで、JavaScriptを処理した後のHTMLを取得できます。
# settings.py
DOWNLOADER_MIDDLEWARES = {
'scrapy_selenium.SeleniumMiddleware': 800,
}
# Seleniumをインストールして使用する例
from scrapy_selenium import SeleniumRequest
class MySpider(scrapy.Spider):
def start_requests(self):
yield SeleniumRequest(url="http://example.com", callback=self.parse)成功したプロジェクトのベストプラクティス
スクレイピングを成功させるためのいくつかのベストプラクティスも紹介します。
- リクエストの頻度を制御
サーバーに負担をかけず、ブロックされないようにDOWNLOAD_DELAYやAutoThrottleを設定します。 - クローリングの規模を管理
クローリング対象のページ数やアイテム数を制限し、効率的にデータを収集する。 - 正確なデータ取得
データの正確性を確保するために、必要に応じてカスタムのデータクリーニングを行うパイプラインを作成します。
これで、具体的なScrapyのプロジェクト例と、よくあるトラブルに対処する方法を学びました。最後に、Scrapyを使うメリットや限界、次に進むステップについてまとめます。
まとめ
Scrapyは、Pythonで効率的にウェブスクレイピングを行うための強力なフレームワークです。並列処理やパイプライン機能などを活用することで、大量のデータを短時間で収集し、さまざまな形式で保存することができます。また、ロボット排除規則に従ったクローリングや、カスタマイズ可能なパイプラインでのデータ処理、クローリングの速度調整機能など、柔軟で効率的なスクレイピングが可能です。
Scrapyを使うメリット
Scrapyの限界
一方で、Scrapyにも限界があります。特に、JavaScriptによって動的に生成されるコンテンツのスクレイピングは難しく、SeleniumやSplashのような追加ツールを必要とする場合があります。また、複雑なフォーム操作や動的なウェブページのインタラクションを行う場合には、より強力なブラウザ自動化ツールの併用が必要です。
次のステップ
Scrapyの基本的な使い方に慣れたら、次のステップとして以下のことを試してみると良いでしょう。
- Splashとの統合
JavaScriptを使った動的コンテンツのスクレイピングに挑戦する。 - データベース統合
スクレイピングしたデータをMySQLやPostgreSQLなどのデータベースに直接保存し、より大規模なデータ処理に取り組む。 - 分散クローリング
複数のマシンやクラウド環境でScrapyを分散実行し、大量のデータを高速に収集する。 - カスタムミドルウェアやパイプラインの作成
より高度なデータ処理やクローリングロジックを実装するために、カスタムコンポーネントを開発する。
以上で、Scrapyの使い方に関するガイドは終了です。このガイドを通じて、Scrapyの基本的な使い方や、高度なクローリング手法を理解できたと思います。次のステップとして、実際のプロジェクトに挑戦し、さらなるスキルを磨いていきましょう。

ここまで読んでいただきありがとうございます!
UdemyのPythonコースにはオンラインで学習ができる動画コンテンツがたくさんあります。
当ブログのような文章メインの説明では足りない箇所を補えると思うので、もっと詳しく勉強したいという方はぜひチェックしてみてください!


コメント