1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

pycURLでCurlMultiのレスポンスをアーカイブに保存する

Last updated at Posted at 2018-03-09

pycURLの単体版は結構情報あったのですが、並行リクエストするCurlMultiの情報が少なかったのでサンプル。ストリームのまま直接アーカイブに保存しています。

import pycurl
import time
import io
import tarfile
import datetime

urls = [{"url":r"https://www.yahoo.co.jp/", "key":"yahoo"},
        {"url":r"https://qiita.com/", "key":"qiita"}]
TIMEOUT = 10# 10秒

mh = pycurl.CurlMulti()
reqs = []
for url in urls:
    c = pycurl.Curl()
    r = io.BytesIO()
    c.setopt(pycurl.URL, url["url"])
    c.setopt(pycurl.TRANSFERTEXT, True)
    c.setopt(pycurl.WRITEDATA, r)
    c.setopt(pycurl.SSL_VERIFYPEER, False)
    c.setopt(pycurl.SSL_VERIFYHOST, False)
    #c.setopt(c.VERBOSE, True) #デバッグ用
    if TIMEOUT > 0:
        c.setopt(pycurl.TIMEOUT, TIMEOUT)
        c.setopt(pycurl.CONNECTTIMEOUT, TIMEOUT)
    mh.add_handle(c)
    reqs.append((c, r, url))

performed = False
while True:
    if performed:
        ret = mh.select(TIMEOUT)
        if ret == -1:  continue
    while True:
        ret, num_handles = mh.perform()
        time.sleep(1)
        performed = True
        if ret != pycurl.E_CALL_MULTI_PERFORM: break
    if num_handles == 0: break

with tarfile.open("archive.tar.xz", "w:xz") as tar:
    for req in reqs:
        req[1].seek(0) #これをしないとエラー
        info = tarfile.TarInfo(f"{req[2]['key']}.html")
        info.size = len(req[1].getbuffer())
        info.mtime = datetime.datetime.now().timestamp()
        tar.addfile(info, req[1])

pycURL自体がlibcurlをPythonに持ってきただけなので、同じような実装をしているPHPの情報が参考になりました。curlのオプションはPHPのページを見るといいでしょう。pycURLとほぼ一緒です。

cURL 転送用オプションを設定する - PHP.net
http://php.net/manual/ja/function.curl-setopt.php

とりあえず動くレベルのものなので、サーバーがエラー返してきたときの対応はしていません。PHPですが、以下の記事を参考にするともっと良くなると思います。

curl_multiでHTTP並行リクエストを行うサンプル
https://qiita.com/Hiraku/items/1c67b51040246efb4254

追記:環境によっては「pycurl: libcurl link-time ssl backend (nss) is different from compile-time ssl backend (openssl)」と怒られることがあります。解決法は以下の通りです。
https://qiita.com/kirishimaru/items/722776766da890fd853f

追記:結構メモリ使うので、メモリ溢れそうなら一度中間ファイルを作りましょう。

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?