在python学习笔记4-爬取一系列网页的相关图片 中,我用 requests+BS4 爬取了一个系列网页的图片。
但是,效率太低。
究其原因是,图片是一张一张下载的,一张下载完毕后,才能下载下一张。能不能同时下载多张呢?
答案是肯定的,利用 python 中的线程就可以做到同时下载多张图片,提高下载效率。
首先,导入相关的模块,其中的 threading 就是 python 线程模块。
# -*- coding:utf-8 -*-
import os
import requests # requests 模块
from bs4 import BeautifulSoup # 解析 HTML 的模块 导入 BS ,版本 4。
import lxml # bs4的解析插件模块
import time
import threading
定义一些可能用到的变量
# 定义 第一个页面的网址和该系列页面的根目录,防止图片用的是相对路径
weburl = r"https://www.xx.com/2019/1211/47543.html"
webroot = r"https://www.xx.com/2019/1211/"
# 翻页的, 当前页面class。具体分析见上一篇文章。
pageRe = "thisclass"
# 设置文件夹路径
localURL = r"images/"
# 设置页面路径 list
pagesList = [weburl] # 默认第一个页面
# 设置图片路径 list,所有的图片都要放在这个 list 里。
srcList = []
# 设置请求 headers,伪装浏览器 并接受中文数据
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.79 Safari/537.36',
'Accept-Language': 'zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2',
'Connection': 'keep-alive'
}
定义几个要用到的函数
# 获取指定页面的HTML
def getHTML(weburl):
webreq = requests.get(weburl,headers=headers)
webreq.encoding = webreq.apparent_encoding # 防止中文乱码
return webreq.text
# 解析指定页面的HTML,获取图片路径 list
def getWebImgSRC(bs,pageurl):
global srcList
# 用 BeautifulSoup 获取页面中指定位置的图片
imgs = bs.select(".content img")
for item in imgs:
srcList.append( item.get("src") ) # 获取每张图片的路径,存入srcList 中
print(pageurl+" 图片数组获取完成")
# 递归调用,获取网页 list
def getWebList(pageurl):
global pagesList
print("开始获取"+pageurl+"的信息")
webreq = requests.get( pageurl ,headers=headers ) # 从第一个页面开始分析翻页
webreq.encoding = webreq.apparent_encoding # 防止中文乱码
html = webreq.text
bs = BeautifulSoup(html,"lxml")
getWebImgSRC(bs, pageurl) # 解析页面获取 图片路径到 srcList 里
# 利用 BeautifulSoup 获取翻页的 li。
pagesLi = bs.select(".dede_pages li")
for index in range(len(pagesLi)): # 因为要获取当前页的索引,所以就利用索引遍历翻页li标签
if pageRe in str(pagesLi[index].get("class")):
if index + 1 >= len(pagesLi):
print("页面已经翻完啦~")
return False
# 获取下一个页面的地址
nextPage = str(pagesLi[index + 1].find("a").get("href"))
pagesList.append(webroot+nextPage)
break
getWebList(webroot+nextPage) # 开始递归调用
开始执行代码:主要思想就是,让每个图片都用一个线程去下载,就相当于多了很多帮手,帮我们下载,可以大大提高页面的下载效率。
# 开始执行代码
start = time.time()
getWebList(pagesList[0]) # 从第一个页面开始爬取各个页面路径
print( "图片下载开始:" )
downloadThreads = [] # 下载线程 的 list
for item in srcList: # 多线程依次下载图片
# 创建一个线程对象
downloadThread = threading.Thread(target=downImage, args=(item,) )
downloadThreads.append(downloadThread)
downloadThread.start() # 启动线程
for item in downloadThreads:
item.join()
end = time.time()
print("图片下载完毕,所用时间:%s"%(end-start))
完工。
通过时长对比,原来要下载 700多s 的图片,被50s内下载完毕。 这个效率提高的不是一点半点啊~~~
绅士们,可以点赞了~