前書き
サイト制作や保守運用に関わっている方向けのお話。
特定サイト内にあるURLを、
全件一覧にして提供してほしいと言ったオーダーが時々あります。
ただ、こうした一覧をWeb担当者が持ち合わせていないことも多かったり。
何がしたいのか
特定サイトのURL一覧を、
無用な負荷をかけずにスクレイピングしてURL一覧をつくりたい、
と考えました。
やったこと
「無用な負荷をかけずにスクレイピングする」は、
「リクエスト数を減らして覗かせていただく」のと同義になってくるのかなと思います。
方法を2つ考えました。
1. サイトマップのページを覗く
大抵のサイトにある「サイトマップ」のページ。
ここにはアクセス者に向けて、該当サイトの全リンクが掲載されていることが多いです。
こちらを覗かせてもらいます。
実装はPython 3.x。
スクレイピング用にBeautifulSoupを利用しています。
https://www.crummy.com/software/BeautifulSoup/bs4/doc/
from bs4 import BeautifulSoup
import requests
r = requests.get("https://xxxxxx......zzzzz/sitemap/")
c = r.content
href = ''
path = './output.txt'
bs = BeautifulSoup(c, "html.parser")
a_list = bs.select("a")
for a in a_list:
href += a.attrs['href'] + '\n'
with open(path, mode='w') as f:
f.write(href)
該当ページへリクエストした後は、
得たコンテンツの「Aタグ」を抜き出して、
href要素のみを引っ張り出し、改行を加えてテキスト出力します。
a_list = bs.select("a")
for a in a_list:
href += a.attrs['href'] + '\n'
上記はシンプルにしていますが、
実際には覗かせていただくサイトの実装に合わせて、
探す要素を工夫する必要はでてくると思います。
あと、引っ張り出したものが、
相対パス定義のURLだったりすると、
プラスαで修正する必要もあります。
ただ、リクエスト数は「サイトマップ」のページ1回だけ。
無用な負荷をかけずに済むのではないでしょうか。
2. XMLサイトマップを覗く
SEO対策などで、
該当サイトにXMLサイトマップを入れ込んでいる場合は、
これを利用してURLを抜き出すのが便利だと思います。
参考:Google サイトマップの作成と送信
https://support.google.com/webmasters/answer/183668?hl=ja
XMLサイトマップの基本的な構成は、以下のようになると思います。
<?xml version="1.0" encoding="UTF-8"?>
<urlset xmlns="https://xxxxxx......zzzzz/sitemap/">
<url>
<loc>https://xxxxxx......zzzzz/sample.html</loc>
<lastmod>2019-07-17</lastmod>
<changefreq>test</changefreq>
<priority>0.8</priority>
</url>
</urlset>
URLはAタグではなく、locタグで定義されています。
これを抜きだせば良さそうです。
先ほど同様に実装はPython 3.x。
スクレイピング用にBeautifulSoupを利用しています。
from bs4 import BeautifulSoup
import requests
import re
path = ‘./output.txt'
r = requests.get("https://xxxxxx......zzzzz/sitemap.xml")
c = r.content
urls = ''
bs = BeautifulSoup(c, "html.parser")
loclist = bs.select("loc")
for loc in loclist:
urls += re.sub('<[a-z]>', '', loc.text)
urls += '\n'
with open(path, mode='w') as f:
f.write(urls)
先ほどと大体同じですが、
URLはlocタグに囲まれたテキスト担っているので、
タグを正規表現で指定して消すようにしました。
for loc in loclist:
urls += re.sub('<[a-z]>', '', loc.text)
urls += '\n'
pythinで正規表現を使って文字の置換対象を指定するなら、
replace じゃなくて re.sub を使いましょう。
また、もしローカルでサイトマップXMLを入手できるなら、
上記のようにリクエストを飛ばさず、ローカルでファイルを覗く方が良いでしょう。
まとめ
上記方法であれば、どちらもリクエスト数は1回で済むので、
無用な負荷をかけることなくURL一覧を作成できるかなと考えました。
スクレイピングはとても便利ですので色々と試して見たくなるものですが、
無用な負荷はかけずに、節度を持って利用することを常に意識したいと思います。