Qiita Teams that are logged in
You are not logged in to any team

Log in to Qiita Team
Community
OrganizationEventAdvent CalendarQiitadon (β)
Service
Qiita JobsQiita ZineQiita Blog
6
Help us understand the problem. What are the problem?

More than 1 year has passed since last update.

@sawa---i

特定サイトのURL一覧を無用な負荷をかけずに取得する

前書き

サイト制作や保守運用に関わっている方向けのお話。

特定サイト内にある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一覧を作成できるかなと考えました。

スクレイピングはとても便利ですので色々と試して見たくなるものですが、
無用な負荷はかけずに、節度を持って利用することを常に意識したいと思います。

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
6
Help us understand the problem. What are the problem?