座敷牢日誌

都落ちした元SEがソフトウェアやネット関連のことを書いています

pythonでリクエストヘッダーを付与してファイルをダウンロードする

あるサイトで毎日公開されるzipファイルを、シェルスクリプト&cronで取得していたのだが、その端末が無くなってしまったので、スクリプトを新たに書き直すことにした。HTMLソースのスクレイピングgrepsedを組み合わせていたが、どうやっていたが忘れてしまったし、BeautifulSoupでやったほうがよほど簡単そうなので、全てpythonで動かすことにした。その際にちょっと悩んだのが、リクエスト送信時のヘッダ情報をどう付与するかだった。

wgetではこうやる

リクエスト時にRefererをヘッダに指定してやらないとエラーが返されてしまう。wgetでは次のように指定する。

wget http://svr1.example.com/test.zip \
--header="Referer: http://svr2.example.com/index2.html"

pythonのurllib2モジュールを使ってリクエストヘッダを付与する

単純にファイルをダウンロードしたい場合は、「urllib.urlretrieve」を使うもんだと思っていた。

import urllib
urllib.urlretrieve("http://svr1.example.com/test.zip", "test.zip")

しかし、リクエスト送信時にヘッダ情報を設定する方法が見つけられなかった。
urllib2モジュールにはRequestというクラスがあり、これでヘッダーを付与してファイルを取得することができる。

import urllib2

req = urllib2.Request("http://svr1.example.com/test.zip")
req.add_header("Referer", "http://svr2.example.com/index2.html")
with open("test.zip", "wb") as myfile:
    myfile.write(urllib2.urlopen(req).read())

urllib2にはurlretrieveがなかったのでこういう方法をとったのだけど、これがBAなのかというとあまり自信がない。

urllib.urlretrieveを使ってリクエストヘッダを付与することもできる

次のフォーラムのやり取りを参考にして、urllibのFancyURLopenerクラスを継承してヘッダを付与する方法があることを知った。

import urllib

class AppURLopener(urllib.FancyURLopener):
    version = "App/1.7"
    def __init__(self, *args):
        urllib.FancyURLopener.__init__(self, *args)
    def add_referer(self, url=None):
        if url:
            self.addheader('Referer', url)

urllib._urlopener = AppURLopener()
urllib._urlopener.add_referer("http://svr2.example.com/index2.html")
urllib.urlretrieve("http://svr1.example.com/test.zip", "test.zip")

Requestオブジェクトを使ったほうがずっとスマートだとは思うけど、どっちがいいんだろう。

広告を非表示にする