前提・実現したいこと
Golangでスクレイピングを行なっています。
そこで、ツイッターの特定のユーザーのイイね一覧を取得しようとしています。
しかし、イイねはログインしていないと取得することはできません。
そこで、ログイン後イイねページにリダイレクトするリクエストを送ります。
試していること
curlでは
curl -L POST https://twitter.com/sessions --data-urlencode "authenticity_token=hoge" --data-urlencode "session[username_or_email]=hoge" --data-urlencode "session[password]=hoge" --data-urlencode "redirect_after_login=/hoge/likes" --data-urlencode "ui_metrics=hoge"
とすればうまく取得できています。
しかし、Golangでは
values := url.Values{} values.Add("authenticity_token", "hoge") values.Add("session[username_or_email]", "hoge") values.Add("session[password]", "hoge") values.Add("redirect_after_login", "hoge") values.Add("ui_metrics", "hoge") req, err := http.NewRequest( "POST", "https://twitter.com/sessions", strings.NewReader(values.Encode()), ) client := &http.Client{} resp, err := client.Do(req) if err != nil { fmt.Println(err) return }
としても、 https://twitter.com/login/error?username_or_email=hoge&redirect_after_login=hoge にリダイレクトされうまくログインできません。
Postmanでx-www-form-urlencodedを指定してdataを送信しも同様のページにリダイレクトされます。
なにが違うんでしょうか。
追記
values := url.Values{} values.Add("authenticity_token", "hoge") values.Add("session[username_or_email]", os.Getenv("TWITTER_USER_NAME")) values.Add("session[password]", os.Getenv("TWITTER_PASSWORD")) values.Add("redirect_after_login", "/"+os.Getenv("TWITTER_USER_NAME")+"/likes") values.Add("ui_metrics", "hoge") req, err := http.NewRequest( "POST", "https://twitter.com/sessions", strings.NewReader(values.Encode()), ) req.Header.Add("Content-Type", "application/x-www-form-urlencoded") jar, _ := cookiejar.New(nil) client := &http.Client{Jar: jar} resp, err := client.Do(req)
このようにしても/login/errorにリダイレクトされます。
login/errorでsession[username_or_email]やredirect_after_loginの値が使われているので、valuesは正しく渡っています。
本当に原因がわかりません。。。
curlのラージLオプション無しで動作しない事を確認してみてください。
(動作しないことが確認できたらラージLオプションの機能がどういったものかを調べましょう)
-Lがリダイレクト先まで追跡するオプションなのは知っております。
-Lでリクエストした場合、you are being redirected のようなページが出力され正しくログインします。
したがって、Golangでは期待通りの動作をしていないということになります。
あ、すいません、Goのhttp.Clientは3xx系のHTTPステータスコードが返ったらリダイレクト先へ再度リクエストを投げるのが標準の挙動でした。
このあたりの挙動が問題ではなさそうですね・・・。
req.Header.Add("Content-Type", "application/x-www-form-urlencoded") をつけてみるとか。
req.Header.Add("Content-Type", "application/x-www-form-urlencoded") は試しましたが、不可能でした。
うーむ。おそらく同じ条件じゃないから再現しにくいですね。これは「アカウントが二段階認証を有効にしていない」ということが必須?
あと、「この形のログイン」自体イレギュラーな方法かと。
開発者APIキーを取得してOAuth経由でアクセスするのが順当かも。