Pythonのpycurlライブラリの使い方

pythonでhttp/https通信を実現する方法のひとつである、pycurlの使い方をまとめました。

 

1 pycurlとは

pythonからlibcurlを呼ぶインターフェースを提供するライブラリです。

curlコマンドと同様に、HTML取得等のhttp/https通信することができます。

2 HTMLボディを取得

curl.setopt(pycurl.[項目], [値])で各種パラメータを設定します。

 

リクエストヘッダのUser-Agentフィールドを適切に設定しないとアクセスを拒否されるサイトが多いので、pycurl.USERAGENTで設定しています(ブラウザ種別などの詳細な設定はUser-Agent一覧を記載したページを参照してください)。

 

pycurl.PROXYに設定する値は"192.168.0.1:80"の形式の文字列です。

レスポンスコードはcurl.getinfo(pycurl.HTTP_CODE)を呼ぶと、200、404、503等の整数値が返ってきます。

import pycurl

k_curl_timeout = 6  # 6sec.
k_curl_agent = 'Mozilla/5.0'


def get_html_body(url, proxy=""):
    b = BytesIO()
    curl = pycurl.Curl()
    curl.setopt(pycurl.URL, url)
    curl.setopt(pycurl.TIMEOUT, k_curl_timeout)
    curl.setopt(pycurl.USERAGENT, k_curl_agent)
    curl.setopt(pycurl.WRITEFUNCTION, b.write)
    curl.setopt(pycurl.PROXY, proxy)
    try:
        curl.perform()
        http_code = curl.getinfo(pycurl.HTTP_CODE)
        if http_code == 200:
            retval = b.getvalue()
        else:
            retval = str(http_code)
    except Exception as e:
        retval = str(e)
    curl.close()
    return retval

なお、BytesIOのgetvalueメソッドで取得する値のデコードが必要になるかもしれません(windows-13jやcp932なページ)。

レスポンスのHTTPヘッダのcharsetを取得するか、以下の様なコードでgetvalueメソッドの戻り値をデコードすると良いでしょう。

k_charset = ['iso-8859-1', 'utf-8', 'shift-jis', 'euc-jp', 'cp932']


def decode(value):
    for charset in k_charset:
        try:
            decoded = value.decode(charset)
            return decoded
        except:
            pass
    return value

3 ファイルを取得

BytesIOのwriteメソッドではなく、ファイルオブジェクトのwriteメソッドをpycurl.WRITEFUNCTIONに設定します。

def get_file(url, name, proxy=""):
    with open(name, 'wb') as f:
        curl = pycurl.Curl()
        curl.setopt(pycurl.URL, url)
        curl.setopt(pycurl.TIMEOUT, k_curl_timeout)
        curl.setopt(pycurl.USERAGENT, k_curl_agent)
        curl.setopt(pycurl.WRITEFUNCTION, f.write)
        curl.setopt(pycurl.PROXY, proxy)
        try:
            curl.perform()
            http_code = curl.getinfo(pycurl.HTTP_CODE)
            if http_code == 200:
                retval = True
            else:
                retval = False
        except:
            retval = False
        curl.close()
        return retval

4 HTMLヘッダを取得

HTMLヘッダのみを取得する為にpycurl.HEADERとpycurl.NOBODYを1にします。

def get_html_header(url, proxy=""):
    b = BytesIO()
    curl = pycurl.Curl()
    curl.setopt(pycurl.URL, url)
    curl.setopt(pycurl.TIMEOUT, k_curl_timeout)
    curl.setopt(pycurl.USERAGENT, k_curl_agent)
    curl.setopt(pycurl.HEADER, 1)
    curl.setopt(pycurl.NOBODY, 1)
    curl.setopt(pycurl.WRITEFUNCTION, b.write)
    curl.setopt(pycurl.PROXY, proxy)
    try:
        curl.perform()
        http_code = curl.getinfo(pycurl.HTTP_CODE)
        if http_code == 200:
            retval = b.getvalue()
        else:
            retval = str(http_code)
    except Exception as e:
        retval = str(e)
    curl.close()
    return retval