2013-08-07 85 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