scrapyで生成される各種.pyファイルについて考える
scrapyについては「10分で理解する Scrapy」という名記事がQiita内にあるので、基本的にそれを参考にしていただくのが最適な方法です。しかし、私にはscrapyで扱う各種.pyファイルのコードの意味がわからないので、自分がしたいことにはすぐに転用できませんでした。と言うことで、scrapyで使用する.pyファイルの意味を少しずつ意味を理解するための初歩的な記事となります。
gooブログに投稿している「ひげめがね日記」というタイトルを取得することを目標としました。
##0.環境
環境は、Windows10Home 64bitにpython3.9.6をインストールし、Windows PowerShellでコーディング、実行しています。
以下のコードを実行するためには scrapyのインストールがが必要です。
詳細は「10分で理解する Scrapy」を参考にしてください。
##1.プロジェクトの作成
まず、"higeme"というプロジェクトを作成しました。
$ scrapy startproject higeme
New Scrapy project 'higeme', using template directory
...
You can start your first spider with:
cd higeme
scrapy genspider example example.com
##2.Spiderの追加
上記のとおり親切にも、「最初にこうすれば良いよ」というガイドが出てくるので、そのとおりやってみます。まずcdコマンドでフォルダ移動します。
$ cd higeme
次に"scrapy genspider example example.com"の部分についてですが、これは「ドメイン名"example.com"(絶対参照のURLで書くと"http(s)://example.com"というサイト)をクロールするためのSpiderの名前を"example”とする」ということを意味しています。今回は「ひげめがね日記:https://blog.goo.ne.jp/higeme_1015」というサイトをクロールしますので、ドメイン名は"blog.goo.ne.jp"となります。そしてSpider名は"scrapy_higeme"とします。以上を反映させると以下のようになります。
$ scrapy genspider scrapy_higeme blog.goo.ne.jp
Created spider 'scrapy_higeme' using template 'basic' in module:
higeme.spiders.scrapy_higeme
これで\higeme\spidersフォルダにscrapy_higeme.pyというファイルが作成されました。実際にtreeコマンドで見てみると、
$ tree /f
フォルダー パスの一覧: ボリューム Windows
ボリューム シリアル番号は E426-2CEE です
C:.
│ scrapy.cfg
│
└─higeme
│ items.py
│ middlewares.py
│ pipelines.py
│ settings.py
│ __init__.py
│
├─spiders
│ │ scrapy_higeme.py
│ │ __init__.py
│ │
│ └─__pycache__
│ __init__.cpython-39.pyc
│
└─__pycache__
settings.cpython-39.pyc
__init__.cpython-39.pyc
scrapy_higeme.pyが作成されたことが確認できます。
初心者にとっては、こんなにすぐファイルが生成されることに驚きです。scrapyは優れたパッケージだと感じます。
##3.setting.pyの設定変更
higemeフォルダ内のsetting.pyの記述を変えます。やることは「コメントアウトを外す("#"の削除)」だけなので簡単です。
外す箇所はまず"DOWNLOAD_DELAY = 3"の部分。頻繁にアクセスしすぎてDos攻撃と間違えられないようにする設定のようです。私の設定では28行目にありました。
# Configure a delay for requests for the same website (default: 0)
# See https://docs.scrapy.org/en/latest/topics/settings.html#download-delay
# See also autothrottle settings and docs
DOWNLOAD_DELAY = 3
# The download delay setting will honor only one of:
#CONCURRENT_REQUESTS_PER_DOMAIN = 16
#CONCURRENT_REQUESTS_PER_IP = 16
次に"HTTPCACHE"から始まる最後の5行をコメントアウトします。これはキャッシュを有効にするための設定のようです。
# Enable and configure HTTP caching (disabled by default)
# See https://docs.scrapy.org/en/latest/topics/downloader-middleware.html#httpcache-middleware-settings
HTTPCACHE_ENABLED = True
HTTPCACHE_EXPIRATION_SECS = 0
HTTPCACHE_DIR = 'httpcache'
HTTPCACHE_IGNORE_HTTP_CODES = []
HTTPCACHE_STORAGE = 'scrapy.extensions.httpcache.FilesystemCacheStorage'
##4.items.pyの設定
higemeフォルダ内のitems.pyの記述を変えます。当初は以下のような記述になっています。
import scrapy
class HigemeItem(scrapy.Item):
# define the fields for your item here like:
# name = scrapy.Field()
pass
まず、クラス名("class"の後ろに記載する名称)についてです。この名前は何でも良いそうです。このままでも問題ないと思いますが"Higeme"ばかりだとわかりづらくなるので、わかりやすいようあえて"Hogehoge"としました。このクラス名が後に設定するspidersフォルダ内のpyファイルの記述に対応させる必要があります。このため、このクラス名は覚えておく必要があります。
次に今回はブログのタイトルを取得することが目的なので、"title"というフィールドを用意します。今回はURLを指定するので意味がないですが、まあ練習のために"url"も取得するようにそのフィールドも用意しました。以上を反映させると以下のようにitem.pyを書き換えられます。
import scrapy
class Hogehoge(scrapy.Item):
title = scrapy.Field()
url = scrapy.Field()
##5.spidersフォルダ内の.pyファイルの設定
spidersフォルダ内にある.pyファイルを書き換えます。私の場合はscrapy_higeme.pyというファイルになっています。当初は大体下記のような記述になっていると思います。
import scrapy
class ScrapyHigemeSpider(scrapy.Spider):
name = 'scrapy_higeme'
allowed_domains = ['blog.goo.ne.jp']
start_urls = ['http://blog.goo.ne.jp/']
def parse(self, response):
pass
これを以下のように書き換えます。
import scrapy
# higeme\item.py の class"Hogehoge" をimportする
from higeme.items import Hogehoge
class ScrapyHigemeSpider(scrapy.Spider):
name = 'scrapy_higeme'
allowed_domains = ['blog.goo.ne.jp']
#タイトルを取得するURLの指定
start_urls = ['http://blog.goo.ne.jp/higeme_1015']
def parse(self, response):
# class"Hogehoge"のitemに結果を格納する
item = Hogehoge()
item['title'] = response.css('title::text').extract_first()
item['url'] = response.url
# itemを出力する
yield item
コメント行にそれぞれの説明を付記してあるとおりですが、念のため説明を。
3行目の"higeme.items"は、higemeフォルダ内のitems.pyファイルを意味しています。importの後にはitems.py内のクラス名を記載します。先ほどわかりやすいように設定した"Hogehoge"を記載します。
9行目はクローリングを始める最初のURLの指定です。今回は巡回するのではなく単一のページからタイトルを取得することが目標なので、ずばり取得したいページのURLを記載しました。
13行目、item = の後はやはりクラス名"Hogehoge"が入ります。
14~15行目は、「Scrapy を使ってクローリング・スクレイピングしてみる」を参考にしました。とりあえずこう書くもののようです。ここは今後学習が必要ですが、responseで取得、格納するのでしょうね。
最終行はitemを出力するという意味だそうです。
##6.実行、出力
下記1行目のように実行すると、大量なアウトプットが生成されますが、確かに'ひげめがね日記'というタイトルを取得することができました。
$ scrapy crawl scrapy_higeme
2021-08-08 07:04:40 [scrapy.utils.log] INFO: Scrapy 2.5.0 started (bot: higeme)
...
2021-08-08 07:04:45 [scrapy.downloadermiddlewares.redirect] DEBUG: Redirecting (301) to <GET https://blog.goo.ne.jp/higeme_1015> from <GET http://blog.goo.ne.jp/higeme_1015>
2021-08-08 07:04:47 [scrapy.core.engine] DEBUG: Crawled (200) <GET https://blog.goo.ne.jp/higeme_1015> (referer: None) ['cached']
2021-08-08 07:04:47 [scrapy.core.scraper] DEBUG: Scraped from <200 https://blog.goo.ne.jp/higeme_1015>
{'title': 'ひげめがね日記', 'url': 'https://blog.goo.ne.jp/higeme_1015'}
2021-08-08 07:04:47 [scrapy.core.engine] INFO: Closing spider (finished)
...
最後に、ページタイトルを取得するだけであれば、scrapyより簡便にできる方法がありますので、必要な方はほかのページを参考にしてください、ということを付記いたします。