再帰的なsitemap.xmlからページ一覧を取得する方法

アキ＠IT業界の歩き方です。
[株式会社アスターリンク](https://www.aster-link.co.jp/)に在籍し、ITエンジニアやSEO担当をしています。
今回はSEOの調査でめんどくさいと思ったことと、簡易的な対処法を紹介していきます。

SEOの調査をする時に、ページ一覧を取得したいと思ったことはありませんか？
例えばページ一覧を取得できれば、下記の調査が進みます。
- ページURL
- TDKh1（title、description、keywords、h1）
- アンカータグのURLやアンカーテキストの取得

他にもホームページ制作のリニューアル案件で、手っ取り早く見積もりを出すために、ページ一覧を知りたいといった事があるでしょう。
では、どのようにページ一覧を取得すればよいのでしょうか？
# 手っ取り早くページ一覧を取得するにはsitemap.xmlから取得する
ページ一覧を取得するにはsitemap.xmlからの取得が手っ取り早いでしょう。
一般的なWebサイトであれば下記のURLにsitemap.xmlが存在します。
>https://example.com/sitemap.xml

上記URLに主要なページ一覧が表示されるため、一発で取得できます。
あとは、[XMLからCSVへ変換するWebサービス](https://onlineconvertfree.com/ja/convert-format/xml-to-csv/)などを利用して、Excelで処理が可能です。
# WordPressサイトのsitemap.xmlは簡単にページ一覧を取得できない
ところがWordPressサイトの場合はsitemap.xmlから簡単にページ一覧を取得できないケースが多いです。
なぜなら、sitemap.xmlの中身が下記の様になるためです。

```xml:https://shigoto-web.co.jp/tensyoku/sitemap.xml
<sitemapindex xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.sitemaps.org/schemas/sitemap/0.9 http://www.sitemaps.org/schemas/sitemap/0.9/siteindex.xsd" xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">	<sitemap>
		<loc>https://www.shigoto-web.co.jp/tensyoku/sitemap-misc.xml</loc>
		<lastmod>2022-04-28T06:53:58+00:00</lastmod>
	</sitemap>
	<sitemap>
		<loc>https://www.shigoto-web.co.jp/tensyoku/sitemap-pt-post-2022-04.xml</loc>
		<lastmod>2022-04-28T05:58:46+00:00</lastmod>
	</sitemap>
	<sitemap>
		<loc>https://www.shigoto-web.co.jp/tensyoku/sitemap-pt-post-2022-03.xml</loc>
		<lastmod>2022-04-27T04:15:25+00:00</lastmod>
	</sitemap>
（省略）
```
loc要素にページのURLが来るかと思いきや、xmlのURLが指定されています。
つまり、再帰的に取得しなければ、ページ一覧を取得できないのです。

実はWordPressは標準の機能でsitemap.xmlは出力されず別途プラグインを用いることとなります。
その中でも有名なプラグインが「Google XML Sitemaps」であるため、WordPressサイトのsitemap.xmlが上記のような結果になるケースが多いというわけです。

sitemap.xmlのloc要素にxmlが指定される形式は、[大きなサイトマップを分割するためにの仕組み](https://developers.google.com/search/docs/advanced/sitemaps/large-sitemaps?hl=ja)が利用されています。
無数にあるxmlにアクセスして連結する作業は、さすがにめんどくさいですね。

:::note info
余談ですが、「Google XML Sitemaps」はnoindexにした記事まで出力されるため、不便で結局、sitemap.xmlの出力機能を作ることになります。
この辺についてはいずれ、別記事で発信したいと思います。
:::

# sitemap.xmlをスクレイピングするコードを作って解決
結局、解決するにはsitemap.xmlをスクレイピングするコードを作って解決しました。
かんたんにコードを紹介します。
コードは何でも良かったのですが、スクレイピングしやすそうなpythonを選びました。
※pythonは、しっかり学んだことがなく、見様見真似で書いていますので、お気づきの点がありましたら他の閲覧者の方のためにもコメントでフィードバック頂けると嬉しいです。
```python:get_pages_by_sitemap.py
from bs4 import BeautifulSoup
import urllib.request as req
import os.path
import re

def parse_sitemap(url):
    savename = "delete-ok.text"
    if os.path.exists(savename):
        os.remove(savename)
    req.urlretrieve(url, savename)

    xml = open(savename, "r", encoding="utf-8").read()
    soup = BeautifulSoup(xml, 'html.parser')

    pages = [] 
    #ページリストを取得
    for i in soup.find_all("url"):
        loc = i.find('loc').string.strip()
        pages.append(loc)

    #sitemap.xmlが入れ子の場合は再帰的に呼び出す
    for i in soup.find_all("sitemap"):
        loc = i.find('loc').string.strip()
        pages.extend(parse_sitemap(loc))

    #後処理
    if os.path.exists(savename):
        os.remove(savename)

    return pages

if __name__ == '__main__':
    #sitemap.xmlを取得する
    url = "https://shigoto-web.co.jp/tensyoku/sitemap.xml"
    pages = parse_sitemap(url)

    print("--------------")
    for loc in pages:
        print(loc)
    print("--------------")

```
URLを任意に変更いただき実行すれば取得できると思います。

# 追記です

この記事で紹介した記事一覧の取得を用いて[SEOの調査プログラム](https://zenn.dev/it_aki/articles/8be4599568f453)をZennで紹介しましたので、合わせてご覧ください。

https://zenn.dev/it_aki/articles/8be4599568f453

# 追記：Githubにソースを公開しました

この記事のプログラムはGithubで公開しております。
ぜひご利用ください。

https://github.com/it-aki/research_pages


# 参考
アキ＠IT業界の歩き方はWeb制作やSEOコンサルティングを強みとしています。
メディア運営も得意で[しごとウェブ転職](https://www.shigoto-web.co.jp/tensyoku/)や[IT業界の歩き方](https://www.it-career-navi.com/)など運営しています。
ご依頼は[株式会社アスターリンク](https://www.aster-link.co.jp/)までどうぞ。