スナックelve 本店

バツイチ40代女の日記です

python3ではてなapiをいじる

elve.hatenadiary.jp
のコードを少し直した

requestsモジュールなし、urllibモジュールでapiにアクセスする方法は
qiita.com

HTMLの出力に関しては
torina.top

入力文字の判定は
qiita.com

を参考にさせていただきました。

目的

自分のサイトをブクマしてくれてる人を一覧表示したかったのが始まりです。

実行結果

実行
検索する文字列とはてなIDを入力
三日はてブ.htmlというファイルができる

f:id:elve:20180331003406p:plain
変更なし
入力したIDがスターをつけていれば★がつきます。
ブクマされたサイト、ブクマしたユーザー、ブクマした日付、コメント が一覧で表示されます。

ポイント

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

qiita.com

関数の外だからreturnできない

sys.exit()だった

エンコードしちゃだめだった

urllib.request.urlopen().text().read()に.encode('utf-8')つけるとxmljsonにしようとする所(次の行)でエラーが出てしまった。

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")