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实现文本文件合并
Dec 29 Python
Python实现读取并保存文件的类
May 11 Python
tensorflow 使用flags定义命令行参数的方法
Apr 23 Python
Python 读写文件的操作代码
Sep 20 Python
对python中的高效迭代器函数详解
Oct 18 Python
使用python批量读取word文档并整理关键信息到excel表格的实例
Nov 07 Python
Pycharm以root权限运行脚本的方法
Jan 19 Python
python如何获取列表中每个元素的下标位置
Jul 01 Python
解决python多行注释引发缩进错误的问题
Aug 23 Python
Python3如何对urllib和urllib2进行重构
Nov 25 Python
利用python绘制正态分布曲线
Jan 04 Python
Django框架中模型的用法
Jun 10 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
在PWS上安装PHP4.0正式版
2006/10/09 PHP
PHP5中的时间相差8小时的解决办法
2008/03/28 PHP
php旋转图片90度的方法
2013/11/07 PHP
PHP网页游戏学习之Xnova(ogame)源码解读(十三)
2014/06/26 PHP
ThinkPHP无限级分类原理实现留言与回复功能实例
2014/10/31 PHP
PHP获取服务器端信息的方法
2014/11/28 PHP
PHP制作百度词典查词采集器
2015/01/29 PHP
CodeIgniter配置之autoload.php自动加载用法分析
2016/01/20 PHP
用javascript父窗口控制只弹出一个子窗口
2007/04/10 Javascript
用javascript实现的仿Flash广告图片轮换效果
2007/04/24 Javascript
兼容IE与firefox火狐的回车事件(js与jquery)
2010/10/20 Javascript
web的各种前端打印方法之jquery打印插件PrintArea实现网页打印
2013/01/09 Javascript
jQuery中nextAll()方法用法实例
2015/01/07 Javascript
详解JavaScript for循环中发送AJAX请求问题
2020/06/23 Javascript
Angular动态添加、删除输入框并计算值实例代码
2017/03/29 Javascript
JS简单获取当前日期和农历日期的方法
2017/04/17 Javascript
JavaScript实现购物车基本功能
2017/07/21 Javascript
js实现canvas保存图片为png格式并下载到本地的方法
2017/08/31 Javascript
JavaScript实现的原生态Tab标签页功能【兼容IE6】
2017/09/18 Javascript
JS笛卡尔积算法与多重数组笛卡尔积实现方法示例
2017/12/01 Javascript
微信小程序基于slider组件动态修改标签透明度的方法示例
2017/12/04 Javascript
vue中的过滤器实例代码详解
2019/06/06 Javascript
nodejs中内置模块fs,path常见的用法说明
2020/11/07 NodeJs
python实现爬虫统计学校BBS男女比例之多线程爬虫(二)
2015/12/31 Python
Python实现二维数组按照某行或列排序的方法【numpy lexsort】
2017/09/22 Python
Python解析命令行读取参数--argparse模块使用方法
2018/01/23 Python
浅谈tensorflow 中tf.concat()的使用
2020/02/07 Python
使用Python文件读写,自定义分隔符(custom delimiter)
2020/07/05 Python
解决python便携版无法直接运行py文件的问题
2020/09/01 Python
人力资源部副职的竞聘演讲稿
2014/01/07 职场文书
讲座主持词
2014/03/20 职场文书
房产公证书范本
2014/04/10 职场文书
2014党的群众路线教育实践活动总结报告
2014/10/31 职场文书
大学生学期个人总结
2015/02/12 职场文书
2016教师国培研修感言
2015/12/08 职场文书
小学音乐课歌曲《堆雪人》教学反思
2016/02/18 职场文书