このブログはプログラミングと電子工作に偏っているので、このブログを読んでいる人は、これらに興味があると考えられます。
では、その人が書いているブログもプログラミングや電子工作に関係するのではないか?と考えてpythonとbeautifulsoupで取得することを考えました。
ブログの購読者は↓から取得できます。
s51517765.hatenadiary.jp
import requests from bs4 import BeautifulSoup def get_aboutpage_2_subscriber(url, id_list, profile_page_list): html = requests.get(url) soup = BeautifulSoup(html.text, 'lxml') ##lxmlを指定するほうがよい alink = soup.find_all('a') for a in alink: if a.get("href") != None: link = a.get("href") if "https://blog.hatena.ne.jp/" in link and "abuse_report" not in link: # https://blog.hatena.ne.jp/-/abuse_report?target_url=https%3A%2F%2Fs51517765.hatenadiary.jp%2Fabout link2 = link.replace("https://blog.hatena.ne.jp/", "") finded_id = link2.replace("/", "") if finded_id not in id_list: id_list[finded_id] = 1 profile_page_list[finded_id] = link else: id_list[finded_id] += 1 return profile_page_list, id_list
beautifulsoupでalink = soup.find_all('a')
のようにLinkを取得し"https://blog.hatena.ne.jp/"
が含まれているものが、読者のブログページです。ひとつだけ、https://blog.hatena.ne.jp/-/abuse_report?target_url=https%3A%2F%2Fs51517765.hatenadiary.jp%2Fabout
が余計なので、除外します。
ここから、読者のidを取得し、辞書に加えていきます。
次に、読者のidからプロフィールページを取得します。
プロフィールページはLinkのうち/about
が含まれているものです。
import requests from bs4 import BeautifulSoup import time def get_subscriber_aboutpage(id): url = "https://blog.hatena.ne.jp/" + id + "/" html = requests.get(url) soup = BeautifulSoup(html.text, 'lxml') ##lxmlを指定するほうがよい alink = soup.find_all('a') for a in alink: if a.get("href") != None: link = a.get("href") if "/about" in link: return link break time.sleep(0.2)
これを繰り返し、幅優先探索の要領で、このブログの読者と読者のブログの読者を取得します。
幅優先探索 - Wikipedia
idの辞書をforで回しているときに、辞書を書き換えようとすると、RuntimeError: dictionary changed size during iteration
というエラーが出るので、一旦読み取り用の辞書を id_list_tmp = id_list.copy()
として用意します。 id_list_tmp = id_list
とするとpythonでは同じポインタにアクセス(参照渡し)するようでダメです。
if __name__ == '__main__': id_list = {} id_list_tmp = {} # RuntimeError: dictionary changed size during iteration about_page_list = {} my_url = "https://s51517765.hatenadiary.jp/about" about_page_list, id_list = get_aboutpage_2_subscriber(my_url, id_list, about_page_list) i=0 while i<2: i+=1 id_list_tmp = id_list.copy() #辞書はループを回している間は書き換えできないので for id in id_list_tmp: print(id) try: profile_link = get_subscriber_aboutpage(id) get_aboutpage_2_subscriber(profile_link, id_list, about_page_list) except Exception as e: print("-------------------------------") print(e) print(profile_link) print("-------------------------------") for k, v in sorted(id_list.items(), key=lambda x: -x[1]): # 降順ソート if v != 1: print(str(k) + ": " + str(v)) # print(about_page_list) print(id_list)
とりあえず、3階まで取得してみましたが予想とは異なる結果でした。
ブログ読者であっても、自身はブログを書いていなかったりします。
また、この集計方法では重複カウントも出てきますが、正規化されないgoogleのページランクのようなものでこれはこれでいいのかとも思います。
3階の時点で8000人近く出てきました。(私の読者の読者の読者)
3階までの結果の一部
ponyoponyokun: 79 dmasaki: 62 aka12aya70y: 62 ironchocolate: 62 riyunion2: 55 akira2013web: 49 sakuyaoi: 49 grazieatutti: 47 youhp01: 47 nue0801: 45 doubleworkandstock: 44 opio8: 43 oshaberiitboy: 42 torus1: 41 sayakasumi382: 41 fukai19930806347: 40 mksurf: 38 at25250410: 38 kihappy1: 38 hidamaru: 37 cat-whisker: 35 AKI1200: 35 brachiodesign: 35 a24o92: 35 bunntinnmalu: 35 kihaseason2015: 34 momokuri777: 34 axia18: 33 noritoikioi: 33 je_online: 33 mraka2015: 33 m07v-sk160: 33 sakabesharoushi: 32 editman: 31 koppamizin007: 30 brd1267: 29 kojiebi-gm: 29 umauma-free: 29 kotokunohate: 29 periaki0813: 28 syuusakukakizoe: 28 takipon5: 28 taicho-fujiyama: 27 ko-chanblog95: 27 azu-ryugaku: 27 setsuyakufufu: 27 karin88: 26 esupro: 26 mentalx: 26 nie3: 26 titirobo: 26 gqp: 25 chippyofficial: 25 TAKOICHI: 25 Hikaru-English: 25 hal7pi: 25 sara_pezzini: 25 WhiteTree: 24 ishideo: 24 tai_mijinko: 24 otasuke0411: 24 myprivatecomedy: 23 takahon: 23 miwamomoka: 23 for-mom: 23 sorairo2000: 23 sekiuti: 23 dutch2017: 23 nottoworry-money: 22 c6amndbgr3: 22 ev_traveler: 21 salondealfurd: 21