質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.49%
HTTP

HTTP(Hypertext Transfer Protocol)とはweb上でHTML等のコンテンツを交換するために使われるアプリケーション層の通信プロトコルです。

Python 3.x

Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

Raspberry Pi

Raspberry Piは、ラズベリーパイ財団が開発した、名刺サイズのLinuxコンピュータです。 学校で基本的なコンピュータ科学の教育を促進することを意図しています。

Q&A

解決済

1回答

1181閲覧

Python3とはてなAPIを利用した、はてなフォトライフへの画像アップロードをしたい

shut9

総合スコア14

HTTP

HTTP(Hypertext Transfer Protocol)とはweb上でHTML等のコンテンツを交換するために使われるアプリケーション層の通信プロトコルです。

Python 3.x

Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

Raspberry Pi

Raspberry Piは、ラズベリーパイ財団が開発した、名刺サイズのLinuxコンピュータです。 学校で基本的なコンピュータ科学の教育を促進することを意図しています。

0グッド

2クリップ

投稿2018/08/12 09:32

編集2018/08/12 11:05

前提・実現したいこと

はてなフォトライフのAPIを利用して、Python3とWSSE認証によって、画像をアップロードしたいと考えています。

発生している問題・エラーメッセージ

Error! status_code: 500 message: <!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN"> <html><head> <title>500 Internal Server Error</title> </head><body> <h1>Internal Server Error</h1> <p>The server encountered an internal error or misconfiguration and was unable to complete your request.</p> <p>Please contact the server administrator, root@localhost and inform them of the time the error occurred, and anything you might have done that may have caused the error.</p> <p>More information about this error may be available in the server error log.</p> </body></html>

該当のソースコード

Python

1#!/home/pi/.pyenv/shims/python 2#coding=utf-8 3import sys 4import datetime 5import random 6import hashlib 7import base64 8 9import requests 10from chardet.universaldetector import UniversalDetector 11 12import datetime 13now = datetime.datetime.now() 14dtime = str(now.year)+"""-"""+str(now.month)+"""-"""+str(now.day)+"""T"""+str(now.hour)+""":"""+str(now.minute)+""":"""+str(now.second) 15print(dtime) 16 17# setting ----------------------------------------------------------- 18username = '****user' 19api_key = '****accesstoken' 20blogname = '****brogname' 21 22# main ----------------------------------------------------------- 23def main(): 24 data = create_data() 25 post_hatena(data) 26 27def wsse(username, api_key): 28 created = datetime.datetime.now().isoformat() + "Z" 29 b_nonce = hashlib.sha1(str(random.random()).encode()).digest() 30 b_digest = hashlib.sha1(b_nonce + created.encode() + api_key.encode()).digest() 31 c = 'UsernameToken Username="{0}", PasswordDigest="{1}", Nonce="{2}", Created="{3}"' 32 return c.format(username, base64.b64encode(b_digest).decode(), base64.b64encode(b_nonce).decode(), created) 33 34def create_data(): 35 files = open("./test.png", "rb").read() 36 uploadData = base64.b64encode(files) 37 template = """ 38 <entry xmlns="http://purl.org/atom/ns#"> 39 <title>Sample</title> 40 <content mode="base64" type="image/png">"""+str(uploadData)+"""</content> 41 </entry> 42 """ 43 44 data = base64.b64decode(template) 45 return data 46 47def post_hatena(data): 48 headers = {'X-WSSE': wsse(username, api_key)} 49 url = 'http://f.hatena.ne.jp/atom/post/' 50 r = requests.post(url, data=data, headers=headers) 51 52 if r.status_code != 201: 53 sys.stderr.write('Error!\n' + 'status_code: ' + str(r.status_code) + '\n' + 'message: ' + r.text) 54 55if __name__ == '__main__': 56 main()

試したこと

HTTPやWSSE、requestsモジュール等に関する知識がほぼ無く、何が原因でステータスコード500エラーが出ているのかがあまりよくわかっていません。
はてなサービスにおけるWSSE認証(http://developer.hatena.ne.jp/ja/documents/auth/apis/wsse)
を見た限りでは、認証の仕方に問題はないように思えます。
おそらくcreate_data()関数内のエンコードの仕方に問題があるのではと思っているのですが、いまいち何が間違っているのかよくわかりません。

補足情報(FW/ツールのバージョンなど)

Raspberry Pi3 B+ (Raspbian)
Python 3.6.6

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

ベストアンサー

はてなフォトライフAtomAPI

POST /atom/post

<entry xmlns="http://purl.org/atom/ns#"> <title>Sample</title> <content mode="base64" type="image/jpeg">/9j/2wCEAAQDAwQDAw.../9n/AA==</content> </entry>

Python

1 data = base64.b64decode(template) 2 return data

base64.b64encode(files)エンコードした後にxml全体をbase64.b64decode(template)でデコードする必要はないような。

発行しているリクエストはHTMLプロキシソフトで確認してみてくださいな。


試しにアップロードしてみた所、以下の箇所も修正する必要がありました。

diff

1-str(uploadData) 2+uploadData.decode()

書き換えたサンプルコードです、ご参考まで。

Python

1# -*- coding: utf-8 -*- 2from base64 import b64encode 3from datetime import datetime 4from hashlib import sha1 5import random 6import requests 7import sys 8from pathlib import Path 9 10now = datetime.now() 11dtime = str(now.year)+"""-"""+str(now.month)+"""-"""+str(now.day)+"""T"""+str(now.hour)+""":"""+str(now.minute)+""":"""+str(now.second) 12print(dtime) 13 14 15username = '****user' 16api_key = '****accesstoken' 17blogname = '****brogname' # ※不要でした。 18 19 20def wsse(username: str, api_key: str) ->str: 21 created = datetime.now().isoformat() + "Z" 22 b_nonce = sha1(str(random.random()).encode()).digest() 23 b_digest = sha1(b_nonce + created.encode() + api_key.encode()).digest() 24 return f'UsernameToken Username="{username}", PasswordDigest="{b64encode(b_digest).decode()}", Nonce="{b64encode(b_nonce).decode()}", Created="{created}"' 25 26 27def create_data(file_name: str='./test.png') ->str: 28 uploadData = b64encode(Path(file_name).read_bytes()) 29 return """ 30 <entry xmlns="http://purl.org/atom/ns#"> 31 <title>Sample</title> 32 <content mode="base64" type="image/png">""" + uploadData.decode() + """</content> 33 </entry> 34 """ 35 36 37def post_hatena(data): 38 headers = {'X-WSSE': wsse(username, api_key)} 39 url = 'http://f.hatena.ne.jp/atom/post/' 40 r = requests.post(url, data=data, headers=headers) 41 try: 42 r.raise_for_status() 43 except: 44 sys.stderr.write(f'Error!\nstatus_code: {r.status_code}\nmessage: {r.text}') 45 46 47def main(): 48 data = create_data() 49 post_hatena(data) 50 51 52if __name__ == '__main__': 53 main() 54

■参考情報

投稿2018/08/12 15:53

編集2018/08/12 20:10
umyu

総合スコア5846

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

shut9

2018/08/13 04:24

ご回答ありがとうございます。 修正いただいたとおりに書くと、アップロードができました。 大変助かりました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.49%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問