用 python 实现一个多线程网页下载器

今天上来分享一下昨天实现的一个多线程网页下载器。

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

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

废话少说,上源码:

  1 # -*- coding:utf-8 -*-
  2 import urllib, httplib
  3 import thread
  4 import time
  5 from Queue import Queue, Empty, Full
  6 HEADERS = {"Content-type": "application/x-www-form-urlencoded",
  7                         ‘Accept-Language‘:‘zh-cn‘,
  8                         ‘User-Agent‘: ‘Mozilla/4.0 (compatible; MSIE 6.0;Windows NT 5.0)‘,
  9                         "Accept": "text/plain"}
 10 UNEXPECTED_ERROR = -1
 11 POST = ‘POST‘
 12 GET = ‘GET‘
 13 def base_log(msg):
 14     print msg
 15 def base_fail_op(task, status, log):
 16     log(‘fail op. task = %s, status = %d‘%(str(task), status))
 17 def get_remote_data(tasks, results, fail_op = base_fail_op, log = base_log):
 18     while True:
 19         task = tasks.get()
 20         try:
 21             tid = task[‘id‘]
 22             hpt = task[‘conn_args‘] # hpt <= host:port, timeout
 23         except KeyError, e:
 24             log(str(e))
 25             continue
 26         log(‘thread_%s doing task %d‘%(thread.get_ident(), tid))
 27         #log(‘hpt = ‘ + str(hpt))
 28         conn = httplib.HTTPConnection(**hpt)
 29
 30         try:
 31             params = task[‘params‘]
 32         except KeyError, e:
 33             params = {}
 34         params = urllib.urlencode(params)
 35         #log(‘params = ‘ + params)
 36
 37         try:
 38             method = task[‘method‘]
 39         except KeyError:
 40             method = ‘GET‘
 41         #log(‘method = ‘ + method)
 42
 43         try:
 44             url = task[‘url‘]
 45         except KeyError:
 46             url = ‘/‘
 47         #log(‘url = ‘ + url)
 48
 49         headers = HEADERS
 50         try:
 51             tmp = task[‘headers‘]
 52         except KeyError, e:
 53             tmp = {}
 54         headers.update(tmp)
 55         #log(‘headers = ‘ + str(headers))
 56         headers[‘Content-Length‘] = len(params)
 57
 58         try:
 59             if method == POST:
 60                 conn.request(method, url, params, headers)
 61             else:
 62                 conn.request(method, url + params)
 63             response = conn.getresponse()
 64         except Exception, e:
 65             log(‘request failed. method = %s, url = %s, params = %s headers = %s‘%(
 66                         method, url, params, headers))
 67             log(str(e))
 68             fail_op(task, UNEXPECTED_ERROR, log)
 69             continue
 70
 71         if response.status != httplib.OK:
 72             fail_op(task, response.status, log)
 73             continue
 74
 75         data = response.read()
 76         results.put((tid, data), True)
 77
 78 class HttpPool(object):
 79     def __init__(self, threads_count, fail_op, log):
 80         self._tasks = Queue()
 81         self._results = Queue()
 82
 83         for i in xrange(threads_count):
 84             thread.start_new_thread(get_remote_data,
 85                                                             (self._tasks, self._results, fail_op, log))
 86
 87     def add_task(self, tid, host, url, params, headers = {}, method = ‘GET‘, timeout = None):
 88         task = {
 89             ‘id‘ : tid,
 90             ‘conn_args‘ : {‘host‘ : host} if timeout is None else {‘host‘ : host, ‘timeout‘ : timeout},
 91             ‘headers‘ : headers,
 92             ‘url‘ : url,
 93             ‘params‘ : params,
 94             ‘method‘ : method,
 95             }
 96         try:
 97             self._tasks.put_nowait(task)
 98         except Full:
 99             return False
100         return True
101
102     def get_results(self):
103         results = []
104         while True:
105             try:
106                 res = self._results.get_nowait()
107             except Empty:
108                 break
109             results.append(res)
110         return results
111
112 def test_google(task_count, threads_count):
113     hp = HttpPool(threads_count, base_fail_op, base_log)
114     for i in xrange(task_count):
115         if hp.add_task(i,
116                 ‘www.google.cn‘,
117                 ‘/search?‘,
118                 {‘q‘ : ‘lai‘},
119 #                method = ‘POST‘
120                 ):
121             print ‘add task successed.‘
122
123     while True:
124         results = hp.get_results()
125         if not results:
126             time.sleep(1.0 * random.random())
127         for i in results:
128             print i[0], len(i[1])
129 #            print unicode(i[1], ‘gb18030‘)
130
131 if __name__ == ‘__main__‘:
132     import sys, random
133     task_count, threads_count = int(sys.argv[1]), int(sys.argv[2])
134     test_google(task_count, threads_count)

from: http://blog.csdn.net/gzlaiyonghao/article/details/4083852

时间: 2024-10-27 13:06:59

用 python 实现一个多线程网页下载器的相关文章

Python实现多线程HTTP下载器

本文将介绍使用Python编写多线程HTTP下载器,并生成.exe可执行文件. 环境:windows/Linux + Python2.7.x 单线程 在介绍多线程之前首先介绍单线程.编写单线程的思路为: 解析url: 连接web服务器: 构造http请求包: 下载文件. 接下来通过代码进行说明. 解析url 通过用户输入url进行解析.如果解析的路径为空,则赋值为'/':如果端口号为空,则赋值为"80":下载文件的文件名可根据用户的意愿进行更改(输入'y'表示更改,输入其它表示不需要更

用python实现的百度音乐下载器-python-pyqt-改进版

之前写过一个用python实现的百度新歌榜.热歌榜下载器的博文,实现了百度新歌.热门歌曲的爬取与下载.但那个采用的是单线程,网络状况一般的情况下,扫描前100首歌的时间大概得到40来秒.而且用Pyqt做的界面,在下载的过程中进行窗口操作,会出现UI阻塞的现象. 前两天有时间调整了一下,做了几方面的改进: 1.修改了UI界面阻塞的问题,下载的过程中可以进行其它的UI操作; 2.爬虫程序采用一个主线程,8个子线程的方式快速爬取,网络状况一致的情况下,将扫描100首歌曲的时间提高到了8.9秒左右:(本

爬虫学习——网页下载器和urllib2模块

什么是网页下载器? 一.网页下载器是爬虫的核心组件 二.常用的python网页下载器有urlilib2基础模块和requests第三方插件两种 urllib2支持功能:1.支持直接url下载:2.支持向网页直接输入的数据:3.支持需要登陆网页的cookie处理:4.需要代理访问的代理处理 三.urllib2的三种下载方法 方法一.直接下载法 相应代码如下: #-*-coding:utf-8-*- #调用urllib2模块 import urllib2 #直接请求 response=urllib2

Python实战:美女图片下载器,海量图片任你下载

Python应用现在如火如荼,应用范围很广.因其效率高开发迅速的优势,快速进入编程语言排行榜前几名.本系列文章致力于可以全面系统的介绍Python语言开发知识和相关知识总结.希望大家能够快速入门并学习Python这门语言. 本文是在前一部分Python基础之上Python实战:Python爬虫学习教程,获取电影排行榜,再次升级的Python网页爬虫实战课程. 1.项目概述. 利用XPath和requests模块进行网页抓取与分析,达到网页图片下载的效果. 抓爬图片地址:http://www.2c

第5章 网页下载器和urllib2模块

网页下载器:将互联网上URL对应的网页下载到本地的工具 通过网页下载器将互联网中的url网页,存储到本地或内存字符串 python有哪几种网页下载器? 1.urllib2  python官方基础模块 2.requests   python第三方包更强大 urllib2下载网页方法1:最简洁方法 url-------------------------->urllib2.urlopen(url) 代码: import urllib2 /#直接请求 response = urllib2.urlopn

Java实现的一个简单的下载器

package com.shawearn.download;import java.io.BufferedInputStream;import java.io.BufferedOutputStream;import java.io.DataInputStream;import java.io.DataOutputStream;import java.io.EOFException;import java.io.File;http://www.huiyi8.com/jiaoben/import j

python爬虫实战——5分钟做个图片自动下载器

python爬虫实战--图片自动下载器 制作爬虫的基本步骤 顺便通过这个小例子,可以掌握一些有关制作爬虫的基本的步骤. 一般来说,制作一个爬虫需要分以下几个步骤: 分析需求(对,需求分析非常重要,不要告诉我你老师没教你) 分析网页源代码,配合F12(没有F12那么乱的网页源代码,你想看死我?) 编写正则表达式或者XPath表达式(就是前面说的那个神器) 正式编写python爬虫代码 效果 运行: 恩,让我输入关键词,让我想想,输入什么好呢?好像有点暴露爱好了. 回车 好像开始下载了!好赞!,我看

【图文详解】python爬虫实战——5分钟做个图片自动下载器

python爬虫实战--图片自动下载器 之前介绍了那么多基本知识[Python爬虫]入门知识,大家也估计手痒了.想要实际做个小东西来看看,毕竟: talk is cheap show me the code! 制作爬虫的基本步骤 顺便通过这个小例子,可以掌握一些有关制作爬虫的基本的步骤. 一般来说,制作一个爬虫需要分以下几个步骤: 1. 分析需求(对,需求分析非常重要,不要告诉我你老师没教你) 2. 分析网页源代码,配合F12(没有F12那么乱的网页源代码,你想看死我?) 3. 编写正则表达式或

Bing图片下载器(Python实现)

分享一个Python实现的Bing图片下载器.下载首页图片并保存到到当前目录.其中用到了正则库re以及Request库. 大致流程如下: 1.Request抓取首页数据 2.re正则匹配首页图片URL 3.再次使用Request下载图片数据 源码: # --*-- encoding: UTF-8 --*-- """bingloader.py下载Bing.com首页图片""" import reimport sysimport osimport r