VBScript でバッチ twitter 投稿


  本来は API を使うので、必要ありませんが mixi と同じでした




現在は動作しません

当時は試しにやってみたのは、API の無い mixi のテストのついでだったのですが、Twitter は API で
普通に投稿できるので以下を参照して下さい

VBScript : Twitter API を呼び出して投稿する

また、mixi ボイスのほうも試してみたら、少し問題があったので修正して動くようにしました

VBScript でバッチ mixi ボイス投稿




2010/05/26 更新

1) デバックフラグを追加
2) ログインをユーザ名に変更( ルートは混雑する可能性があります )
3) rfc3986_convert を追加


VBScript でバッチ mixi ボイス投稿 が動作したので、Twitter も試してみたら、基本的には同じでした。

ログインが https で、ログイン後、セッション用のクッキーを取得して、そのクッキーをセットして
投稿画面を呼び出すと、投稿用のキーが hidden のフィールドにセットされているので取り出して、
普通に POST します。

※ 環境によっては、lang=ja もセットする必要があるかもしれません
※ クッキーは無くても動作しました
※ アクセストークンを取得するページの仕様が変わると動作しなくなります
※ 現在 API で呼び出すテスト中です

関連する記事

PHP : CodeIgniter + Twitter API Library での oauth 投稿の具体的なポイント
Ruby + mechanize : mixi ボイスとTwitterへの同時投稿のプロトタイプ
Ruby + mechanize : mixi ボイスへの投稿を php と連携して行う








  Twitter.vbs ( 最新コード ) : 2010/05/26




1) デバックフラグを追加しました( テスト以外で実際に利用する場合は、False にします )
2) アクセストークンを取得する為のページをユーザページより取得する為に、ログインをユーザ名にしました
  ( ルートは混雑する可能性があります )
3) 次の段階として、正式な API でテストする予定なので rfc3986_convert を追加しました。

関連する記事

PHP/JavaScript/ASP/ps/py : 処理別の urlencode の結果の違い



  

' ***********************************************************
' Twittre 投稿
' ***********************************************************
bDebug = True
strText = "VBScriptから投稿しています"

Set objHTTP = Wscript.CreateObject("MSXML2.XMLHTTP")
Set Stream = Wscript.CreateObject("ADODB.Stream")
Set Stream2 = Wscript.CreateObject("ADODB.Stream")
Set StreamBin = Wscript.CreateObject("ADODB.Stream")

strUser = "ユーザー名"
strPass = "パスワード"
strLoginTargetPath = "https://twitter.com/sessions"
strMainPagePath = "http://twitter.com/" & strUser
strTargetPath = "http://twitter.com/status/update"


Call objHTTP.Open( "POST",strLoginTargetPath, False )
Call objHTTP.setRequestHeader("Content-Type", "application/x-www-form-urlencoded")
strData = ""
strData = strData & "session%5Busername_or_email%5D="&strUser
strData = strData & "&session%5Bpassword%5D="&strPass
Call objHTTP.SetRequestHeader("Content-Length",Len(strData))
Call objHTTP.Send(strData)

' ***********************************************************
' 返されたヘッダー
' ***********************************************************
strHeaders = objHTTP.getAllResponseHeaders()

if bDebug then
	if 2 = MsgBox( strHeaders, 1 ) then
		Wscript.Quit
	end if
end if

' ***********************************************************
' ヘッダーを改行で分解
' ***********************************************************
aHeader = Split(strHeaders,vbCrLf)
strCookie = ""

' ***********************************************************
' Set-Cookie を取得
' ( これが無くても動くようです )
' ***********************************************************
For I = 0 to Ubound(aHeader)

	if Left(aHeader(I),10) = "Set-Cookie" then
		aCookie = Split( aHeader(I), ":" )
		strWork = Trim(aCookie(1))
		aCookie = Split( strWork, ";" )
		strWork = Trim(aCookie(0))
		if strCookie <> "" then
			strCookie = strCookie & " "
		end if
		if Left(strWork,8) = "_twitter" then
			strCookie = strCookie & strWork & ";"
		end if
	end if

Next

if bDebug then
	if 2 = MsgBox( strCookie, 1 ) then
		Wscript.Quit
	end if
end if

' ***********************************************************
' メインページへアクセス
' ***********************************************************
Call objHTTP.Open("GET",strMainPagePath,False)
' これが無くても動くようです
' ( アクセストークンの埋め込まれたページが取得できた )
Call objHTTP.setRequestHeader("Cookie", strCookie )
Call objHTTP.Send()

if bDebug then
	if 2 = MsgBox( objHTTP.responseText, 1 ) then
		Wscript.Quit
	end if
end if


' ***********************************************************
' アクセス用のトークンを取得
' ***********************************************************
Set regEx = New RegExp
 
regEx.IgnoreCase = True
regEx.Global = True
 
regEx.Pattern = "authenticity_token"" type=""hidden"" value=""([^""]+)"""
 
Set Matches = regEx.Execute( objHTTP.responseText )
For Each Match in Matches
	strPostKey = Match.SubMatches(0)
	Exit For
Next

if bDebug then
	if 2 = MsgBox( strPostKey, 1 ) then
		Wscript.Quit
	end if
end if


' ***********************************************************
' 投稿
' ***********************************************************
Call objHTTP.Open("POST",strTargetPath,False)
Call objHTTP.setRequestHeader("Content-Type", "application/x-www-form-urlencoded")
strData = "status=" & rfc3986_convert(URLEncode(strText))
strData = strData & "&authenticity_token=" & strPostKey
Call objHTTP.SetRequestHeader("Content-Length",Len(strData))
Call objHTTP.Send(strData)

'Wscript.Echo objHTTP.responseText
Wscript.Echo "OK"

' ***********************************************************
' SHIFT_JIS を UTF-8 に変換して URLエンコード
' ※ 全ての文字をパーセントエンコーディングします
' ***********************************************************
Function URLEncode(str)

	Stream.Open
	Stream.Charset = "shift_jis"
	' shift_jis で入力文字を書き込む
	Stream.WriteText str
	' コピーの為にデータポインタを先頭にセット
	Stream.Position = 0
 
	Stream2.Open
	Stream2.Charset = "utf-8"
	' shift_jis を utf-8 に変換
	Stream.CopyTo Stream2
	Stream.Close

	' コピーの為にデータポインタを先頭にセット
	Stream2.Position = 0

	' バイナリで開く
	StreamBin.Open
 	StreamBin.Type = 1

	' テキストをバイナリに変換
	Stream2.CopyTo StreamBin
	Stream2.Close

	' 読み込みの為にデータポインタを先頭にセット
	StreamBin.Position = 0

	Buffer = ""
	' BOMを取り去る
	StreamBin.Read(3)
	Do while not StreamBin.EOS
		LineBuffer = StreamBin.Read(16)
 
		For i = 1 to LenB( LineBuffer )
			CWork = MidB(LineBuffer,i,1)
			Cwork = AscB(Cwork)
			Cwork = Hex(Cwork)
			Cwork = Ucase(Cwork)
			if Len(Cwork) = 1 then
				Buffer = Buffer & "%0" & Cwork
			else
				Buffer = Buffer & "%" & Cwork
			end if
		Next
 
	Loop

	StreamBin.Close

	URLEncode = Buffer

End Function

' ***********************************************************
' 仕様を明確にする為に単純変換
' ***********************************************************
Function rfc3986_convert(str)

	Dim strResult,I,strWork

	strResult = str

	strResult = Replace(strResult,"%2D", "-")
	strResult = Replace(strResult,"%2E", ".")

	' 0〜9
	For I = &H30 to &H39
		strWork = Hex(I)
		strWork = "%" & Ucase(strWork)
		strResult = Replace(strResult,strWork, Chr(I))
	Next

	' A〜Z
	For I = &H41 to &H5A
		strWork = Hex(I)
		strWork = "%" & Ucase(strWork)
		strResult = Replace(strResult,strWork, Chr(I))
	Next

	strResult = Replace(strResult,"%5F", "_")

	' a〜z
	For I = &H61 to &H7A
		strWork = Hex(I)
		strWork = "%" & Ucase(strWork)
		strResult = Replace(strResult,strWork, Chr(I))
	Next

	strResult = Replace(strResult,"%7E", "~")
	
	rfc3986_convert = strResult

End Function
  

  Twitter.vbs ( 旧コード )

データを追って行くと、何故か同名フィールドが二つあったり、クッキーエントリが同じのが二つ
あったりして、トラップかと思いましたが、無視して動きました。作成側のチェック漏れでしょうね。

※ デバッグ用のコードをコメントで残しています

  

' ***********************************************************
' ( 連続実行を想定しているので、クライアント用オブジェクト )
' ***********************************************************
Set objHTTP = Wscript.CreateObject("MSXML2.XMLHTTP")
' ***********************************************************
' キャラクタセット変換用
' ***********************************************************
Set Stream = Wscript.CreateObject("ADODB.Stream")
Set Stream2 = Wscript.CreateObject("ADODB.Stream")
' ***********************************************************
' URLエンコード用
' ***********************************************************
Set StreamBin = Wscript.CreateObject("ADODB.Stream")

Call objHTTP.Open("POST","https://twitter.com/sessions",False)
Call objHTTP.setRequestHeader("Content-Type", "application/x-www-form-urlencoded")
strData = ""
strData = strData & "session%5Busername_or_email%5D=メールアドレス"
strData = strData & "&session%5Bpassword%5D=パスワード"
Call objHTTP.SetRequestHeader("Content-Length",Len(strData))
Call objHTTP.Send(strData)

strHeaders = objHTTP.getAllResponseHeaders()

'Wscript.Echo strHeaders
'Wscript.Quit

aHeader = Split(strHeaders,vbCrLf)
strCookie = ""

For I = 0 to Ubound(aHeader)

	if Left(aHeader(I),10) = "Set-Cookie" then
		aCookie = Split( aHeader(I), ":" )
		strWork = Trim(aCookie(1))
		aCookie = Split( strWork, ";" )
		strWork = Trim(aCookie(0))
		if strCookie <> "" then
			strCookie = strCookie & " "
		end if
		if Left(strWork,8) = "_twitter" then
			strCookie = strCookie & strWork & ";"
		end if
	end if

Next

'Wscript.Echo strCookie
'Wscript.Quit

Call objHTTP.Open("GET","http://twitter.com/",False)
Call objHTTP.setRequestHeader("Cookie", strCookie )
Call objHTTP.Send()

'Wscript.Echo objHTTP.responseText
'Wscript.Quit

Set regEx = New RegExp
 
regEx.IgnoreCase = True
regEx.Global = True
 
regEx.Pattern = "authenticity_token"" type=""hidden"" value=""([^""]+)"""
 
Set Matches = regEx.Execute( objHTTP.responseText )
For Each Match in Matches
	strPostKey = Match.SubMatches(0)
	Exit For
Next

'Wscript.Echo strPostKey
'Wscript.Quit

Call objHTTP.Open("POST","http://twitter.com/status/update",False)
Call objHTTP.setRequestHeader("Content-Type", "application/x-www-form-urlencoded")
strData = "status=" & URLEncode("いつまで有効が解りませんが、" & _
	"VBScript でアプリケーションのバッチ投稿が可能です")
strData = strData & "&authenticity_token=" & strPostKey
Call objHTTP.SetRequestHeader("Content-Length",Len(strData))
Call objHTTP.Send(strData)

'Wscript.Echo objHTTP.responseText
Wscript.Echo "OK"


' ***********************************************************
' SHIFT_JIS を UTF-8 に変換して URLエンコード
' ***********************************************************
Function URLEncode(str)

	Stream.Open
	Stream.Charset = "shift_jis"
	' shift_jis で入力文字を書き込む
	Stream.WriteText str
	' コピーの為にデータポインタを先頭にセット
	Stream.Position = 0
 
	Stream2.Open
	Stream2.Charset = "utf-8"
	' shift_jis を utf-8 に変換
	Stream.CopyTo Stream2
	Stream.Close

	' コピーの為にデータポインタを先頭にセット
	Stream2.Position = 0

	' バイナリで開く
	StreamBin.Open
 	StreamBin.Type = 1

	' テキストをバイナリに変換
	Stream2.CopyTo StreamBin
	Stream2.Close

	' 読み込みの為にデータポインタを先頭にセット
	StreamBin.Position = 0

	Buffer = ""
	' BOMを取り去る
	StreamBin.Read(3)
	Do while not StreamBin.EOS
		LineBuffer = StreamBin.Read(16)
 
		For i = 1 to LenB( LineBuffer )
			CWork = MidB(LineBuffer,i,1)
			Cwork = AscB(Cwork)
			Cwork = Hex(Cwork)
			Cwork = Ucase(Cwork)
			if Len(Cwork) = 1 then
				Buffer = Buffer & "%0" & Cwork
			else
				Buffer = Buffer & "%" & Cwork
			end if
		Next
 
	Loop

	StreamBin.Close

	URLEncode = Buffer

End Function
  




yahoo  google  MSDN  MSDN(us)  WinFAQ  Win Howto  tohoho  ie_DHTML  vector  wdic  辞書  天気 


[realwebapp]
Mozilla/5.0 AppleWebKit/537.36 (KHTML, like Gecko; compatible; ClaudeBot/1.0; +claudebot@anthropic.com)
24/04/19 19:13:36
InfoBoard Version 1.00 : Language=Perl

1 BatchHelper COMprog CommonSpec Cprog CprogBase CprogSAMPLE CprogSTD CprogSTD2 CprogWinsock Cygwin GameScript HTML HTMLcss InstallShield InstallShieldFunc JScript JScriptSAMPLE Jsfuncs LLINK OldProg OracleGold OracleSilver PRO PRObrowser PROc PROconePOINT PROcontrol PROftpclient PROjscript PROmailer PROperl PROperlCHAT PROphp PROphpLesson PROphpLesson2 PROphpLesson3 PROphpfunction PROphpfunctionArray PROphpfunctionMisc PROphpfunctionString PROsql PROvb PROvbFunction PROvbString PROvbdbmtn PROvbonepoint PROwebapp PROwin1POINT PROwinSYSTEM PROwinYOROZU PROwindows ProjectBoard RealPHP ScriptAPP ScriptMaster VBRealtime Vsfuncs a1root access accreq adsi ajax amazon argus asp aspSample aspVarious aspdotnet aw2kinst cappvariety centura ckeyword classStyle cmaterial cmbin cmdbapp cmenum cmlang cmlistbox cmstd cmstdseed cmtxt cs daz3d db dbCommon dbaccess dnettool dos download flex2 flex3 flex4 framemtn framereq freeWorld freesoft gimp ginpro giodownload google hdml home hta htmlDom ie9svg install java javaSwing javascript jetsql jquery jsp jspTest jspVarious lightbox listasp listmsapi listmsie listmsiis listmsnt listmspatch listmsscript listmsvb listmsvc memo ms msde mysql netbeans oraPlsql oracle oracleWiper oraclehelper orafunc other panoramio pear perl personal pgdojo pgdojo_cal pgdojo_holiday pgdojo_idx pgdojo_ref pgdojo_req php phpVarious phpguide plsql postgres ps r205 realC realwebapp regex rgaki ruby rule sboard sc scprint scquest sdb sdbquest seesaa setup sh_Imagick sh_canvas sh_dotnet sh_google sh_tool sh_web shadowbox shgm shjquery shvbs shweb sjscript skadai skywalker smalltech sperl sqlq src systemdoc tcpip tegaki three toolbox twitter typeface usb useXML vb vbdb vbsfunc vbsguide vbsrc vpc wcsignup webanymind webappgen webclass webparts webtool webwsh win8 winofsql wmi work wp youtube