幼儿教师师德2020年第22期
信19与电10
China Computer&Communication
Python中用多线程爬取网页图像的好处
关丽梅
(武汉城市职业学院,湖北武汉430064)
摘要:线程是操作系统中非常重要的概念,它是操作系统能够分配资源和调度的最小单位,Python爬虫在从网页爬取数据时也可以使用多线程,这样可以大大提高任务的执行效率并促进系统资源的合理高效利用.基于此,本文以Python使用Beaut ifulSoup爬取一个网页内的图像为例,从代码及执行结果角度,通过对比论述使用多线程的好处.
关键词:线程;Python;爬虫;BeautifulSoup
中图分类号:TP309.7文献标识码:A文章编号:1003-9767(2020)22-063-03
Advantages of Multi Thread Crawling Web Images in Python
GUAN Limei
(Wuhan City Polytechnic,Wuhan Hubei430064,China)
Abstract:Thread is a very important concept in the operating system.It is the smallest uri让that the operating system can allocate resources and schedule.Python crawler can also u mult t hreading when crawling data from web pages,which can greatly improve the efficiency of task execution and promote the rational and efficient utilization of system resources.In this paper,Python us BeautifulSoup to crawl the image of a web page as an example,from the perspective of code and execution results,the advantages of using multithreading are discusd by comparison.
Keywords:thread;Python;crawler;BeautifulSoup
0引言
线程是操作系统能够独立调度和分配任务的最小单位,多个线程共享一个进程的全部系统资源[1-2]o当需要执行多个任务时,让多线程同时运行,可以提高执行效率。如果使用一个线程依次执行各项任务,一个任务执行完才能进行下一个,假设执行到中间某个任务时需要等待的时间较长或者卡死了,
后面的任务都做不了,这是非常麻烦的事情。Python 可以使用多线程,多个线程同时进行,互不干扰,在利用Python爬虫爬取网页上的数据时,为了提高效率也应该使用多线程。本文通过Python使用BeautifulSoup爬取一个网页图像的案例说明使用多线程的好处及用法。
1爬取网页图像的案例说明
1.1案例的要求
衣服包包指定一个网站的网址,从该页爬取页面内的全部图像,保存到本地客户端文件夹client内的子文件夹download 内,图像取名规则为下载的排序数字(即第几个被下载的),然后是扩展名。客户端的路径:项目文件夹-->client-->download->图像文件。爬虫代码所在的文件是client.py,保存在项目文件夹中的client文件夹中。
1.2案例的分析xiyang
因为一个网页有多个图像文件,所以需要找到所有图像文件的下载地址url,按每个图像的url发出请求获得文件的数据并保存到本地文件。由于下载一个图像,这个请求和保存数据的代码段就要执行一次,下载多个图像就要执行很多遍。这个代码段虽然可以直接写在循环体内,但是会使循环显得臃肿,所以可以将下载的这段代码写到download函数内,在循环体内进行函数调用就行了。为了使代码
规范整齐、好理解,可以定义2个函数:一个是爬取图像的函数imgSpider,主要功能是访问网页,获得该网页所有图像的url地址,针对每个地址调用一次download函数;另一个就是download 函数。主程序在导入基本库包设置初始参数和访问地址后,再调用爬虫函数imgSpider就可以了。
作者简介:关丽梅(1973-),女,辽宁西丰人,本科,副教授。研究方向:静态网页设计、动态网页设计、程序设计语言。
信
ia 与电
ns China Computer & Communication 專该語言2020年第22期
1.3案例的实现方法如果没有使用线程就相当于是单线程的做法。比如,对 所有的图像依次调用download 函数,只有本次download 执 行完才能进行下一个。就像多辆车子排队请求使用一条公路, 只有第一辆车子通过了,第二辆车才能动。如果某辆车抛锚 了,后面的都动不了。每个下载使用一个独立线程的做法则是多线程做法,对 每个图像的下载创建一个线程,由线程调用download 函数, 有多少图像就会创建多少线程,每个线程都独立进行下载, 多个线程可以并行运行,不依赖其他线程的执行情况。就像 多辆车子使用多条公路,一辆车子占一条公路,各辆车子是 独立行进的,多条路可
以并行,互不干扰,如果一辆车子抛 锚了,其他车辆不受影响。2单线程的做法代码#定义一个图像爬取函数def imgSpider(url):try:urls=[] #用来保存访问过的图像url req = quest.Request(url, headers=headers) resp = quest.urlopen(req)data = ad()dammit = UnicodeDammit(data, ['utf-S*, "gbk"]) # 自 动编码识别data = dammit.unicode_markup # 转换成字符串 soup = BeautifulSoup(data, "html.paTr ” ) images = soup.lect("img n ) # 取得所有图像节点 for image in images:try:src = image[n src n ] #取出图像的src 属性,即 图像名url = quest.urljoin(start_url, src)#图像的完整url 地址是start_url 拼接上文件名if url not in urls: #如果url 没有出现在urls 中, 即没有访问过urls.append(url) # 向 urls 中添加 url print(url) #打印访问的图像url 请求地址 download(url) #调用下载函数
匆匆的主要内容except Exception as err:print(err)except Exception as err:
print(err)#end def imgSpider()#定义下载图像函数
def download(url):global count try:
count=count+l if(url[len(url)-4]==n .H ): # 如果图像 url 倒数的第 4 个符号是圆点ext=url[len(url)-4:] #取得圆点后的扩展名el:
ext=req = quest.Request(url, headers=headers) resp = quest.urlopen(req,timeout= 100) data = ad() #取得图像的数据with open(,,download\V ,4-str(count)+ext,n wb H ) as f: # 下载的文件保存到download 文件夹#名称是下载到的数字序列号拼接上扩展名
f.write(data) #将数据存到文件中
print(H downloaded",str(count)+ext) # 输出下载完成
的提示except Exception as err:print(err)#end def download()#主程序from bs4 import BeautifulSoup from bs4 import UnicodeDammit import quest start_url =,,v/M # 这是中国气象网的
首页,可以换成其他网页地址headers={ "Ur-Agent" :" Mozilla/5.0 (Windows; U; Windows NT 6.0 x64; en-US; rv:1.9pre) Gecko/2008072421 Minefield/3.0.2pre M }count=0
imgSpider(start_url)
3多线程的做法代码
后文出现的所有省略的代码与单线程的代码相同#定义一个图像爬取函数
def imgSpider(url):
global threads
global count try:for image in images: try:if url not in urls: # 如果 url 没有出现在urls 中,即没有访问过count=count+l # count 保存 下载 到了第几个图像,故加1
2020年第22期
信19与电10
China Computer&Communication d=threading.Thread(target=download,args=(u
rl,count))#创建线程
d.tDaemon(Fal)#设置线程为后台线程
d.start()#启动现线程
threads.append(d)#将启动的线程添加到threads列表
except Exception as err:
print(err)
except Exception as err:
print(err)
#end def imgSpider()
#定义下载图像函数
def download(url,count):
try:
except Exception as err:
print(err)用餐礼仪
#end def download()
月古诗
#主程序
threads=[]#保存工作的所有线程
imgSpider(start_url)
for t in threads:
t.join()
print(**download End”)
4两种做法的主要代码分析
4.1单线程做法中imgSpider函数的一段代码
for image in images:#取得所有图像节点
try:快速上网
src=image[”src”]#取出图像的src属性,即图像名
quest.urlj oin(start_url,src)
#图像的完整url地址是start_url拼接上文件名
if url not in urls:#如果url没有出现在urls中,即没有访问过
urls.append(url)#向urls中添加url
print(url)#打印访问的图像url请求地址
download(url)#调用下载函数
except Exception as err:
print(err)
这个foi■循环中对每个图像依次通过访问调用download 函数实现下载,如果下载到某一个图像时受阻,即执行download中途执行不下去了,那么就无法让循环继续,后面所有的图像都不能继续下载,造成系统资源的闲置浪费及下载效率低下。
手洗衣服4.2多线程做法中imgSpider函数的一段代码
for image in images:
try:
src=image[n src n]#取出图像的src属性,即图像名
quest.urljoin(start_url,src)
#图像的完整url地址是start_url拼接上文件名
if url not in urls:#如果url没有出现在urls 中,即没有访问过
urls.append(url)#向urls中添加url
print(url)#打印访问的图像url请求地址
count=count+1#count保存下载到了第几个图像,故加1
d=threading.Thread(target=download,args=(url,cou nt))#创建线程
d.tDaemon(Fal)#设置线程为后台线程
d.start()#启动现线程
threads.append(d)#将启动的线程添加到threads 列表
except Exception as err:
print(err)
for循环内对每个图像的下载都创建了一个线程,每个线程再去调用函数download,多个线程并列执行,可以独立同时调用download函数,有效提高了爬取效率。此外,如果某一个图像的下载受阻,也只是一个线程缓慢进行,其他线程不受影响。
5结语
以下载图像为例,通过用单线程与多线程进行对比分析发现,多线程的效率更高。当然这只是一个从单一网页爬取图像的简单案例,多线程也适用于从各网站爬取复杂数据的爬虫程序,在Python中得到广泛使用,在写爬虫代码时都用多线程。
参考文献
[1]黄锐军•数据采集技术-Python网络爬虫项目化教程[M],北京:高等教育出版社,200&
[2]刘延林.Python网络爬虫开发从入门到精通[M].北京:北京大学出版社,2019.