PyQtとTweepyを使った簡易Twitterクライアント

前回の発展編みたいなものです。

フォームに打ち込んだツイート内容を送信するところまでやります。

PyQt (python Qt)

QtっていうのはC++で書かれたフレームワークの一つで、
GUISQLなど様々な機能を持ったものです。

今回は機能の一つであるQtGuiを使ってPythonの簡単なフォームアプリケーションを作りました。
でもPython2系だとQtを使うのに結構不便あるらしいのでしっかりやりたい方はPython3系を使うのをおすすめします。
(ライブラリを使うのでこの記事では2系を使います)

環境

前回と同じで
Python2.7.3
windowsXP-32bit-SP3

ライブラリ

easy_install

各種ライブラリのinstallに必要

Tweepy

Twitterの認証からつぶやきの送信用

PyQt

こちらはeasy_installではなくインストーラーを落として使います

プログラムの流れ

①起動と同時にブラウザを開きユーザにアプリケーションの認証をさせる
②発行されたPINコードを入力させるフォームであるform1を表示。
 OAuth認証を行いAccessTokenを獲得
③form1を閉じ、ツイートの入力画面のあるform2を開く
④ユーザの入力した文字をtweepyを使って送信する

プログラム

各種ライブラリのimportをし、
グローバル変数にConsumerKey,ConsumerSecret,OAuthHandlerを宣言しておく
(引数渡したりとか面倒だったので)

#coding: UTF-8

#systemライブラリ
import sys
#tweepyライブラリ
import tweepy
#ブラウザを開くためのライブラリ
import webbrowser
#PyQtのQtGui,QtCoreをimport
from PyQt4 import QtGui,QtCore

#developerのconsumerkey
consumer_key  = "consumerkey"
#developerのconsumersecret
consumer_secret = "consumersecret"
#oauth認証に必要なハンドルの宣言
auth=tweepy.OAuthHandler(consumer_key,consumer_secret)

form1のクラス
AccessTokenの取得までを行う

#form1クラス
class Form1(object):
	#コンストラクタ
	def __init__(self):
		#form1の宣言
		self.form1=QtGui.QWidget()
		#form1のサイズ指定
		self.form1.resize(200,100)
		#form1のタイトル指定
		self.form1.setWindowTitle('Setting Acount')

		#Buttonを宣言し、'send'とButtonに表示
		self.button1=QtGui.QPushButton('send',self.form1)
		#Buttonの位置を指定
		self.button1.setGeometry(50,63,100,25)

		#入力するBOXであるLineEditを宣言
		self.edit1=QtGui.QLineEdit(self.form1)
		#LineEditの位置を指定
		self.edit1.setGeometry(50,25,100,30)

		#button1を押したときのイベントをclick_forms_ok_buttonメソッドに指定
		self.button1.clicked.connect(self.click_forms_ok_button)
		#form1を表示
		self.form1.show()

	#pinコードを受け取りaccesstokenを取得するメソッド
	def get_accesstoken(self,pin_key):
		#accesstokenの取得
		auth.get_access_token(pin_key)

	#button1を押した時のイベントメソッド
	def click_forms_ok_button(self):
		#pinコードをLineEditから読み取る
		pin=self.edit1.text()
		#get_accesstokenメソッドにpinコードを渡してaccesstokenを獲得
		self.get_accesstoken(pin)
		#accesstokenを取得したのでform1を閉じる
		self.form1.close()

form2のクラス
ツイート送信を行う

#form2クラス
class Form2(object):
	#コンストラクタ(ユーザIDを受け取る)
	def __init__(self,userid):
		#form2の宣言
		self.form2=QtGui.QWidget()
		#form2のサイズ指定
		self.form2.resize(250,300)
		#form2のタイトルをユーザIDに指定
		self.form2.setWindowTitle(userid)
		

		#labelの宣言・'Tweet'とテキストを指定・位置を指定
		self.state_label=QtGui.QLabel(self.form2)
		self.state_label.setText('Tweet')
		self.state_label.setGeometry(50,50,100,50)

		#ツイートを入力するLineEditの宣言・位置を指定
		self.edit1=QtGui.QLineEdit(self.form2)
		self.edit1.setGeometry(50,100,150,50)

		#ツイート送信buttonの宣言・'send'とテキストを指定・位置を指定
		self.button1=QtGui.QPushButton('send',self.form2)
		self.button1.setGeometry(50,200,100,25)

		#ツイート送信buttonの宣言・'quit'とテキストを指定・位置を指定
		self.button2=QtGui.QPushButton('quit',self.form2)
		self.button2.setGeometry(50,250,100,25)

		#ツイートを送信するためのapiハンドルを取得
		self.api=tweepy.API(auth)
							
		#button1を押したときのイベントをsend_tweetメソッドに指定		
		self.button1.clicked.connect(self.send_tweet)
		#button1を押したときのイベントをend_clientメソッドに指定
		self.button2.clicked.connect(self.end_client)
		#form2を表示
		self.form2.show()

	#button1を押した時のイベントメソッド
	def send_tweet(self):
		#とらい!
		try:
			#edit1に入力された内容をunicodeに変換してpostに入れる
			post=unicode(self.edit1.text())
			#postをツイートとして送信
			self.api.update_status(post)
		#例外発生
		except tweepy.error.TweepError, e:
			#例外発生したときのステータス
			print str(e.response.status)
			#例外発生した時の理由
			print str(e.response.reason)
		else:
			#無事送信が完了したら出力
			print 'Accept Send'
		#edit1の内容をクリアする
		self.edit1.clear()

	#button2を押した時のイベントメソッド
	def end_client(self):
		#form2を閉じて終了する
		self.form2.close()

mainメソッド
form1の表示→form2の表示→終了
までの流れをここで行う

#main
def main():
	#別途説明
	QtCore.QTextCodec.setCodecForCStrings(QtCore.QTextCodec.codecForName('unicode'))

	#ユーザにアプリケーションを認証させるためのurlを取得
	pin_url=auth.get_authorization_url()
	#ブラウザでpin_urlを開く
	webbrowser.open(pin_url)

	#Guiを使うためにシステムに宣言
	app=QtGui.QApplication(sys.argv)
	#Form1クラスのfirstを宣言(form1が閉じるまで実行)
	first=Form1()
	#アプリケーションの終了
	app.exec_()

	#獲得したaccesstokenでusernameを取得
	username=str(auth.get_username())
	#Form2クラスのsecondを宣言
	second=Form2(username)
	#システムに全アプリケーションの終了を返す
 	sys.exit(app.exec_())

までがコードの大まかな部分になります。

別途説明の部分

↓ここの部分で

#edit1に入力された内容をunicodeに変換してpostに入れる
post=unicode(self.edit1.text())
#postをツイートとして送信
self.api.update_status(post)

PyQtのQLineEditやQLabelに入力された内容はQStringという特殊な型を持って取得されます。
そのため日本語をunicodeに変換しようとしても文字化けしてしまいます。
もちろん日本語のツイート送信にはasciiからunicodeに変換する必要があるのでこのまま送るわけにもいきません。

ここでこの一文についての説明をします

QtCore.QTextCodec.setCodecForCStrings(QtCore.QTextCodec.codecForName('unicode'))

QtCoreからQStringなどの特殊な型に対してunicodeへ変換することを許可させることができます。
あんまり詳しいことがわかってないのでなんとも言えませんがとりあえずこれを書いておけば日本語のツイートを送信することができます。

プログラム全貌

#coding: UTF-8

#systemライブラリ
import sys
#tweepyライブラリ
import tweepy
#ブラウザを開くためのライブラリ
import webbrowser
#PyQtのQtGui,QtCoreをimport
from PyQt4 import QtGui,QtCore

#developerのconsumerkey
consumer_key  = "consumerkey"
#developerのconsumersecret
consumer_secret = "consumersecret"
#oauth認証に必要なハンドルの宣言
auth=tweepy.OAuthHandler(consumer_key,consumer_secret)

#form2クラス
class Form2(object):
	#コンストラクタ(ユーザIDを受け取る)
	def __init__(self,userid):
		#form2の宣言
		self.form2=QtGui.QWidget()
		#form2のサイズ指定
		self.form2.resize(250,300)
		#form2のタイトルをユーザIDに指定
		self.form2.setWindowTitle(userid)
		

		#labelの宣言・'Tweet'とテキストを指定・位置を指定
		self.state_label=QtGui.QLabel(self.form2)
		self.state_label.setText('Tweet')
		self.state_label.setGeometry(50,50,100,50)

		#ツイートを入力するLineEditの宣言・位置を指定
		self.edit1=QtGui.QLineEdit(self.form2)
		self.edit1.setGeometry(50,100,150,50)

		#ツイート送信buttonの宣言・'send'とテキストを指定・位置を指定
		self.button1=QtGui.QPushButton('send',self.form2)
		self.button1.setGeometry(50,200,100,25)

		#ツイート送信buttonの宣言・'quit'とテキストを指定・位置を指定
		self.button2=QtGui.QPushButton('quit',self.form2)
		self.button2.setGeometry(50,250,100,25)

		#ツイートを送信するためのapiハンドルを取得
		self.api=tweepy.API(auth)
							
		#button1を押したときのイベントをsend_tweetメソッドに指定		
		self.button1.clicked.connect(self.send_tweet)
		#button1を押したときのイベントをend_clientメソッドに指定
		self.button2.clicked.connect(self.end_client)
		#form2を表示
		self.form2.show()

	#button1を押した時のイベントメソッド
	def send_tweet(self):
		#とらい!
		try:
			#edit1に入力された内容をunicodeに変換してpostに入れる
			post=unicode(self.edit1.text())
			#postをツイートとして送信
			self.api.update_status(post)
		#例外発生
		except tweepy.error.TweepError, e:
			#例外発生したときのステータス
			print str(e.response.status)
			#例外発生した時の理由
			print str(e.response.reason)
		else:
			#無事送信が完了したら出力
			print 'Accept Send'
		#edit1の内容をクリアする
		self.edit1.clear()

	#button2を押した時のイベントメソッド
	def end_client(self):
		#form2を閉じて終了する
		self.form2.close()

#form1クラス
class Form1(object):
	#コンストラクタ
	def __init__(self):
		#form1の宣言
		self.form1=QtGui.QWidget()
		#form1のサイズ指定
		self.form1.resize(200,100)
		#form1のタイトル指定
		self.form1.setWindowTitle('Setting Acount')

		#Buttonを宣言し、'send'とButtonに表示
		self.button1=QtGui.QPushButton('send',self.form1)
		#Buttonの位置を指定
		self.button1.setGeometry(50,63,100,25)

		#入力するBOXであるLineEditを宣言
		self.edit1=QtGui.QLineEdit(self.form1)
		#LineEditの位置を指定
		self.edit1.setGeometry(50,25,100,30)

		#button1を押したときのイベントをclick_forms_ok_buttonメソッドに指定
		self.button1.clicked.connect(self.click_forms_ok_button)
		#form1を表示
		self.form1.show()

	#pinコードを受け取りaccesstokenを取得するメソッド
	def get_accesstoken(self,pin_key):
		#accesstokenの取得
		auth.get_access_token(pin_key)

	#button1を押した時のイベントメソッド
	def click_forms_ok_button(self):
		#pinコードをLineEditから読み取る
		pin=self.edit1.text()
		#get_accesstokenメソッドにpinコードを渡してaccesstokenを獲得
		self.get_accesstoken(pin)
		#accesstokenを取得したのでform1を閉じる
		self.form1.close()


#main
def main():
	#別途説明
	QtCore.QTextCodec.setCodecForCStrings(QtCore.QTextCodec.codecForName('unicode'))

	#ユーザにアプリケーションを認証させるためのurlを取得
	pin_url=auth.get_authorization_url()
	#ブラウザでpin_urlを開く
	webbrowser.open(pin_url)

	#Guiを使うためにシステムに宣言
	app=QtGui.QApplication(sys.argv)
	#Form1クラスのfirstを宣言(form1が閉じるまで実行)
	first=Form1()
	#アプリケーションの終了
	app.exec_()

	#獲得したaccesstokenでusernameを取得
	username=str(auth.get_username())
	#Form2クラスのsecondを宣言
	second=Form2(username)
	#システムに全アプリケーションの終了を返す
 	sys.exit(app.exec_())

if __name__ == '__main__':
    main()

例外処理とかはほとんど入ってないです
勉強用に作ったので

フォーム画面

デザインにはほとんど凝ってないので・・・(

f:id:everysick:20130405120941j:plain

f:id:everysick:20130405120946j:plain

またデザインについてはQt Designerという便利なものがあるのでコードで設計するのが面倒だったらそっちを使えばいいと思います。