みなさんこんにちは。
前回の投稿から約3か月空いてしまいました…(忙しくてサボっていました 笑)またボチボチ更新していきますのでよろしくお願いします。
その1の出力結果↓
1 2 3 4 5 6 7 8 9 |
# 出力結果 立憲 国会審議の復帰を検討new 南禅寺で刺激臭 客ら喉の痛み写真 火災4件1人死亡 不審火続く写真new 1兆円市場? 睡眠負債ビジネス写真 FB 閲覧履歴消去できる新機能写真 協会会長「伊調と話したい」写真new TOKIO会見 山口脱退申し入れ写真new 松岡 山口は甘ったれた発言写真new |
ここから「写真」、「new」を消したいと思います。色々やり方はあると思いますが、シンプルにsoupのなかから”span”タグを全て消してしまいます。それにはdecompose()を使います。
1 2 |
for s in soup("span"): s.decompose() |
その1と合わせるとこんな感じになります。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
import requests from bs4 import BeautifulSoup url = 'http://news.yahoo.co.jp/' res = requests.get(url) soup = BeautifulSoup(res.text,"html.parser") for s in soup("span"): s.decompose() #spanタグを抜き出して削除 h1s = soup.find_all("h1",class_="ttl") for h1 in h1s: print(h1.text) ps = soup.find_all("p",class_="ttl") for p in ps: print(p.text) |
1 2 3 4 5 6 7 8 9 |
# 出力結果 立憲 国会審議の復帰を検討 南禅寺で刺激臭 客ら喉の痛み 火災4件1人死亡 不審火続く 1兆円市場? 睡眠負債ビジネス FB 閲覧履歴消去できる新機能 協会会長「伊調と話したい」 TOKIO会見 山口脱退申し入れ 松岡 山口は甘ったれた発言 |
当たり前ですがYahooニュースのHTML構造が変わってしまうとこのプログラムは動きません。(そんなに頻繁に変わるものではないと思いますが…)さてここまでできたらもうちょっと改良してみたい。
①プログラムを定期的に動かしてトピックスを取得する
②前回取得したトピックスと比較して、新しいトピックスがあれば通知する
①はLinuxだとcronがありますが、今使っているのはWindowsなのでよくわかりません。調べてみたらbatファイルを作ってタスクスケジューラで管理するのだとか。Pythonとあまり関係ないので、とりあえず②を先にやります。
前回の情報をどうやって保存しておくか、ですがシンプルにテキストファイルに毎回吐き出すことにしました。
1 2 3 |
f = open('hogehoge.txt', 'w') # 書き込みモードで開く f.write(moji) # 引数の文字列をファイルに書き込む f.close() # ファイルを閉じる |
前回保存したテキストファイルから前回のトピックスを読み込み→前回のトピックスを今回取得したトピックスと比較して、新しい項目がある場合は通知→今回のトピックスをテキストファイルに上書き保存、という流れにします。Yahooニュースの内部ロジックがよくわかりませんが、単純に新しい項目が追加されたら古い項目が下にずれていくということでも無さそうです。最大8項目というのは不変なようですが。ということで、リストとして上から比較していくのではなく、順番によらない要素ごとの比較(=集合の比較)を利用します。
前回のトピックスの要素からなる集合をold、今回のトピックスの要素からなる集合をnewとして差集合を求めます。もしグレーにあたる要素がひとつでもあれば、今回のトピックスだけにある要素ということになるので、新しいトピックスがあるとして表示します。差集合の長さ(=len)が1以上であれば「差集合がある」ということになります。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 |
import requests from bs4 import BeautifulSoup import sys #sys.exit()を利用するために必要 #テキストファイルから前回のトピックスを集合として展開する f = open('hogehoge.txt','r') #ファイル読み込み f_old = f.read() list_old = f_old.splitlines() #文字列を改行ごとにリスト化 set_old = set(list_old) #リストを集合に変換 f.close() # ファイルを閉じる #その1の処理 url = 'http://news.yahoo.co.jp/' res = requests.get(url) soup = BeautifulSoup(res.text,"html.parser") for s in soup("span"): s.decompose() #spanタグを抜き出して削除 list_new = [] #空のリスト作成 h1s = soup.find_all("h1",class_="ttl") for h1 in h1s: list_new.append(h1.text) ps = soup.find_all("p",class_="ttl") for p in ps: list_new.append(p.text) set_new = set(list_new) #リストを集合に変換 set_dif = set_new - set_old #差集合を求める #差集合がなければ処理終了 if len(set_dif) == 0: print("新しいトピックスはありません") sys.exit() #以降の処理には進まず終了 #差集合があればリストとして取り出す else: newlist = list(set_dif) newstr = '\n'.join(newlist) print("新しいトピックスです") print(newstr) string = "\n".join(list_new) #リスト内の文字列を改行して結合 f = open('hogehoge.txt', 'w') # 書き込みモードで開く f.write(string) # 引数の文字列をファイルに書き込む f.close() # ファイルを閉じる |
新しいトピックスがある場合はこのような形で表示されます。
1 2 3 4 5 |
# 出力結果 新しいトピックスです 髪食べた 池松壮亮の怪演ぶり 入試問題公表 著作権処理に壁 米で老人ホーム銃撃 5人死亡 |
ない場合は
1 2 |
# 出力結果 新しいトピックスはありません |
もし上のソースをコピーしてそのまま張り付けた場合、hogehoge.txtがないのでエラーになるかと思います。pyファイルと同じディレクトリに空のhogehoge.txtを作成すれば問題ありません。再度実行して上書き保存されたhogehoge.txtをメモ帳などで開くと、新しく取得したトピックスが丸々記載されていると思います。その1よりはまとも?な処理ができたでしょうか。まだプログラミングを始めたばかりなので変数の指定のしかたが難しい。。読みにくい部分もあると思いますが長い目で生温かく見守ってください。タスクスケジューラへの登録などはまた後日。