2013-08-07 79 views
1

我有視頻450MB。我想將其上傳到xvideos.com我在我的腳本中使用上傳大文件太慢

xvideos_log_data = {'login': xv_login, 
        'password': password, 
        'referer': 'http://upload.xvideos.com/account', 
        'log': 'Login to your account'} 

def xvideos(f_path): 
    _print('xvideos started uploading...') 

    try: 
     s = requests.Session() 
     s.post('http://upload.xvideos.com/account', data=xvideos_log_data, headers=headers) 
     rp = s.get('http://upload.xvideos.com/account/uploads/new') 
     apc = re.search(r'onclick="launch_upload_basic\(\'(.*?)\'\)', rp.text).group(1) 

     payload = {'APC_UPLOAD_PROGRESS': apc, 
        'message': ''} 
     r = s.post('http://upload.xvideos.com/account/uploads/submit?video_type=other', 
        data=payload, 
        files={'upload_file': open(f_path, 'rb')}, headers=headers) 
     edt = re.search(r'<a href="(.*?)" target="_top"', r.text) 
     if edt is None: 
      _print(re.search(r'inlineError.*>(.*?)<', r.text).group(1)) 
      return 
     payload = {'title': make_title(), 
        'keywords': ' '.join(make_tags()), 
        'description': choice(description), 
        'hide': 0, 
        'update_video_information': 'Update information'} 
     r = s.post('http://upload.xvideos.com' + edt.group(1), data=payload, headers=headers) 

     _print('xvideos finished uploading') 

    except Exception as error: 
     _print(error) 

    finally: 
     return 

問題是上傳速度很慢,但成功。我在我的服務器上啓動腳本。當我嘗試在瀏覽器中上傳時 - 速度很快。

可能是什麼問題?

回答

4

問題很可能是請求庫下面的Python代碼httplib

在較老的Python版本(2.2)中分塊編碼串流是非常可怕的,現在它非常糟糕。通過直接在套接字上替換定製的http層並更好地處理緩衝區,我可以得到一個應用程序以2%的CPU進行流式處理,並像快速網絡鏈接上的完全鏈接利用率。由於非常低效的緩衝,Httplib只能達到1 MB/s,CPU佔用率達到50%或更多。 httplib適合短時間的請求,但不適合大量上傳(不需要調整/黑客入侵)。

你可以嘗試一些東西,使事情變得更好,這取決於你的網絡和操作系統設置上:

  1. 調整你的套接字緩衝區通過setsockoptionSO_SNDBUF,如果你不需要很多的連接,並擁有快速網絡,類似於4 MB或更大的東西是可能的,以減少快速管道上總是空的緩衝區的問題(10GE和更多)

  2. 使用不同的http庫(例如pycurl或Twisted,以某些修補程序爲例)轉讓,例如使每個socket.send()調用移動幾MB的數據而不是一些小的4kB緩衝區。

如果做得對,Python幾乎可以充分利用10 GE鏈接。

+0

其實,你很可能通過簡單的加載/ mmaping整個文件一次,並把它當作數據,而不是通過把事情快爲你的用例,如果你有一個64位Python和足夠的內存文件參數。 (因爲你可能會避免使用這種緩慢的分塊編碼)。 – schlenk

+0

我在ubuntu 12.10 x64服​​務器上有1GB RAM。我會嘗試這些想法。謝謝。 – Alex

2

我上傳到Amazon S3時遇到同樣的問題。

我的瀏覽器可以以8MB/s的速度上傳,但httplib或只需要1MB/s的請求。

經過大量的搜索,我發現httplib確實是負責任的。

塊的大小是固定的8192

我建立這個猴修補程序和爲20MB 500MB的文件測試了許多值。

400000,我得到了比我的瀏覽器相同的速度:8MB /秒。 :)

import httplib 
import httplib2 

def patch_httplib(bsize=400000): 
    """ Update httplib block size for faster upload (Default if bsize=None) """ 
    if bsize is None: 
     bsize = 8192 
    def send(self, data, sblocks=bsize): 
     """Send `data' to the server.""" 
     if self.sock is None: 
      if self.auto_open: 
       self.connect() 
      else: 
       raise httplib.NotConnected() 
     if self.debuglevel > 0: 
      print "send:", repr(data) 
     if hasattr(data, 'read') and not isinstance(data, list): 
      if self.debuglevel > 0: print "sendIng a read()able" 
      datablock = data.read(sblocks) 
      while datablock: 
       self.sock.sendall(datablock) 
       datablock = data.read(sblocks) 
     else: 
      self.sock.sendall(data) 
    httplib2.httplib.HTTPConnection.send = send