概要
webサイトに貼り付けられているCSVファイルやExcel、PDFファイルなどをリストアップするために作成。
基点となるURLを指定し、その中にあるリンクを再帰的に辿ってリンクのリスト、データファイルのリストをそれぞれTSVで出力。
使い方
・「base_url」に基点となるURLを設定。サイトマップとか。
・「def_recur_srch_cnt」で再帰探索する回数を指定。
・必要に応じてページ内で検索対象にするタグ、抽出対象とするURLのフィルタ条件を変更
ソースコード
import sys
import re
import time
import requests
from bs4 import BeautifulSoup
from urllib.parse import urljoin
# url = sys.argv[1]
headers = {"User-Agent": "Mozilla/5.0 (X11; Linux x86_64; rv:57.0) Gecko/20100101 Firefox/57.0",}
# リンクを再帰探索する数
def_recur_srch_cnt = 10
# ベースURL
base_url = "https://www.hogehoge.jp/sitemap.html"
# ファイル出力先フォルダ
out_dir = "C:\\work\\tmp\\"
# ファイル名
out_fname_dl = "datalink.txt"
out_fname_pl = "pagelink.txt"
out_fname_tl = "tableaulink.txt"
out_fname_ck = "checked_url.txt"
# 変数初期化
search_urls = []
checked_urls = []
tmp_urls = []
search_urls.append(base_url)
#ファイルオープン
f_dl = open(out_dir + out_fname_dl, "w", encoding='UTF-8')
f_pl = open(out_dir + out_fname_pl, "w", encoding='UTF-8')
f_tl = open(out_dir + out_fname_tl, "w", encoding='UTF-8')
# 初期設定で定義した数だけURL階層を再帰的に検索
for i in range(def_recur_srch_cnt):
for url in search_urls:
# 既にチェックしたURLでなければ処理を実行
if not(url in checked_urls):
try:
rr = requests.get(url, headers=headers)
html = rr.content
soup = BeautifulSoup(html, "html.parser")
# ページタイトルの取得
pagetitle = soup.head.title.get_text()
# リンク先抽出対象となるメインコンテンツ部分の指定
elements = soup.body.find("div", id="main")
except Exception as ee:
sys.stderr.write("*** error *** in requests.get ***\n")
sys.stderr.write(str(ee) + "\n")
try:
# ページリンクの抽出
# .htm又は.htmlのページを対象とするが、"?!"に続くディレクトリを含むものは除外
for aa in elements.find_all("a", href=re.compile(r'^(?=^(https://www.hogehoge.jp|/|\.+/).*html?[^\.]*$)(?!.*/(en|press)/.*)')):
# 改行をスペースに置換の上、ドメイン名を省略している場合は付加
link = re.sub(r'\n', " ", aa.get("href"))
# さらに相対パスの場合は検索対象ページのURLを絶対パスに変換
if link.startswith(".") or link.startswith("/"):
link = urljoin(url, link)
# リンク名取得
name = re.sub(r'\n', " ", aa.get_text())
# ファイル出力
f_pl.write(str(i) + "\t" + url + "\t" + pagetitle + "\t" + link + "\t" + name + "\n")
# アンカータグを削除した上で一時URLリストに追加
tmp_urls.append(re.sub(r'#.+$', "", link))
# データファイルへのリンクの抽出
for aa in elements.find_all("a", href=re.compile(r'.*\.(csv|CSV|xlsx?|XLSX?|docx?|DOCX?|pptx?|PPTX?|pdf|PDF)$')):
datalink = re.sub(r'\n', " ", aa.get("href"))
datatype = re.sub(r'.*\.', "", datalink)
dataname = re.sub(r'\n', " ", aa.get_text())
f_dl.write(str(i) + "\t" + url + "\t" + pagetitle + "\t" + datatype + "\t" + datalink + "\t" + dataname + "\n")
except Exception as ee:
sys.stderr.write("*** error *** in BeautifulSoup ***\n")
sys.stderr.write(str(ee) + "\n")
# 抽出したリンク情報を重複削除の上で検索対象URLリストに追加)
tmp_urls.sort()
search_urls = list(set(tmp_urls))
# チェック済URLとしてリストに追加
checked_urls.append(url)
# Sleep 2秒
time.sleep(2)
#ファイルクローズ
f_dl.close()
f_pl.close()
f_tl.close()
# join()で要素内容を結合
s = "\n".join(checked_urls)
with open(out_dir + out_fname_ck, "w", encoding='UTF-8') as f:
# 書き込み
f.write(s)
特定のタグを指定する方法もある。
for aa in elements.find_all("div", class_="class_name"):
id = aa.attrs['id']
name = aa.noscript.a.img.attrs['alt']
f_tl.write(str(i) + "\t" + url + "\t" + id + "\t" + name + "\n")
参考URL