python 网页爬虫+保存图片+多线程+网络代理

今天,又算是浪费了一天了。python爬虫,之前写过简单的版本,那个时候还不懂原理,现在算是收尾吧。


以前对网页爬虫不了解,感觉非常神奇,但是解开这面面纱,似乎里面的原理并不是很难掌握。首先,明白一个概念,HTTP协议,为什么叫超文本协议。超文本的概念,是所有的数据几乎都使用文本模式传输,包括文字,图像等,然后在一个网页中,需要做的是解析这些字符数据,并还原成原始的文件。

爬虫的概念,是以一个网页作为起点,从中发现更多的链接和数据信息,并依此以树形展开,可以想象成为一颗树,对每一个网页,需要按照需求对数据进行筛选(找图片,呢还是找关键字,或者找音频等),最后,根据筛选出的URL,对数据进行下载。大致步骤为:

网页==》网页树==》筛选信息==》下载

笔者这里就以网页图片作为例子:

比如,一张网页里,可能有很多张图片,首先最基本的是对这一张网页中所有的图片链接要能够识别出来,这里一般的方法是对网页文本根据正规式进行匹配,从而搜集包含图片的链接。eg:reg = r"""src\s*="?(\S+)\.jpg"""。其次,对于这些链接进行文件。看起来很抽象的东西,这两步就能实现。接着,网页树就有点难,需要从网页中找到有用的网页链接,然后对这些连接又一次进行筛选,有点像递归。这里的难点很多,比如,当网页链接数量非常多的时候,如何有效筛选有效连接,如何控制搜索深度,如何分配进程等等。

另外,由于目前很多国外的网站是上不去的,所以,有些网页数据下载需要通过代理;另外,考虑到有些机器性能较好,也实现了多线程的机制。笔者进行了一天的调研,终于调试通过。以下是代码:

 

import re
import os
import sys
import time  
import threading
import socket
import urllib
import urllib2


server = '127.0.0.1'
port = '8087'
timeout = 720
socket.setdefaulttimeout(timeout)

class timer(threading.Thread): #The timer class is derived from the class threading.Thread  
	def __init__(self, num, interval,dir,url):  
		threading.Thread.__init__(self)  
		self.thread_num = num
		self.interval = interval  
		self.url = url  
		self.dir = dir  
		self.thread_stop = False  
	def run(self): #Overwrite run() method, put what you want the thread do here  
		#while not self.thread_stop:  
			DownloadImgs(self.interval,self.url,self.dir)
		#print 'Thread Object(%d), Time:%s' %(self.thread_num, time.ctime())  
		#time.sleep(self.interval)  
	def stop(self):  
		self.thread_stop = True 

def getContent(url,type):
	print(">>start connecting:%s" % url)
	from urllib2 import Request, urlopen, URLError, HTTPError
	
	proxy = urllib2.ProxyHandler({'http':'http://127.0.0.1:8087'}) 
	opener = urllib2.build_opener(proxy,urllib2.HTTPHandler) 
	urllib2.install_opener(opener)
	try:
		urlHandler = urllib2.urlopen(url)
		headers = urlHandler.info().headers
		length = 0
		for header in headers:
			if header.find('Length') != -1:
				length = header.split(':')[-1].strip()
				length = int(length)
		if(type=="img" and length<15000):
			print(" >>>>>>>>%d" % length)
			dataStr = 'EOF'
		else:
			print(" ++++++++%d" % length)
			dataStr = urlHandler.read()
	except HTTPError, e:
		print 'The server couldn\'t fulfill the request.'
		print 'Error code: ', e.code
	except URLError, e:
		print 'We failed to reach a server.'
		print 'Reason: ', e.reason
	else:
#	print("%s" % dataStr)
#	f = open("text.txt",'wb')
#	f.write(dataStr)
#	f.close()
		return dataStr
def DownloadImgs(interval,url,dir):
	dataStr = getContent(url,"html")
	print("...:%s" % url)
	if(os.path.isdir(dir) == False):
		os.mkdir(dir);
	reg = r"""src\s*="?(\S+)\.jpg"""
	imgre = re.compile(reg)
	imglist = imgre.findall(dataStr)
	x = 0
	for imgurl in imglist:
		imgurl =''.join('%s.jpg' % imgurl)
		if(imgurl.find('http:')>=0):
			print ("\tdownloading: %s,%s" % (x,imgurl))
			imgdata=getContent(imgurl,"img")
			if(imgdata != 'EOF'):
				outputFile = '%s/%s.jpg' % (dir,x)
				f = open(outputFile,'wb')
				f.write(imgdata)
				f.close()
				x = x + 1
		else:
			print ("\tcannot connect: %s" % imgurl)
		time.sleep(interval)

url_="http://tieba.baidu.com/p/";
id=2460150866;
n=1;

thread=[]
for i in range(0, n):
	url=''.join('%s%d' % (url_,id + i))
	dir=''.join('PIC%d' % (id+i) )
	print("######dir = %s, id = %d" % (dir,id+i))
	thread.append(timer(1, 1,dir,url))
for i in range(0, n):
	thread[i].start()



#for i in range(0, n):
#	url=''.join('%s%d' % (url_,id + i))
#	dir=''.join('PIC%d' % i)
#	print("######dir = %s, id = %d" % (dir,id))
#	DownloadImgs(0.1,url,dir)


 



 

posted @ 2013-08-20 21:39  pangbangb  阅读(632)  评论(0编辑  收藏  举报