webページのsitemap.xmlからそのドメイン以下にあるURLの一覧を取得し、各ページをたどって情報を取得するクローラーを作ってみました。
XMLサイトマップを利用してクロールする際には、ScrapyのsitemapSpiderを使うと楽です。
・クローラー作成の際は、絶対に後述の「クロール先に迷惑をかけないための設定」を行ってください。これを怠ると普通に逮捕されたりします。
(クローラーは全く違法なものではないですし、Googleをはじめとするあらゆる企業や個人などに利用されていますが、使用方法をミスると結果的に誰かのサーバーを攻撃した、みたいになることがあります)
・この記事を見て作成したクローラーにより生じたいかなる損害、不利益など、一切関知しませんし責任も負いかねます。
・記事のサンプルコードでは、クロール対象ドメインをこのブログのものにしています。しかし、僕のブログにはクローラー避けの対策がなされているので、これのコピペじゃデータ取得に失敗すると思います。適宜、クロールしても問題ないサイトのドメインに置き換えて実行してください。
・あとごめん、タイトルに「対象サイトの全ページのurlとタイトルを取得」とありますが、対象サイトのデータ形式によっては全ページ取れないこともあります。その時はぜひいいやり方を見つけて教えてください!
もくじ
XMLサイトマップとはなんぞ?
ざっくり言うと、そのサイトに含まれる記事(URL)の全リストです。
各記事について、URL以外にも最終更新日、更新頻度、重要度などの情報が含まれており、これらをXML形式で記述しているものです。
XMLサイトマップの例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
<?xml version="1.0" encoding="UTF-8"?> <urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">; <url> <loc>http://www.example.com/</loc>; <lastmod>2005-01-01</lastmod> <changefreq>monthly</changefreq> <priority>0.8</priority> </url> (引用者によって中略) <url> <loc>http://www.example.com/catalog?item=83&desc=vacation_usa</loc>; <lastmod>2004-11-23</lastmod> </url> </urlset> |
Webの文脈で一般に「サイトマップ」という言葉が使われる際には、それが指すものは2種類あります。
①サイトマップ(人間用に見やすくフォーマットしてる記事一覧)
②XMLサイトマップ(機械というかプログラムが読みやすいフォーマットで書かれたもの)
これらは混同されがちですが全く異なるもので、両方めっちゃ大事です。
当ブログで言えば、
①サイトマップ(人間用に見やすくフォーマットしてる記事一覧)
→https://sutaba-mac.site/sitemap/
②XMLサイトマップ(機械というかプログラムが読みやすいフォーマットで書かれたもの)
→https://sutaba-mac.site/sitemap.xml/
と、それぞれ全く違うフォーマットで書かれていることが分かるかと思います。
今回の記事で扱うのは後者、②XMLサイトマップ(機械というかプログラムが読みやすいフォーマットで書かれたもの)になります。
これは主にGoogleのクローラーにサイトの内容を伝えるためのもので、SEO的に非常に重要です。
XMLサイトマップをクロールする
今回はScrapyのsitemapSpiderを使います。楽そうなので。
Scrapyって何?って方はまずこちらを。
Scrapyのインストール
もし、Scrapyがインストールされていなければ、まずはpipを使ってインストールしてください。
仮想環境を立てる
Scrapyのインストールの際には、まず仮想環境を立てることが推奨されています。
まず、下記のコマンドでvirtualenvを使って仮想環境を用意します。
仮想環境を使いたいプロジェクトのディレクトリに移動し、下記のコマンドで仮想環境を作成します。
仮想環境の名前(myenv)はなんでもokです。
次のコマンドで、作成した仮想環境をアクティベートします。
コンソールで行頭に(myenv)のように表示されればokです。
次に、pipでScrapyをインストールします。
下記のコマンドを打って、scrapyのバージョンが表示されればインストール成功です。
scrapyプロジェクトの作成
プロジェクトのディレクトリに移動しておきます。
genspiderコマンドでspiderを作成します。
genspiderコマンドの引数にはそれぞれ、
scrapy genspider [spiderの名前] [クロール対象のドメイン]
を指定します。
すると、spiderディレクトリ内に下記のようなspiderのテンプレが生成されているはずです。
1 2 3 4 5 6 7 8 9 10 11 |
# -*- coding: utf-8 -*- import scrapy class SitemapSpider(scrapy.Spider): name = 'sitemap' allowed_domains = ['sutaba-mac.site'] start_urls = ['http://sutaba-mac.site/'] def parse(self, response): pass |
これを、下記のように変更します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
# -*- coding: utf-8 -*- # SitemapSpiderをインポート from scrapy.spiders import SitemapSpider class SitemapSpider(SitemapSpider): name = 'sitemap' allowed_domains = [ 'sutaba-mac.site', ] # XMLサイトマップをリスト形式で指定。 # '/sitemap.xml' sitemap_urls = [ ‘https://sutaba-mac.site/robots.txt', ] # 抜き出したデータの処理をする def parse(self, response): # URLとタイトルの辞書(dictionary)を返す yield { 'url': response.url, 'title': response.css('title::text').extract_first(), } |
sitemap_urls のリストで、「 XMLサイトマップをリスト形式で指定。」とコメントしてるにもかかわらず、思いっきり”robots.txt”という関係なさそうなurlを指定してますが、robots.txtの中身にはXMLサイトマップの場所が書かれていることがあるので、これを指定してもOKです。
もちろん、素直にsitemap.xmlを指定してもok。
また、robots.txtとsitemap.xmlを同時に指定した場合でも”no more duplicates will be shown”(ダブったやつはもう表示しねえからな)とのメッセージが出たので問題なさそうではある。
クロール先に迷惑をかけないための設定(重要)
settings.pyを開いて、以下の3行を探してください。
デフォルトではコメントアウトされていることがあるので、忘れずにコメントを外して有効にしておきましょう。
これをしないで、クロール先に迷惑をかけた場合、最悪逮捕されるのでマジで注意です。
1 2 3 4 5 |
# クロールする間隔の調整(秒数で指定、この場合は3秒リクエスト間隔をあけることになる) DOWNLOAD_DELAY = 3 # robots.txtの指示に従う設定。クロール禁止のURLやクロール間隔の指定などが記述されている場合がある。 ROBOTSTXT_OBEY = True |
それから、ユーザーエージェントの設定に自分の連絡先を明示しておくのがベターです。
1 |
USER_AGENT = ‘sitemapExplorer (twitter: @sutaba_mac)' |
クロールの実行
下記のコマンドでクロール実行。
-o オプションを使うと、実行結果を.txt, csvなどの形式で出力できます。
うまくいってたら、sitamaps.csvって名前のファイルに実行結果が格納されてるはず。
課題とか手をつけれなかったものとか
・sitemaps.org – プロトコルに載ってるフォーマットに従ったサイトマップのクロールはできるっぽいが、表記ゆれの検証(そもそも、そんなにフォーマットのバリエーションあるのか調査とか)できていない。
・sitemap_rules, sitemap_followなどの設定でもう少し細かくクロールを制御できるが、そこの設定は今回飛ばした。
・個人のサイトやブログなど、小規模なものは今回のコードで行けるが、記事数がめっちゃ多い巨大なサイト(ニュースサイトとか)だと多分sitemap.xmlに全アーカイブはなさそう(1日分とか1週間分とかのレベルで切り分けるはず)なので、そういうケースの対処は知らない。
参考にしたもの、ページ
スパイダー — Scrapy 1.2.2 ドキュメント
virtualenv 基本的なコマンド使い方メモ – Qiita
User Guide — virtualenv 16.0.0 documentation
sitemaps.org – プロトコル