当我们需要在网站上大量下载某种图片类型的时候,使用手动点击图片进行保存的形式既费时又费力,选择用爬虫来获取海量图片会极大的方便我们获取图片数据这一过程。
一.选择有反爬虫机制的网站进行爬取
我们最常见的图片下载地址就是百度图片了,但是百度拥有反爬虫机制,网上很多爬虫程序在一页上只能爬取30张图片,而且百度页面没有分页,网址没有页数可以让我们改,还好代码里面留了翻页流的网址,所以,现在来分享给大家。
import re
import requests
from urllib import error
from bs4 import BeautifulSoup
import os
num = 0
numPicture = 0
file = ''
List = []
def Find(url):
global List
print('正在检测图片总数,请稍等.....')
t = 0
i = 1
s = 0
while t < 2000:
Url = url + str(t)
try:
Result = requests.get(Url, timeout=7)
except BaseException:
t = t + 60
continue
else:
result = Result.text
pic_url = re.findall('"objURL":"(.*?)",', result, re.S) # 先利用正则表达式找到图片url
s += len(pic_url)
if len(pic_url) == 0:
break
else:
List.append(pic_url)
t = t + 60
return s
def recommend(url):
Re = []
try:
html = requests.get(url)
except error.HTTPError as e:
return
else:
html.encoding = 'utf-8'
bsObj = BeautifulSoup(html.text, 'html.parser')
div = bsObj.find('div', id='topRS')
if div is not None:
listA = div.findAll('a')
for i in listA:
if i is not None:
Re.append(i.get_text())
return Re
def dowmloadPicture(html, keyword):
global num
# t =0
pic_url = re.findall('"objURL":"(.*?)",', html, re.S) # 先利用正则表达式找到图片url
print('找到关键词:' + keyword + '的图片,即将开始下载图片...')
for each in pic_url:
print('正在下载第' + str(num + 1) + '张图片,图片地址:' + str(each))
try:
if each is not None:
pic = requests.get(each, timeout=7)
else:
continue
except BaseException:
print('错误,当前图片无法下载')
continue
else:
string = file + r'\\' + keyword + '_' + str(num) + '.jpg'
fp = open(string, 'wb')
fp.write(pic.content)
fp.close()
num += 1
if num >= numPicture:
return
if __name__ == '__main__': # 主函数入口
word = input("请输入搜索关键词(可以是人名,地名等): ")
url = 'http://image.baidu.com/search/flip?tn=baiduimage&ie=utf-8&word=' + word + '&pn='#翻页流的网址
tot = Find(url)
Recommend = recommend(url) # 记录相关推荐
print('经过检测%s类图片共有%d张' % (word, tot))
numPicture = int(input('请输入想要下载的图片数量 '))
file = input('请建立一个存储图片的文件夹,输入文件夹名称即可')
y = os.path.exists(file)
if y == 1:
print('该文件已存在,请重新输入')
file = input('请建立一个存储图片的文件夹,输入文件夹名称即可')
os.mkdir(file)
else:
os.mkdir(file)
t = 0
tmp = url
while t < numPicture:
try:
url = tmp + str(t)
result = requests.get(url, timeout=10)
print(url)
except error.HTTPError as e:
print('网络错误,请调整网络后重试')
t = t + 60
else:
dowmloadPicture(result.text, word)
t = t + 60
print('当前搜索结束,感谢使用')
print('猜你喜欢')
for re in Recommend:
print(re, end=' ')
整个运行台的显示如下(关键词,下载数量,存储文件夹由我们自己在运行台中输入设置):
选择批量爬取关键词为“王凯”的图片,选取了其中的两张来展示。
二.选择无反爬虫机制的网站进行爬取
除了百度图片以外,还可以从其它的网站上进行图片爬取,比如:美桌,该网站并没有robots协议,因此可以任意爬取。
我们可以对爬取的内容进行任意更改,比如说从美桌上爬取名为“靳东”的图片。爬取过程中用到的第三方库主要是requests和pypinyin(将汉字转换成拼音),代码如下
import requests
import re
import os
from pypinyin import lazy_pinyin
class starImage():
def __init__(self):
# self.name = input("请输入你喜欢的明星的名字:") # 放开这个地方可以下载网站内其他明星剧照
self.name = '靳东'
self.nameUrl = "http://www.win4000.com/mt/" + ''.join(lazy_pinyin(self.name)) + ".html"
self.path = r'./明星'+'/'+self.name
def getHTMLText(self,url):
headers = {
'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/73.0.3683.103 Safari/537.36',
'referer': 'http://www.win4000.com/mt/star.html'
}
re = requests.get(url, headers=headers, timeout=10) # 设置超时时间
if re.status_code == 200:
re.encoding = re.apparent_encoding # 以网站编码为准
return re.text
# 获取详情页网址
def getPageUrls(self,Text):
re_pageUrl = re.findall('<a target="_blank" href="(.*?)">',Text)
# print(re_pageUrl)
return re_pageUrl
# 下载图片
def downloadPic(self,pageUrls):
for i in range(len(pageUrls)):
pageHtmlTxet=self.getHTMLText(pageUrls[i])
photoName = re.findall('<div class="ptitle"><h1>(.*?)</h1>', pageHtmlTxet)[0] # 图集名
photoList = re.findall('data-original="(.*?)" alt="%s"'%photoName,pageHtmlTxet) # 图片URL
for index, jpg in enumerate(photoList):
jpg = jpg.replace('_130_170','')
path = self.path+'//'+photoName+'//' # 创建存放路径
if not os.path.exists(path):
os.makedirs(path) # 递归创建文件夹
img = requests.get(jpg)
with open(path + '%s.jpg' % (index), 'wb') as f:
f.write(img.content)
print('下载 %s的%d图片成功' % (photoName, index))
# 逻辑业务
def fun(self):
try:
Text = self.getHTMLText(self.nameUrl) # 第一页
self.downloadPic(self.getPageUrls(Text)) # 下载第一分页所有图片
nextPage = re.findall(r'next" href="(.+)"', Text)[0] # 第二页
self.downloadPic(self.getPageUrls(self.getHTMLText(nextPage))) # 下载第二分页所有图片
try:
while (nextPage):
nextText = self.getHTMLText(nextPage) # 其他分页
nextPage = re.findall(r'next" href="(.+)"', nextText)[0]
self.downloadPic(self.getPageUrls(self.getHTMLText(nextPage))) # 下载第三页至结束的所有图片
except IndexError:
print("已全部下载完毕")
except TypeError:
print("不好意思,没有{}的照片".format(self.name))
if __name__=='__main__':
a = starImage()
a.fun()
附上三张图片
还是蛮帅气的,哈哈