python实现多线程网页下载器


Posted in Python onApril 15, 2018

本文为大家分享了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之关于循环的小伎俩
Oct 02 Python
对Python新手编程过程中如何规避一些常见问题的建议
Apr 01 Python
Python3调用微信企业号API发送文本消息代码示例
Nov 10 Python
python验证码识别实例代码
Feb 03 Python
如何使用 Pylint 来规范 Python 代码风格(来自IBM)
Apr 06 Python
Python实现的绘制三维双螺旋线图形功能示例
Jun 23 Python
Python列表list排列组合操作示例
Dec 18 Python
python实现微信每日一句自动发送给喜欢的人
Apr 29 Python
Python数据处理篇之Sympy系列(五)---解方程
Oct 12 Python
python 实现快速生成连续、随机字母列表
Nov 28 Python
详细分析Python垃圾回收机制
Jul 01 Python
手把手教你将Flask应用封装成Docker服务的实现
Aug 19 Python
Python实现定时精度可调节的定时器
Apr 15 #Python
Python编写一个优美的下载器
Apr 15 #Python
python实现音乐下载器
Apr 15 #Python
tensorflow 1.0用CNN进行图像分类
Apr 15 #Python
tensorflow学习笔记之mnist的卷积神经网络实例
Apr 15 #Python
tensorflow学习笔记之简单的神经网络训练和测试
Apr 15 #Python
Pytorch入门之mnist分类实例
Apr 14 #Python
You might like
php 设计模式之 工厂模式
2008/12/19 PHP
php 验证码制作(网树注释思想)
2009/07/20 PHP
JQuery中根据属性或属性值获得元素(6种情况获取方法)
2013/01/17 Javascript
ie8 不支持new Date(2012-11-10)问题的解决方法
2013/07/31 Javascript
推荐5 个常用的JavaScript调试技巧
2015/01/08 Javascript
jquery validate表单验证的基本用法入门
2016/01/18 Javascript
Javascript实现图片轮播效果(一)让图片跳动起来
2016/02/17 Javascript
微信小程序 Video API实例详解
2016/10/02 Javascript
阿里云ecs服务器中安装部署node.js的步骤
2016/10/08 Javascript
Three.js基础部分学习
2017/01/08 Javascript
vue2滚动条加载更多数据实现代码
2017/01/10 Javascript
Django与Vue语法的冲突问题完美解决方法
2017/12/14 Javascript
Vue 使用 Mint UI 实现左滑删除效果CellSwipe
2018/04/27 Javascript
echarts.js 动态生成多个图表 使用vue封装组件操作
2020/07/19 Javascript
js实现移动端图片滑块验证功能
2020/09/29 Javascript
Python break语句详解
2014/03/11 Python
Python实现的批量下载RFC文档
2015/03/10 Python
在Python中封装GObject模块进行图形化程序编程的教程
2015/04/14 Python
python使用wxPython打开并播放wav文件的方法
2015/04/24 Python
python如何为被装饰的函数保留元数据
2018/03/21 Python
解决Python中list里的中文输出到html模板里的问题
2018/12/17 Python
selenium+python截图不成功的解决方法
2019/01/30 Python
python同时替换多个字符串方法示例
2019/09/17 Python
使用TensorFlow-Slim进行图像分类的实现
2019/12/31 Python
如何在Python对Excel进行读取
2020/06/04 Python
网络公司美工设计工作个人的自我评价
2013/11/03 职场文书
高中毕业生自我鉴定例文
2013/12/29 职场文书
党课知识竞赛主持词
2014/04/01 职场文书
分公司经理任命书
2014/06/05 职场文书
信息员培训方案
2014/06/12 职场文书
银行求职自荐信
2014/06/30 职场文书
2015元旦家电促销活动策划方案
2014/12/09 职场文书
2016年“5.12”护士节致辞
2015/07/31 职场文书
解决Jupyter-notebook不弹出默认浏览器的问题
2021/03/30 Python
MySQL创建索引需要了解的
2021/04/08 MySQL
在Java中Collection的一些常用方法总结
2021/06/13 Java/Android