こんにちは!ほけきよです。
今日は自動化第四弾!! またまたGoogleに媚びを売るSEO対策です(^^)
前回は内部リンクネットワークの可視化でした。今回は、リンク切れの抽出です!
悲しきNot Found
…Googleさんがお怒りになる前に片付けちゃいましょう!
リンク切れとは?
自サイトで言うと、こういうのです
悲しいですよね。以前まであったはずのものがなくなるのは…
というわけで、リンク切れは早めに対処しましょう!
めんどい
そう思い、いちいちリンククリックして確かめてたんですが、
めんどい、めんどうがすぎる
大体のリンクはちゃんと通るのに、通らないリンクを探すなんて、修行ですか? というわけで、3記事で飽きました。ううーん、そうだ、自動化しよう
環境を作る
- python(3系)
- bs4
- urllib
python環境のある人へ : pipで全部入ります。面倒な人は、anacondaに全部入っているはずなのでそれで。
python環境のないwinユーザへ : python環境をwindowsにいれる方法は、私の過去記事に書いています。anacondaを入れておくと大抵のことができるのではかどります(容量が2GBほど必要ということには注意しておいてください)
コード
例の如く下記コードをコピペしてinvalid_links.py
などで保存してください
*1
どこでもいいのですがあんまりわからない!って人はデスクトップに一旦保存しておきましょう。
from bs4 import BeautifulSoup import urllib from urllib import request import time from argparse import ArgumentParser import csv def extract_url(root_url): page = 1 is_articles = True urls = [] while is_articles: html = request.urlopen(root_url+"/archive?page={}".format(page)) soup = BeautifulSoup(html, "html.parser") articles = soup.find_all("a",class_="entry-title-link") for article in articles: urls.append(article.get("href")) if len(articles) == 0: # articleがなくなったら終了 is_articles = False page += 1 return urls def url_checker(url, urls): #変なリンクは除去したい flag1 = "http" in url[:5] #ハテナのキーワードのリンクはいらない flag2 = "d.hatena.ne.jp/keyword/" not in url #amazonリンクはダメ flag3 = "http://www.amazon.co.jp" not in url and "http://amzn.to/" not in url return flag1 and flag2 and flag3 def check_invalid_link(root_url, urls, output): import re regex = r'[^\x00-\x7F]' #正規表現 entry_url = root_url + "/entry/" with open (output, "w") as f: writer = csv.writer(f, lineterminator='\n') writer.writerow(["URL", "ERROR", "LINK", "STATUS"]) for i,url in enumerate(urls): print(i+1,"/",len(urls),url) try: html = request.urlopen(url) except urllib.error.HTTPError as e: print(e.reason) except urllib.error.URLError as e: print(e.reason) soup = BeautifulSoup(html, "html.parser") entry = soup.select(".entry-content")[0] links = entry.find_all("a") for link in links: l = link.get("href") #日本語リンクは変換 matchedList = re.findall(regex,l) for m in matchedList: l = l.replace(m, urllib.parse.quote_plus(m, encoding="utf-8")) check = url_checker(l, urls) if check: #リンク切れ検証 try: html = request.urlopen(l) except urllib.error.HTTPError as e: writer.writerow([url, "HTTP ERROR", l, e.reason]) print("HTTPError:", l, e.reason) except urllib.error.URLError as e: writer.writerow([url, "URL ERROR", l, e.reason]) print("URLError:", l, e.reason) except UnicodeEncodeError as e: writer.writerow([url, "UNICODE ENCODE ERROR", l, e.reason]) print("UnicodeEncodeError:", l, e.reason) # time.sleep() if __name__ == '__main__': """ TODO - APIを叩いてなんとかなるやつ実装 - amazon associateの対応 - youtubeの削除された動画対応 """ parser = ArgumentParser() parser.add_argument("-u", "--url", type=str, required=True,help="input your url") parser.add_argument("-o", "--output", type=str, default="articles.csv", help="output csv name") args = parser.parse_args() urls = extract_url(args.url) check_invalid_link(args.url, urls, args.output)
なにをやっているかだけ簡単に説明しておきます。
- 本文中から
http
で始まるリンクだけ抜き出している - ハテナのキーワードリンクは邪魔なので排除する
- amazon associateリンクは特殊なことをしないとアクセスできないので除去する
- リンクにアクセスして、エラーが出たら出力する
という流れになります。
実行する
ターミナル or コマンドプロンプトを開き*2、さっきのinvalid_links.py
が保存されている場所まで移動します。
デスクトップに保存している方は下記コマンドで実行されるはずです。
cd Desktop python invalid_links.py --url http://www.procrasist.com --output procrasist.csv
--url URL
で、調べたいブログのURLを入力してください--output hoge.csv
で、出力されるcsvの名前を決められます(省略できて、省略した場合はarticles.csv
になります)
結果はこんな感じ。
最新記事から順番にびゃぁーーっと調べてくれます。
なお、結果はcsvファイルにも出力されます。 結構リンク切れってあるのね。
今後の課題/注意
下記のことはまだできていません
- amazon商品リンクのリンク切れ
- youtubeの削除されたものの追従
- はてなブログのみに対応
- ブラウザでのみアクセスを許しているものがあり、拒否(Forbidden)されちゃう。
- 日本語以外のエンコードエラーに非対応(いずれ直します)
いずれもAPIでうまくすればうまくいくっぽいですが、ちょっと面倒だったので、今回はやめておきます。TODO! はてなブログ以外で試したいという方は、相談していただければ応えられる範囲で答えます!URLをぶっこ抜くところがおそらく一番のポイントです
あと、これは注意ですが、外部へのアクセスを頻繁に行いすぎると、そのサイト運営者の迷惑になりますので、コード実行は最小限にしておいてください。
※コードが動かない場合も連絡ください。
まとめ
いかがでしたか? コレでいちいち眠たい眼こすりながらリンクポチポチする必要もなくなりましたねっ
どうぞ試してみてください!