ScrapyでPOSTDの記事情報を抽出した
動機
最近「そうだWebアプリを作ろう」とぼんやり思っていたのですが、そのためにはPythonのWebクローラフレームワークであるScrapyが必要だと分かりました。
今回はScrapyの勉強のために、最近発見し読み始めたPOSTDさんの記事をクローリングしてみました。
やったこと
Scrapyで記事一覧情報(タイトル、タグなど)を抽出し、JSONL形式でアウトプットした。
参考にしたWebサイト
Scrapy Tutorial 10分で理解する Scrapy
環境
$ python --version Python 3.6.8 :: Anaconda custom (64-bit)
$ scrapy version Scrapy 1.5.1
コーディング
実際にScrapyでクローラを作成してみます。
プロジェクトの作成
まずはプロジェクトを作ります。
$ scrapy startproject postd
Spiderの実装
Itemsの作成
まずitems.py
を編集します。
今回は記事の
- URL
- タイトル
- 日にち
- タグ
を抽出することにしたので、以下のようにItemsを定義します。
# -*- coding: utf-8 -*- import scrapy class ArticleItem(scrapy.Item): url = scrapy.Field() title = scrapy.Field() date = scrapy.Field() tags = scrapy.Field()
Spiderの追加
以下のようにSpiderを作成します。
scrapy genspider article postd.cc
作成されたarticle.py
を編集してparseをいじります。
# -*- coding: utf-8 -*- import scrapy from postd.items import ArticleItem class ArticleSpider(scrapy.Spider): name = 'article' allowed_domains = ['postd.cc'] start_urls = ['https://postd.cc/'] def parse(self, response): for article in response.css('.block-titles-wrap'): yield ArticleItem( url=article.css('div.block-titles a::attr(href)').get(), title=article.css('div.block-titles a::text').get(), date=article.css('div.block-titles div::text').get(), tags=article.css('div.block-text div div a::text').getall(), ) next_page = [i.split(' ')[1].split('\"')[1] for i in response.css( 'div.pagination div a.pagination-jump').getall() if 'Next' in i] if next_page != []: yield response.follow(next_page[0], callback=self.parse)
設定の編集
最後にクロールを実行する前にsettings.py
を編集します。
リクエスト間隔の設定
以下のようにコメントを外す。
# Configure a delay for requests for the same website (default: 0) # See https://doc.scrapy.org/en/latest/topics/settings.html#download-delay # See also autothrottle settings and docs DOWNLOAD_DELAY = 3
レスポンスのキャッシュの設定
以下のようにコメントを外す。
# Enable and configure HTTP caching (disabled by default) # See https://doc.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'
エンコードの設定
以下を追記する。
FEED_EXPORT_ENCODING='utf-8'
Spiderの実行
JSONL形式でアウトプットします。
$ scrapy crawl article -o articles.jl
これで無事にarticles.jl
に記事情報がアウトプットされました。
感想
今後やりたいこと
クロールを定期的に行う
今回クローリングすることができましたが、コマンドを入力しクローリングを開始している状態です。
「ある時間が来たらクローラを起動する」という風にしたいと思います。
アウトプットの形式
まだデータベースについて詳しくないのですが、データベースとして使いやすいようなアウトプットを調べたいです。
記事の書き方
とても久しぶりの記事で書く気力もあまりありませんでした。
気が向いたらもうちょっと追記したいと思います。
Scrapyについて
settings.pyの記法
デフォルトで生成されるsettings.py
の行の長さやコメントの表記が、Pythonのコーディング規約のPEP8に準拠していないのはPythonフレームワークとしてどうなのかなぁと思いました。