YAMAGUCHI::weblog

海水パンツとゴーグルで、巨万の富を築きました。カリブの怪物、フリーアルバイター瞳です。

urllib2のみでmultipart/form-dataを送る

はじめに

サワディーカップ(こんにちは)、Python界のミステリハンターです。さて、PyCon mini JPから早くも1週間が経ちまして、僕もPythonやってかないといかんなー、と思った次第です。そこで、早速Webクローラーを書きまして、そのときにformデータをmultipartで送信する部分がありましたので、こんな感じに実装したよというのをメモしておきます。

multipart/form-data関連リンク

まあ要はurlencodeで送信してた内容を区切り線で分けてbodyに突っ込みました、ちゃんちゃん、っつーことでいいんすかね。

こんな感じに実装した

urllib2を使ったのはヘッダの追加が簡単だったからです。httplibを使う例が多いですが、やってる内容をみるとurllib2のが楽だったりします。

import urllib2

url = r"http://test.example.com/path/to/form"
encoding = "euc-jp"
boundary = u"--------python"

# formの内容の辞書
form_dict = dict(user=u"hoge",
                 pass=u"日本語もおk")

# form_dict辞書内の要素数だけ区切り線で分けたbodyを作る
def multipart_formdata(form_dict):
    disposition = u'Content-Disposition: form-data; name="%s"'
    lines = []
    for k, v in form_dict.iteritems():
        lines.append(u'--' + boundary)
        lines.append(disposition % k)
        lines.append(u'')
        lines.append(v)
    lines.append(u"--" + boundary + u"--")
    lines.append(u'')
    value = u"\r\n".join(lines)
    return value.encode(encoding)

# ヘッダにContent-Typeを指定
def request_with_multipart_formdata():
    req = urllib2.Request(url)
    req.add_header("Content-Type",
                   "multipart/form-data; boundary=%s" % boundary.encode(encoding))

    data = multipart_formdata(form_dict)
    conn = urllib2.urlopen(req, data)

これはフォームデータを送るような簡単な場合ですが、画像ファイルなどを送信する場合はもうちょい手が加わります。今回は実装してませんが、ほんのちょっと手を加えるだけです。