ラズパイによるbotとしてはてなブログのエントリーをTweetする機能を作っています。
【プログラミング素人のはてなブログ】JSON形式からのData取得と辞書書式 https://t.co/bIuwdtqVLo
— プログラミング素人 (@s51517765) 2018年1月3日
これまでは、Tweetの定型文を手動で入力していましたが、自分のはてなブログのエントリー一覧から自動生成することを考えました。
はてなブログのエントリー一覧は↓のようなURLから取得できそうです。
http://s51517765.hatenadiary.jp/archive?page=2
エントリー一覧のURLは末尾の数字を順番に増やして取得できると推測できます。
以前に、C#で作成したスクレイピングツールもあり、こちらでも機能を拡張すれば可能です。
s51517765.hatenadiary.jp
pythonではbeautifulsoupというモジュールが簡単ということなので、試してみました。
↓を参考にしました。
退屈なことはPythonにやらせよう ―ノンプログラマーにもできる自動化処理プログラミング
- 作者: Al Sweigart,相川愛三
- 出版社/メーカー: オライリージャパン
- 発売日: 2017/06/03
- メディア: 単行本(ソフトカバー)
- この商品を含むブログ (5件) を見る
beautifulsoupはurlを指定してhtmlを取得し、その中から指定したタグを抽出するということが容易にできるそうです。
そこで、以下のようにプログラミングします。
①Urlを指定しhtmlを取得
②エントリーのタグを抽出し、この中から、エントリーのタイトルとurlを取得
③次のページに移動
④エントリーがなくなったら終了
”a”のタグはLinkを示していて、htmlの中から"a"を取得します。
この取得した一覧はlist形式になっています。
html = requests.get(url) soup = BeautifulSoup(html.text, 'lxml') ##lxmlを指定するほうがよい alink = soup.select('a') #linkの一覧をListとして取得
この中から、classが "entry-title-link" であるものを抽出します。
htmlを知っていればわかると思いますが、classはhtmlの記法の一つで、ここで言えば ”entry-title-link” のクラスを指定していて、別途設定したスタイルを適用するようになっています。
if 'entry-title-link' in alink[i].get('class'):
リンク要素から、リンクのテキストとurlを取得します。
print('【プログラミング素人のはてなブログ】' +alink[i].getText()+' '+alink[i].get('href'))
リンクurlを予め宣言しておいた、list=[]に見つからなければ追加しながらprint()します。このようにして重複を防止します。
これを、ページを遷移しながら繰り返し、エントリーがなくなるまで続けます。
ここではページを遷移しても、新しいurlがでてこなくなれば手動でプログラムを停止します。
自動化するには「新しいページに新しいurlがない」とか「『記事はありません』という文言を見つけたら終わり」といった方法が考えられますが、これをコーディングするコストがメリットを超えるので手動停止という方法をとりました。
これが、実行に数十分かかるとなるとPCの前を離れられないなどのコストがかかり、コーディングするべきとなりますが、ここでは数秒なので、目視で止めることで十分なのです。
def soup_taikutsu(url): html = requests.get(url) soup = BeautifulSoup(html.text, 'lxml') ##lxmlを指定するほうがよい alink = soup.select('a') #linkの一覧をListとして取得 #print(len(alink)) #Listの長さ for i in range(len(alink)): if alink[i].get("class")!=None: #クラスが未設定でない if 'entry-title-link' in alink[i].get('class'): #エントリーのclassとして指定されているものの時 if alink[i].get("href") not in list: #すでに抽出済みでなければ list.append(alink[i].get("href")) print('【プログラミング素人のはてなブログ】' +alink[i].getText()+' '+alink[i].get('href')) if __name__ == '__main__': list=[] rootUrl='http://s51517765.hatenadiary.jp/archive?page=' #エントリー一覧の基本url n=1 while(True): url=rootUrl+str(n) soup_taikutsu(url) n+=1
このほかにfind_allという関数を使う方法もできました。
alink = soup.find_all('a')
取得できる結果は同じです。
こちらではListではなく "for ~ in ~"でアクセスします。
またlink urlに"s51517765.hatenadiary.jp/entry/"が見つかるかどうかで判断しました。
import requests, os, bs4 from bs4 import BeautifulSoup print("start!") def soup(url): html = requests.get(url) soup = BeautifulSoup(html.text, 'lxml') alink = soup.find_all('a') for a in alink: if a.string!=None and a.get("href")!=None: if a.get("href").find("s51517765.hatenadiary.jp/entry/")!=-1: #自分のブログの外は除外 #print(a.string) #Linkのテキスト #print(a.get("href")) #Linkのurl if a.get("href") not in list: #urlがリストに無ければ list.append(a.get("href")) print("【プログラミング素人のはてなブログ】" + a.string + " " + a.get("href")) # mainは同様