python实现多线程网页下载器

 更新时间:2018年04月15日 16:03:04   作者:赖勇浩  
这篇文章主要为大家详细介绍了python实现一个多线程网页下载器,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

本文为大家分享了python实现的一个多线程网页下载器,供大家参考,具体内容如下

这是一个有着真实需求的实现,我的用途是拿它来通过 HTTP 方式向服务器提交游戏数据。把它放上来也是想大家帮忙挑刺,找找 bug,让它工作得更好。

keywords:python,http,multi-threads,thread,threading,httplib,urllib,urllib2,Queue,http pool,httppool

废话少说,上源码:

# -*- coding:utf-8 -*- 
import urllib, httplib 
import thread 
import time 
from Queue import Queue, Empty, Full 
HEADERS = {"Content-type": "application/x-www-form-urlencoded", 
            'Accept-Language':'zh-cn', 
            'User-Agent': 'Mozilla/4.0 (compatible; MSIE 6.0;Windows NT 5.0)', 
            "Accept": "text/plain"} 
UNEXPECTED_ERROR = -1 
POST = 'POST' 
GET = 'GET' 
def base_log(msg): 
  print msg 
def base_fail_op(task, status, log): 
  log('fail op. task = %s, status = %d'%(str(task), status)) 
def get_remote_data(tasks, results, fail_op = base_fail_op, log = base_log): 
  while True: 
    task = tasks.get() 
    try: 
      tid = task['id'] 
      hpt = task['conn_args'] # hpt <= host:port, timeout 
    except KeyError, e: 
      log(str(e)) 
      continue 
    log('thread_%s doing task %d'%(thread.get_ident(), tid)) 
    #log('hpt = ' + str(hpt)) 
    conn = httplib.HTTPConnection(**hpt) 
       
    try: 
      params = task['params'] 
    except KeyError, e: 
      params = {} 
    params = urllib.urlencode(params) 
    #log('params = ' + params) 
     
    try: 
      method = task['method'] 
    except KeyError: 
      method = 'GET' 
    #log('method = ' + method) 
     
    try: 
      url = task['url'] 
    except KeyError: 
      url = '/' 
    #log('url = ' + url) 
     
    headers = HEADERS 
    try: 
      tmp = task['headers'] 
    except KeyError, e: 
      tmp = {} 
    headers.update(tmp) 
    #log('headers = ' + str(headers)) 
    headers['Content-Length'] = len(params) 
     
    try: 
      if method == POST: 
        conn.request(method, url, params, headers) 
      else: 
        conn.request(method, url + params) 
      response = conn.getresponse() 
    except Exception, e: 
      log('request failed. method = %s, url = %s, params = %s headers = %s'%( 
            method, url, params, headers)) 
      log(str(e)) 
      fail_op(task, UNEXPECTED_ERROR, log) 
      continue 
       
    if response.status != httplib.OK: 
      fail_op(task, response.status, log) 
      continue 
       
    data = response.read() 
    results.put((tid, data), True) 
     
class HttpPool(object): 
  def __init__(self, threads_count, fail_op, log): 
    self._tasks = Queue() 
    self._results = Queue() 
     
    for i in xrange(threads_count): 
      thread.start_new_thread(get_remote_data,  
                              (self._tasks, self._results, fail_op, log)) 
       
  def add_task(self, tid, host, url, params, headers = {}, method = 'GET', timeout = None): 
    task = { 
      'id' : tid, 
      'conn_args' : {'host' : host} if timeout is None else {'host' : host, 'timeout' : timeout}, 
      'headers' : headers, 
      'url' : url, 
      'params' : params, 
      'method' : method, 
      } 
    try: 
      self._tasks.put_nowait(task) 
    except Full: 
      return False 
    return True 
     
  def get_results(self): 
    results = [] 
    while True: 
      try: 
        res = self._results.get_nowait() 
      except Empty: 
        break 
      results.append(res) 
    return results 
     
def test_google(task_count, threads_count): 
  hp = HttpPool(threads_count, base_fail_op, base_log) 
  for i in xrange(task_count): 
    if hp.add_task(i, 
        'www.google.cn', 
        '/search?', 
        {'q' : 'lai'}, 
#        method = 'POST' 
        ): 
      print 'add task successed.' 
       
  while True: 
    results = hp.get_results() 
    if not results: 
      time.sleep(1.0 * random.random()) 
    for i in results: 
      print i[0], len(i[1]) 
#      print unicode(i[1], 'gb18030') 
       
if __name__ == '__main__': 
  import sys, random 
  task_count, threads_count = int(sys.argv[1]), int(sys.argv[2]) 
  test_google(task_count, threads_count)

 有兴趣想尝试运行的朋友,可以把它保存为 xxxx.py,然后执行 python xxxx.py 10 4,其中 10 表示向 google.cn 请求 10 次查询,4 表示由 4 条线程来执行这些任务。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持脚本之家。

相关文章

  • 一文带你探寻Python中的迭代器

    一文带你探寻Python中的迭代器

    你知道for...in是底层原理是什么样的么?这篇文章就来和大家详细讲一讲Python中迭代器的的相关知识,文中的示例代码讲解详细,感兴趣的可以了解一下
    2023-04-04
  • 详解Python中math和decimal模块的解析与实践

    详解Python中math和decimal模块的解析与实践

    在Python中,math 和 decimal 模块是处理数学运算的重要工具,本文将深入探讨这两个模块的基础知识,并通过实际的代码示例演示它们的用法,希望对大家有所帮助
    2024-02-02
  • Python+Pyecharts实现散点图的绘制

    Python+Pyecharts实现散点图的绘制

    散点图是指在回归分析中,数据点在直角坐标系平面上的分布图,散点图表示因变量随自变量而变化的大致趋势,据此可以选择合适的函数对数据点进行拟合。本文将利用Python Pyecharts实现散点图的绘制,需要的可以参考一下
    2022-06-06
  • python操作excel的包(openpyxl、xlsxwriter)

    python操作excel的包(openpyxl、xlsxwriter)

    这篇文章主要为大家详细介绍了python操作excel的包,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2018-06-06
  • Python中类型关系和继承关系实例详解

    Python中类型关系和继承关系实例详解

    这篇文章主要介绍了Python中类型关系和继承关系,较为详细的分析了Python中类型关系和继承关系的原理与使用技巧,具有一定参考借鉴价值,需要的朋友可以参考下
    2015-05-05
  • Python利用 SVM 算法实现识别手写数字

    Python利用 SVM 算法实现识别手写数字

    支持向量机 (Support Vector Machine, SVM) 是一种监督学习技术,它通过根据指定的类对训练数据进行最佳分离,从而在高维空间中构建一个或一组超平面。本文将介绍通过SVM算法实现手写数字的识别,需要的可以了解一下
    2021-12-12
  • python3+pyqt5+itchat微信定时发送消息的方法

    python3+pyqt5+itchat微信定时发送消息的方法

    今天小编就为大家分享一篇python3+pyqt5+itchat微信定时发送消息的方法,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2019-02-02
  • python 装饰器带参数和不带参数步骤详解

    python 装饰器带参数和不带参数步骤详解

    装饰器是Python语言中一种特殊的语法,用于在不修改原函数代码的情况下,为函数添加额外的功能或修改函数的行为,这篇文章主要介绍了python装饰器带参数和不带参数的相关知识,需要的朋友可以参考下
    2024-05-05
  • 在anaconda中配置graphviz包的详细过程

    在anaconda中配置graphviz包的详细过程

    graphviz是贝尔实验室开发的一个开源的工具包,它使用一个特定的DSL(领域特定语言):dot作为脚本语言,然后使用布局引擎来解析此脚本,并完成自动布局,这篇文章主要介绍了如何在anaconda中配置graphviz包,需要的朋友可以参考下
    2023-02-02
  • OpenCV实战之OpenCV中的颜色空间

    OpenCV实战之OpenCV中的颜色空间

    这篇文章主要介绍了OpenCV实战之OpenCV中的颜色空间,解计算机视觉中常用的色彩空间,并将其用于基于颜色分割。我们还将用C ++和Python共享演示代码,下文详细内容需要的小伙伴可以参考一下
    2022-04-04

最新评论