一、为什么使用多线程爬虫?
首先,单线程的执行程序是顺序执行的,下一个任务必须等待前一个执行完成才接着执行,如果前面发生阻塞,后面的操作不会继续执行。
要解决这个问题可以使用多线程,爬虫属于i/o操作,大批量的请求——响应过程中,阻塞消耗的时间会无限放大,如果爬取的数据很少,
需求量不大,可能无关紧要,但是一般爬虫爬取的数量都是比较大的,所以必须考虑这个阻塞的问题。使用多线程可以有效解决这个问题,
它可以充分利用cpu资源,提高cpu的使用率。
二、怎么使用多线程爬虫?
两种方式:1.面向对象式的编程(基于类);2.面向函数式编程(基于函数)
这里使用面向对象式编程。话不多说,直接上代码,这里以爬取百度美女吧的图片为例,链接:https://tieba.baidu.com/f?kw=%E7%BE%8E%E5%A5%B3&ie=utf-8&pn=0
import requests
import re
import threading #导入多线程模块
from queue import Queue #导入队列模块
class Spider(threading.Thread): #创建爬虫类,必须继承threading.Thread类
def __init__(self,queue,path): #初始化两个属性,queue:队列对象;path:图片保存路径
threading.Thread.__init__(self)
self.queue=queue
self.path=path
def run(self): #重写run()方法,注意是重写,不能随便定义
while not self.queue.empty(): #队列对象不为空继续往下执行代码
url=self.queue.get() #获取队列一个元素赋值给url
try:
fun_download(url,self.path) #执行功能函数,即下面的下载图片函数,方式很多,这里使用正则,普通的爬虫不再一一注释
except Exception as e:
print(e,'下载失败!')
def fun_download(url,path):
url=url
headers={'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/81.0.4044.138 Safari/537.36'}
response=requests.get(url=url,headers=headers)
data1=response.text
data2=re.compile('<a rel="noreferrer" href="(.*?)" title="(.*?)" target="_blank" class="j_th_tit ">')
data3=re.findall(data2,data1)
dict={}
for data4 in data3:
dict['img_link']='https://tieba.baidu.com/'+data4[0]
dict['title']=data4[1]
response1=requests.get(url=dict['img_link'],headers=headers).text
data5=re.compile('<img class="BDE_Image" src="(.*?)" size=')
data6=re.findall(data5,response1)
if data6:
for data7 in data6:
img_data=requests.get(url=data7,headers=headers).content
img_name=data7.split('/')[-1].split('.')[0]
with open(path+img_name+data7[-4:],'ab')as f:
print('正在下载:',img_name)
f.write(img_data)
if __name__ == '__main__':
q=Queue() #创建队列对象
pages=int(input('输入抓取的页数:'))
urls=['https://tieba.baidu.com/f?kw=%E7%BE%8E%E5%A5%B3&ie=utf-8&pn={}'.format(str(50*page)) for page in range(pages)]#列表推导式,储存爬取的url
path='F:\\美女吧\\' #图片保存路径
for url in urls: #遍历urls,写入队列对象
q.put(url)
for _ in range(pages): #创建多线程
spider=Spider(q,path) #创建Spider对象
spider.start() #开始执行多线程任务
q.join() #队列为空时退出多线程任务
多线程速度比单线程要快很多,执行的过程可以看出。下载效果图,2秒就一堆了。
到此结束,刚写博客,有什么不足多多包涵,感谢!