web-dev-qa-db-ja.com

urllib2を使用してWebサイトにログイン-Python 2.7

OKそれが理にかなっている場合....

ウェブサイトごとに異なるログインフォームなどを使用していることに気づきました。それでは、各ウェブサイトに対して最適化する方法を理解するにはどうすればよいですか。私はhtmlファイルで何かを探す必要があると仮定していますが、何がわからないのですか。

Mechanizeや他のライブラリ(他のすべての答えはここにあり、実際に何が起こっているのかを学ぶのを助けていない)を使用したくありません。

Urllib2のドキュメントは本当に助けにはなりません。

ありがとう。

36
tommo

この方法でログインをしばらくしていないと言って、これを序文にします。そのため、より「受け入れられた」方法のいくつかを逃す可能性があります。

これがあなたが望んでいるものかどうかはわかりませんが、mechanizeのようなライブラリやSeleniumのようなより堅牢なフレームワークがなく、基本的な場合はフォーム自体を見て、 inputsを探します。たとえば、www.reddit.com、およびレンダリングされたページのソースを表示すると、次のフォームが見つかります。

<form method="post" action="https://ssl.reddit.com/post/login" id="login_login-main"
  class="login-form login-form-side">
    <input type="hidden" name="op" value="login-main" />
    <input name="user" placeholder="username" type="text" maxlength="20" tabindex="1" />
    <input name="passwd" placeholder="password" type="password" tabindex="1" />

    <div class="status"></div>

    <div id="remember-me">
      <input type="checkbox" name="rem" id="rem-login-main" tabindex="1" />
      <label for="rem-login-main">remember me</label>
      <a class="recover-password" href="/password">reset password</a>
    </div>

    <div class="submit">
      <button class="btn" type="submit" tabindex="1">login</button>
    </div>

    <div class="clear"></div>
</form>

ここには、いくつかのinputがあります-opuserpasswd、およびrem。また、actionパラメーターに注意してください。これは、フォームが投稿されるURLであり、したがってターゲットになります。そのため、最後のステップはパラメーターをペイロードにパックし、POSTリクエストとしてaction URLに送信することです。また、以下では、新しいopenerを作成し、Cookieを処理する機能を追加し、ヘッダーも追加します。これにより、リクエストを実行するためのわずかに堅牢なオープナーが提供されます)。

import cookielib
import urllib
import urllib2


# Store the cookies and create an opener that will hold them
cj = cookielib.CookieJar()
opener = urllib2.build_opener(urllib2.HTTPCookieProcessor(cj))

# Add our headers
opener.addheaders = [('User-agent', 'RedditTesting')]

# Install our opener (note that this changes the global opener to the one
# we just made, but you can also just call opener.open() if you want)
urllib2.install_opener(opener)

# The action/ target from the form
authentication_url = 'https://ssl.reddit.com/post/login'

# Input parameters we are going to send
payload = {
  'op': 'login-main',
  'user': '<username>',
  'passwd': '<password>'
  }

# Use urllib to encode the payload
data = urllib.urlencode(payload)

# Build our Request object (supplying 'data' makes it a POST)
req = urllib2.Request(authentication_url, data)

# Make the request and read the response
resp = urllib2.urlopen(req)
contents = resp.read()

これははるかに複雑になる可能性があることに注意してください-たとえば、GMailでこれを行うこともできますが、毎回変更されるパラメーター(GALXパラメーターなど)をプルする必要があります。繰り返しますが、これがあなたが望んでいたものかどうかはわかりませんが、それが役立つことを願っています。

49
RocketDonkey