アイテムを使用してデータをカプセル化
前回作成したスパイダーで取得した書籍情報はprint出力のみでした。今回はItemを使用してデータ構造を定義し、後続処理に渡せるようにします。まずitems.pyに以下のようなクラスを定義します:
import scrapy
class DangdangBookItem(scrapy.Item):
# 書籍画像URL
image_url = scrapy.Field()
# 書籍タイトル
book_title = scrapy.Field()
# 著者名
author = scrapy.Field()
# 価格情報
price = scrapy.Field()
# 商品説明
description = scrapy.Field()
スパイダー側ではこのアイテムクラスをインポートして使用します:
from scrapy_dangdang.items import DangdangBookItem
取得したデータをアイテムに詰め直す処理は以下の通りです:
product_item = DangdangBookItem(
image_url=image_src,
book_title=title_text,
author=author_name,
price=current_price,
description=detail_text
)
yieldによるデータパイプライン連携
Scrapyではyieldキーワードを使ってアイテムをパイプラインに逐次送信します。これは大量データ処理時のメモリ効率向上に重要です。以下のようにループ内でyieldを使用します:
for item in items_list:
# データ加工処理...
yield product_item
パイプラインによるデータ保存
settings.pyでパイプラインを有効化します:
ITEM_PIPELINES = {
'scrapy_dangdang.pipelines.DangdangJsonPipeline': 300,
}
パイプライン実装例(JSON出力):
import json
class DangdangJsonPipeline:
def open_spider(self, spider):
self.file = open('books_data.json', 'w', encoding='utf-8')
def process_item(self, item, spider):
line = json.dumps(dict(item), ensure_ascii=False) + "\n"
self.file.write(line)
return item
def close_spider(self, spider):
self.file.close()
複数パイプラインの実装
画像ダウンロード用パイプラインの追加例:
import os
import requests
class DangdangImagePipeline:
def process_item(self, item, spider):
if item.get('image_url'):
image_dir = 'book_images'
os.makedirs(image_dir, exist_ok=True)
image_path = os.path.join(image_dir, f"{item['book_title']}.jpg")
response = requests.get('http:' + item['image_url'])
with open(image_path, 'wb') as f:
f.write(response.content)
return item
settings.pyでの複数パイプライン設定:
ITEM_PIPELINES = {
'scrapy_dangdang.pipelines.DangdangJsonPipeline': 300,
'scrapy_dangdang.pipelines.DangdangImagePipeline': 301,
}