Edited at

PycURLでHTTPリクエストあれこれ

More than 3 years have passed since last update.

pythonでHTTPリクエストを送信するには...requests?

いえいえ、PycURLだってあります。

細かくいろいろあれこれするときはPycURLだよねって人、気持ちわかります :smile:

たまには趣向を変えましょう。

ここではPycURLを使っていろいろいろするためのやり方を書いていきます。


PycURLとは...

http://pycurl.io/

https://pypi.python.org/pypi/pycurl

PycURLはlibcurlのためのPythonインタフェースです。大概requestsでもおんなじことができる(はず)。


インストール

pip でインストールします。

$ pip install pycurl

http://pycurl.io/docs/latest/index.html#installation にインストールの説明があります。

サーバには https://gist.github.com/TakesxiSximada/d2792ef0b6ef2947402cca008b0323ea を使います。server.pyをダウンロードして以下を実行してください。

$ python server.py


メソッドの設定

REST APIのメソッドを指定してリクエストを送信します。


GET


get_example_default.py

import pycurl

curl = pycurl.Curl()
curl.setopt(pycurl.URL, 'http://127.0.0.1:8000')
curl.perform()


実行結果

デフォルトの挙動ではrespose bodyは標準出力に書き出されます。

$ python get_example_default.py

OK

メソッドを指定しない場合はGETになります。

メソッド名を明示的に指定したい場合は Curlオブジェクトに pycurl.CUSTOMREQUESTを設定します。


get_example.py

import pycurl

curl = pycurl.Curl()
curl.setopt(pycurl.URL, 'http://127.0.0.1:8000')
curl.setopt(pycurl.CUSTOMREQUEST, 'GET')
curl.perform()



POST

import pycurl

curl = pycurl.Curl()
curl.setopt(pycurl.URL, 'http://127.0.0.1:8000')
curl.setopt(pycurl.CUSTOMREQUEST, 'POST')
curl.perform()

POSTFIELDを設定した場合はデフォルトでPOSTになります。

import urllib.parse

import pycurl

curl = pycurl.Curl()
curl.setopt(pycurl.URL, 'http://127.0.0.1:8000')
field_data = urllib.parse.urlencode({'key': 'value'})
curl.setopt(pycurl.POSTFIELDS, field_data)
curl.perform()


PUT

import pycurl

curl = pycurl.Curl()
curl.setopt(pycurl.URL, 'http://127.0.0.1:8000')
curl.setopt(pycurl.CUSTOMREQUEST, 'PUT')
curl.perform()


PATCH

import pycurl

curl = pycurl.Curl()
curl.setopt(pycurl.URL, 'http://127.0.0.1:8000')
curl.setopt(pycurl.CUSTOMREQUEST, 'PATCH')
curl.perform()


HEAD

import pycurl

curl = pycurl.Curl()
curl.setopt(pycurl.URL, 'http://127.0.0.1:8000')
curl.setopt(pycurl.CUSTOMREQUEST, 'HEAD')
curl.perform()


DELETE

import pycurl

curl = pycurl.Curl()
curl.setopt(pycurl.URL, 'http://127.0.0.1:8000')
curl.setopt(pycurl.CUSTOMREQUEST, 'DELETE')
curl.perform()


OPTIONS

import pycurl

curl = pycurl.Curl()
curl.setopt(pycurl.URL, 'http://127.0.0.1:8000')
curl.setopt(pycurl.CUSTOMREQUEST, 'OPTIONS')
curl.perform()


詳細情報の表示

pycurl.VERBOSEをTrueで設定すると実行時の詳細情報を取得できます。

import pycurl

curl = pycurl.Curl()
curl.setopt(pycurl.URL, 'http://127.0.0.1:8000')
curl.setopt(pycurl.VERBOSE, True)
curl.perform()

実行結果

$ python verbose.py

* Rebuilt URL to: http://127.0.0.1:8000/
* Trying 127.0.0.1...
* Connected to 127.0.0.1 (127.0.0.1) port 8000 (#0)
> GET / HTTP/1.1
Host: 127.0.0.1:8000
User-Agent: PycURL/7.43.0 libcurl/7.43.0 OpenSSL/1.0.2d zlib/1.2.8
Accept: */*

* HTTP 1.0, assume close after body
< HTTP/1.0 200 OK
< Server: BaseHTTP/0.6 Python/3.5.0
< Date: Sat, 21 May 2016 08:26:41 GMT
<
OK
* Closing connection 0


User Agentの変更

pycurl.USERAGENTでUserAgentを設定できます。


set_ua.py

import pycurl

curl = pycurl.Curl()
curl.setopt(pycurl.URL, 'http://127.0.0.1:8000')
curl.setopt(pycurl.VERBOSE, True)
curl.setopt(pycurl.USERAGENT, 'yay (^-^)/~')
curl.perform()


実行結果

$ python set_ua.py

* Rebuilt URL to: http://127.0.0.1:8000/
* Trying 127.0.0.1...
* Connected to 127.0.0.1 (127.0.0.1) port 8000 (#0)
> GET / HTTP/1.1
Host: 127.0.0.1:8000
User-Agent: yay (^-^)/~
Accept: */*

* HTTP 1.0, assume close after body
< HTTP/1.0 200 OK
< Server: BaseHTTP/0.6 Python/3.5.0
< Date: Sat, 21 May 2016 08:37:27 GMT
<
OK
* Closing connection 0


UserAgentはfake-userangetを使うと楽かも。。。

UserAgentを設定するときはいつもfake-useragetを使っているので一応書いておきます。

https://pypi.python.org/pypi/fake-useragent


インストール

$ pip install fake-useragent


PycURLにfake-useragentを使ってChromeのUserAgentを設定する

fake_useragent.UserAgent().chrome でchromeのUAが取得できます。


set_ua_fakeua.py

import pycurl

import fake_useragent

curl = pycurl.Curl()
curl.setopt(pycurl.URL, 'http://127.0.0.1:8000')
curl.setopt(pycurl.VERBOSE, True)

ua = fake_useragent.UserAgent()
curl.setopt(pycurl.USERAGENT, ua.chrome)
curl.perform()


実行結果

$ python set_ua_fakeua.py

* Rebuilt URL to: http://127.0.0.1:8000/
* Trying 127.0.0.1...
* Connected to 127.0.0.1 (127.0.0.1) port 8000 (#0)
> GET / HTTP/1.1
Host: 127.0.0.1:8000
User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/34.0.1847.137 Safari/4E423F
Accept: */*

* HTTP 1.0, assume close after body
< HTTP/1.0 200 OK
< Server: BaseHTTP/0.6 Python/3.5.0
< Date: Sat, 21 May 2016 08:43:20 GMT
<
OK
* Closing connection 0


分割ダウンロード

ファイルを途中からダウンロードしたりしたいこと...ありますよねー。

あるでしょ?

あるんですよ。

うん、あるある。

pycurl.RESUME_FROMを設定すると設定したbyte以降からダウンロードできます。

resumeはサーバ側が対応してないとダメなので、gistのデータを途中からダウンロードしてみます。


resume.py

import pycurl

curl = pycurl.Curl()
curl.setopt(pycurl.URL, 'https://gist.githubusercontent.com/TakesxiSximada/d2792ef0b6ef2947402cca008b0323ea/raw/82d677309084d66247a15ce1640bac44a4b23248/server.py')
curl.setopt(pycurl.VERBOSE, True)
curl.setopt(pycurl.RESUME_FROM, 100)
curl.perform()



プログレスバーの表示

プログレスバーは progressbar パッケージを使うと楽なのでそれを使ってみます。

https://pypi.python.org/pypi/progressbar


インストール

$ pip install progressbar


簡単なprogressbarを表示


progress.py

import io

import pycurl
import progressbar

class PluggableProgress:
def __init__(self, progress_plugin):
self.progress_plugin = progress_plugin

def __call__(self, total_to_download, total_downloaded,
total_to_upload, total_uploaded):
if total_to_download:
percent = int(total_downloaded / total_to_download * 100)
self.progress_plugin.update(percent)

progress_plugin = progressbar.ProgressBar(max_value=progressbar.UnknownLength)
progress = PluggableProgress(progress_plugin)

fp = io.BytesIO()
curl = pycurl.Curl()
curl.setopt(pycurl.URL, '大きめのファイルのURL') # noqa
curl.setopt(pycurl.NOPROGRESS, 0)
curl.setopt(pycurl.PROGRESSFUNCTION, progress)
curl.setopt(pycurl.WRITEDATA, fp)
curl.perform()
progress_plugin.finish()