Python多线程抓取图片

1、基础知识

利用Python的urllib和urllib2库访问并下载网页

1.1、访问某个网址并打印

import urllib2

url = 'http://www.baidu.com'
respone = urllib2.urlopen(url)
page = respone.read()
print page


1.2、将网页保存至文件

import urllib

url = 'http://www.baidu.com'
fname = '1.html'
urllib.urlretrieve(url,fname)


1.3、伪装浏览器

某些网站拒绝爬虫的访问,此时需要将爬虫伪装成浏览器,可通过修改http包的header实现。

url = 'http://m.qiushibaike.com'
user_agent = 'Mozilla/4.0 (compatible; MSIE 5.5; Windows NT)' 
headers = { 'User-Agent' : user_agent } 
req = urllib2.Request(url, headers = headers) 
response = urllib2.urlopen(req)


1.4、文件系统操作

从网络上爬下来的资源需要保存在本地,这时需要对文件系统进行操作。判断保存的路径是否存在,若不存在则创建。

import os
fileName = 'D:/123'
if not os.path.exists(fileName):
	os.makedirs(fileName)


1.5、时间函数

每次测试或者爬取资源通常会选择不同的系统路径,每次都手动修改有点不科学,因此可选择用系统时间作为文件名。

t = time.localtime()
folderName = 'D:/TuChong/' + str(t.__getattribute__('tm_year')) + '-' + str(t.__getattribute__('tm_mon')) + '-' + str(t.__getattribute__('tm_mday')) + '-' + str(self.pageNo) +'/'


1.6、正则表达式

访问网页后,自动选择爬取哪些资源是爬虫设计的关键。从网页众多的内容中抠出你需要的资源,需要使用正则表达式,详细介绍可看:Python正则表达式指南


2、线程

Python的线程有两个基本的函数,__init__()和run()。其中__init__()负责线程的初始化,run()负责主要任务的执行。线程通过start()函数启动。

我们可以通过继承的方式建立自己的线程。

from threading import Thread

class CatchLinks(Thread):
	def __init__(self):
		pass

	def run(self):
		pass


本文的爬虫,根据用户输入的起始页数和终止页数,下载页数范围内的所有图片。

因此,每一页可以启动一个线程,负责提取本文内所有帖子的url。

然后,对于页内的每一个帖子,启动一个线程负责下载帖内的所有图片。

所以,本文定义了两种类型的线程,CatchLinks和CatchImages。


3、源代码

# coding=utf-8

# ----------------------------------
# Python多线程抓取图片
# data:2014.6.27
# author:XuZekun
# version:2.0
# ----------------------------------

import urllib2
import re
import string
import urllib
from threading import Thread
import time
import os

class CatchLinks(Thread):
	url = None
	keepRunning = False	#状态标识
	subThreads = []
	pageNo = None

	def __init__(self,url,pageNo):
		Thread.__init__(self)
		self.url = url
		self.keepRunning = True
		self.pageNo = pageNo
	
	# 获取当前页面所有图片主题的二级链接
	def getLinks(self):
		try:
			respone = urllib2.urlopen(self.url)
			mainPage = respone.read()
		except:
			print 'Get MainPage failed!'

		links =  re.findall('class="theatre-view" href="(.*?)" title="(.*?)">',mainPage,re.S)
		return links

	#获取子链接下所有图片的url,并下载保存
	def getImgs(self,links):
		for item in links:
			if self.keepRunning == True:
				print item[0]
				#print item[1]
				title = item[1].decode("utf-8").replace('/','').replace("'",'')
				print title
				t = CatchImages(item[0],title,self.pageNo)
				t.start()
				self.subThreads.append(t)
	
	def run(self):
		links = self.getLinks()
		self.getImgs(links)

	def quitThreads(self):
		for subThread in self.subThreads:
			subThread.keepRunning = False
			print 'subThread quit'


class CatchImages(Thread):
	url = None
	keepRunning = False
	title = None
	pageNo = None

	def __init__(self,url,title,pageNo):
		Thread.__init__(self)
		self.url = url
		self.title = title
		self.keepRunning = True
		self.pageNo = pageNo

	def getImgs(self,link,title):
		try:
			subPageRespone = urllib2.urlopen(link)
			subPage = subPageRespone.read()
			print 'subThread start'
		except:
			print 'Get subPage:' + title + 'failed!'

		imgurls = re.findall('<figure style=.*?<img src="(.*?)" class="img-responsive copyright-contextmenu"',subPage,re.S)	

		t = time.localtime()
		folderName = 'D:/TuChong/' + str(t.__getattribute__('tm_year')) + '-' + str(t.__getattribute__('tm_mon')) + '-' \
						+ str(t.__getattribute__('tm_mday')) + '-' + str(self.pageNo) +'/'
		if not os.path.exists(folderName):
			os.makedirs(folderName)

		for i in range(len(imgurls)):
			if self.keepRunning == True:
				fname = folderName + title + str(i) + '.jpg'	#图片保存路径
				try:
					urllib.urlretrieve(imgurls[i],fname)
				except:
					print 'write file ' + title + ' error'
					print imgurls[i]

	def run(self):
		self.getImgs(self.url,self.title)


def quit(threads,startPage):
	for i in range(len(threads)):
		threads[i].quitThreads()
		threads[i].keepRunning = False
		print 'thread %d quit' %(i + startPage)
 	print 'exit'


if __name__ == '__main__':
	url = 'http://tuchong.com/tags/%E4%BA%BA%E5%83%8F?page='
	threads = []
	startPage = 8
	endPage = 9

	for i in range(startPage,endPage+1):	#每一页发起一个线程
		print 'thread %d start' %i
		t = CatchLinks(url + str(i),i)
		t.start()
		threads.append(t)

	while True:
		cmd = raw_input()
		if cmd =='quit':
			quit(threads,startPage)


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值