elve.hatenadiary.jp
のコードを少し直した
requestsモジュールなし、urllibモジュールでapiにアクセスする方法は
qiita.com
HTMLの出力に関しては
torina.top
入力文字の判定は
qiita.com
を参考にさせていただきました。
目的
自分のサイトをブクマしてくれてる人を一覧表示したかったのが始まりです。
実行結果
実行
検索する文字列とはてなIDを入力
三日はてブ.htmlというファイルができる
ブクマされたサイト、ブクマしたユーザー、ブクマした日付、コメント が一覧で表示されます。
ポイント
urllibインポートしてるのにrequestがないって言われる問題
AttributeError: module 'urllib' has no attribute 'request'
import urllib
だけじゃ駄目で
import urllib.request
も必要でした。
python - AttributeError: 'module' object has no attribute 'request' - Stack Overflow
htmlの出力
Pythonで文字列に変数を埋め込む方式にはいくつかあったが、ついに式を文字列中に直接記述できるようになった。
Python 3.6の概要 (その1 - f文字列) - atsuoishimoto's diary
ということで、いけてなかったファイル出力を少し綺麗にできたと思います。
子が配列のjson
{"entries":[{"stars":[{"quote":"","name":"elve"}],"can_comment":1,"comments":[],"uri":"http://b.hatena.ne.jp/~"}],"can_comment":1}
これのstarsにアクセスしようとして(目的はさらに子供のnameだった)
json[’entries’][’stars']
ができなくてチョット分からなくなった。結局for文で回した。
inputで戻ってこなくなる(Visual Studio Code)
関数の外だからreturnできない
sys.exit()だった
エンコードしちゃだめだった
urllib.request.urlopen().text().read()に.encode('utf-8')つけるとxmlやjsonにしようとする所(次の行)でエラーが出てしまった。
etreeのXpathで取得できなかった
links = root.xpath('link', namespaces={'rss','{http://purl.org/rss/1.0/}'})
で取れると思ったら取れなかった
ValueError: too many values to unpack (expected 2)
不明
findallを使う
ソース
# -*- coding:utf-8 -*- import urllib import urllib.request import json from lxml import etree import datetime as dt import sys # HTML出力 def HtmlOutput(bmInfos): f = open('三日はてブ.html', 'wb') tableStr = '<table>' tableStr += '<tr><th>★</th><th>URL</th><th>ユーザー</th><th>日付</th><th>コメント</th>\n' for b in bmInfos: bUrl = b['url'].replace("http://", "") bUrl = b['url'].replace("https://", "s/") bUrl = urllib.parse.quote(bUrl) tableStr += '<tr><td>' if b['star'] == 1: tableStr += '★' tableStr += '</td>' tableStr += f'<td><a href="http://b.hatena.ne.jp/entry/{bUrl}" target="_blank">{b["url"]}</a></td>' tableStr += f'<td>{b["user"]}</td>' tableStr += f'<td>{b["date"].strftime("%Y/%m/%d")}</td>' tableStr += f'<td>{b["comment"]}</td>' tableStr += '</tr>\n' html = f""" <!DOCTYPE html> <html lang="ja"> <head> <meta charset="utf-8"> </head> <body> {tableStr} </body> </html> """ f.write(html.encode('utf-8')) f.close() # 入力したはてなIDがスター(黄)つけているか # 0: はてなスターをつけていない # 1: はてなスターをつけている def GetImgIndex(time, eid, user): # URL作成 url = f'http://b.hatena.ne.jp/{user}/' url += time.strftime("%Y%m%d") url += "#bookmark-" + str(eid) url = urllib.parse.quote(url) # アクセス(エンコードしない) r = urllib.request.urlopen("http://s.hatena.com/entry.json?uri=" + url).read() # jsonに変換 jsonStr = json.loads(r) for st in jsonStr['entries']: for st2 in st['stars']: if st2['name'] == myId: return 1 return 0 # ---メイン処理ここから--ー # 検索値、ユーザーID入力 myStr = input("検索したいurl: ") myId = input("あなたのはてなID: ") if myStr == "" or myId == "": print("なんか入れて") sys.exit() if myId.encode('utf-8').isalnum(): if len(myId) > 15: print("長すぎる") sys.exit() else: print("半角英数以外") sys.exit() # これに.decode('utf8')つけるとetreeのところでエラーになる r = urllib.request.urlopen("http://b.hatena.ne.jp/search/text?safe=off&q=" + urllib.parse.quote(myStr, '') + "&users=1&mode=rss").read() root = etree.fromstring(r) links = root.findall(".//{http://purl.org/rss/1.0/}link") bmInfos = [] for link in links: if link != links[0]: r = urllib.request.urlopen("http://b.hatena.ne.jp/entry/jsonlite/?url=" + urllib.parse.quote(link.text, '')).read() jsonStr = json.loads(r) try: for bm in jsonStr['bookmarks']: tdatetime = dt.datetime.strptime(bm['timestamp'], '%Y/%m/%d %H:%M:%S') if tdatetime > (dt.datetime.now() - dt.timedelta(days=3)): bmInfo = {"star": 0, "url": jsonStr['url'], "user": bm['user'], "date": tdatetime, "comment": bm['comment']} bmInfo["star"] = GetImgIndex(tdatetime, jsonStr['eid'], bm['user']) bmInfos.append(bmInfo) else: break except: print("ERR!!") break HtmlOutput(bmInfos) print("END")