経緯
ほぼ前回の続きです
webページのソースをディレクトリそのままにスクレイピング、
詳しく述べると、
https://www.hoge.com/huga/hoge/index.html
とhttps://www.hoge.com/huga/index.html
のソースをまとめて取得するとき、
ドメイン名をトップディレクトリとし、
└── www.hoge.com
└── huga
├── hoge ── index.html
└── index.html
のようにしてローカルに持ってきました
このHTMLソース群の中からリンク(aタグのhref要素やimgタグのsrc要素など)を抽出したいと考えました
スクレイピングする時にわざわざソースをローカルに落とさずに直で抽出すればいいじゃんというツッコミは無しでお願いします
とりあえず思いつくままに書く
from bs4 import BeautifulSoup
import os
def fileGetLink(path):
if os.path.isdir(path):
fileList = os.listdir(path)
for file in fileList:
fileGetLink(os.path.join(path, file))
else:
soup = BeautifulSoup(open(path, encoding='utf-8'), 'html.parser')
for link in soup.find_all("a"): # aタグを取得
with open('./hogeLink.txt', "a", encoding='UTF-8', newline='\n') as f:
if link.get("href") is None:
continue
f.write(link.get("href") + "\n")
for link in soup.find_all("img"): # imgタグを取得
with open('./hogeLink.txt', "a", encoding='UTF-8', newline='\n') as f:
if link.get("src") is None:
continue
f.write(link.get("src") + "\n")
for link in soup.find_all("link"): # linkタグを取得
with open('./hogeLink.txt', "a", encoding='UTF-8', newline='\n') as f:
if link.get("href") is None:
continue
f.write(link.get("href") + "\n")
for link in soup.find_all("script"): # scriptタグを取得
with open('./hogeLink.txt', "a", encoding='UTF-8', newline='\n') as f:
if link.get("src") is None:
continue
f.write(link.get("src") + "\n")
fileGetLink('./www.hoge.com')
冗長だなあ
解説
def fileGetLink(path):
if os.path.isdir(path):
fileList = os.listdir(path)
for file in fileList:
fileGetLink(os.path.join(path, file))
再帰検索してます
ファイルだったら処理、フォルダだったら検索、というのを繰り返しています
soup = BeautifulSoup(open(path, encoding='utf-8'), 'html.parser')
for link in soup.find_all("a"): # aタグを取得
with open('./hogeLink.txt', "a", encoding='UTF-8', newline='\n') as f:
if link.get("href") is None:
continue
f.write(link.get("href") + "\n")
for link in soup.find_all("img"): # imgタグを取得
with open('./hogeLink.txt', "a", encoding='UTF-8', newline='\n') as f:
if link.get("src") is None:
continue
f.write(link.get("src") + "\n")
for link in soup.find_all("link"): # linkタグを取得
with open('./hogeLink.txt', "a", encoding='UTF-8', newline='\n') as f:
if link.get("href") is None:
continue
f.write(link.get("href") + "\n")
for link in soup.find_all("script"): # scriptタグを取得
with open('./hogeLink.txt', "a", encoding='UTF-8', newline='\n') as f:
if link.get("src") is None:
continue
f.write(link.get("src") + "\n")
find_allでまとめて取得してhogeLink.txt
に書き出す処理です
NoneTypeで止まることあるので引っ掛けてcontinueしています
反省と修正
冗長過ぎてダサい
find_allの部分が冗長だなあと自分でも思いました
Beautiful Soupの公式ドキュメントを見ると、
タグを配列にして複数条件いけるおーとのことです
Recall from Kinds of filters that the value to name can be a string, a regular expression, a list, a function, or the value True.
soup = BeautifulSoup(open(path, encoding='utf-8'), 'html.parser')
for link in soup.find_all(["a","link"]):
with open('./hogeLink.txt', "a", encoding='UTF-8', newline='\n') as f:
if link.get("href") is None:
continue
f.write(link.get("href") + "\n")
for link in soup.find_all(["script","img"]):
with open('./hogeLink.txt', "a", encoding='UTF-8', newline='\n') as f:
if link.get("src") is None:
continue
f.write(link.get("src") + "\n")
こんな感じでスッキリしました
再帰処理いらない説
os.walk
というディレクトリ下のファイル全てを検索してくれる関数があるそうです
以下参考記事
def fileGetLink(path):
for pathName, dirName, fileName in os.walk(path):
for file in fileName:
path = os.path.join(pathName,file)
soup = BeautifulSoup(open(path, encoding='utf-8'), 'html.parser')
コンパクトになりました
最終的な実装
from bs4 import BeautifulSoup
import os
def fileGetLink(path):
for pathName, dirName, fileName in os.walk(path):
for file in fileName:
path = os.path.join(pathName,file)
soup = BeautifulSoup(open(path, encoding='utf-8'), 'html.parser')
for link in soup.find_all(["a","link"):
with open('./hogeLink.txt', "a", encoding='UTF-8', newline='\n') as f:
if link.get("href") is None:
continue
f.write(link.get("href") + "\n")
for link in soup.find_all(["script","img"]):
with open('./hogeLink.txt', "a", encoding='UTF-8', newline='\n') as f:
if link.get("src") is None:
continue
f.write(link.get("src") + "\n")
fileGetLink('./www.hoge.com')
まとめ
以上のスクリプトを実行するとソース内のリンクがビャーっとテキストファイルにリンク群が書き出されていきます
webサイトの内部ファイル(画像やpdfなど)の存在チェックをしたい時などにオススメです
余談ですが、最初自分の手癖で書いて、あとから公式ドキュメントなどを調査してコードをブラッシュアップしていく方式がすごく良かったので、皆様も是非やってみて下さい
(誤り等あれば指摘コメント下さい)