(爬图片简易版)
环境:python3 IDLE
可能出现的问题:
将远程数据下载到本地的方法urlretrieve()
函数定义必须在调用前面
数据类型不匹配——
Python正则表达式时出现TypeError: expected string or bytes-like object
python模仿浏览器访问网址——
http请求头中Referer的含义和作用
python爬虫中Response [200]返回值
requests异常requests.exceptions.ConnectionError
HTTPSConnectionPool
列表字典的操作——
深拷贝与浅拷贝
将字符串转为字典
测试正则表达式的网址:https://c.runoob.com/front-end/854/
文字转url格式:http://tools.jb51.net/static/encodetxt/urlencode_decode/index.html
一、流程思路

流程图
二、代码(测试unsplash与花瓣网)
示例网站一:https://unsplash.com/
该网站图片src可直接获取

但本次选用BeautifulSoup的方法从css选择器中找出src位置
- 设置url与函数体执行顺序
import requests
import os
import time
import copy
from urllib.request import urlretrieve
from bs4 import BeautifulSoup
def main():
# keyword是搜索框里的关键词
keyword = 'bread'
url = "https://unsplash.com/s/photos/"+keyword
# 连接到该url并获取网页源代码
data = getTextFromURL(url)
# 清洗数据
pic_list = dataClean(data)
# 新建文件夹的路径,savePictures为文件夹的名称
path = os.getenv("HOMEDRIVE") + os.getenv("HOMEPATH") + "\\Desktop" + "\\savePictures"
# 下载图片至文件夹
downloadPic(pic_list, path)
- 连接网站
def getTextFromURL(url):
# 模仿浏览器访问设置请求头
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36'
}
# 获取网页源代码
html_text = requests.get(url, headers=headers)
# 该网站的图片链接可直接通过css获取,所以选择使用BeautifulSoup库
soup = BeautifulSoup(html_text.text, 'lxml')
#print(html_text)
return soup
- 清洗数据(根据不同网站,清洗的方法也不同)
def dataClean(html_text):
# 通过css选择器来过滤数据
data = html_text.select('#app > div > div > div > div > div > div > div > div > figure > div > div > div > div > a')
# print(data)
result = []
# 获取所需字段
for item in data:
result_dict = {
'title':item.get('title'),
'src':item.find('img').get('src')
}
copy_result_dict = copy.deepcopy(result_dict)
result.append(copy_result_dict)
# print(result)
return(result)
- 新建文件夹
def mkdirFile(path):
# 判断该路径的文件夹是否存在
folder = os.path.exists(path)
# 如果不存在则新建
if not folder:
os.makedirs(path)
print("正在新建文件夹···")
print("成功新建savePictures文件夹!")
else:
print("已经存在该文件夹,可直接下载!")
- 下载文件
def downloadPic(pic_data_list, path):
mkdirFile(path)
print('正在开始下载···')
i = 0
for item in pic_data_list:
# 由于这个网站似乎没发现图片id,暂时用序号代替文件名字
filename = path+'\\'+ str(i+1)+'.jpg'
with open(filename,'w+') as file:
urlretrieve(item.get('src'), filename)
print(str(i+1)+ " 个图片保存完毕!")
i += 1
# 避免下载速度过快
time.sleep(2)
# 设置最大下载量(如果数量过多也许会遇到图片懒加载的问题)
if(i == 20):
print("结束下载!")
break
- 执行函数
try:
main()
except Exception as e:
print(e)
示例网站二:https://huaban.com/
通过f12分析js文件可知,该网址的图片链接格式大致为
图片链接格式图
import requests
import os
import time
import re
import json
import copy
from urllib.request import urlretrieve
from bs4 import BeautifulSoup
def main():
# 网站花瓣网爬图示例,搜索框的文字关键词需转为url格式
key = '%E6%88%BF%E5%AD%90'
url = "https://huaban.com/search/?q=" + key
# https://huaban.com/explore/bianzhifushi
# 连接到该url并获取网页源代码
data = getTextFromURL(url)
# 清洗所需数据得到最后需要的list
pic_list = dataClean(data)
# 假如将文件夹路径设置为桌面上的一个文件,则去获取桌面路径,文件夹名称为savePictures
path = os.getenv("HOMEDRIVE") + os.getenv("HOMEPATH") + "\\Desktop" + "\\savePictures"
#下载图片至文件夹
downloadPic(pic_list, path)
def getTextFromURL(url):
print("正在连接目标网址:"+ url)
# 关闭多余的连接、关闭ssl验证书验证
s = requests.session()
s.keep_alive = False
# 设置请求头
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36',
'Referer':'https://huaban.com/search/?q=%E5%83%8F%E7%B4%A0',
'Connection':'close'
}
# 从网页中获取网页源代码
html_text = requests.get(url,headers=headers,verify=False)
print('连接成功!')
# 不设置这个.text则返回<Response [200]>
html_text = html_text.text
print('获取网页源代码成功!')
return html_text
def dataClean(html_text):
# 发现该网站图片链接为拼接的格式
# 先清洗一次
data = re.findall('"file_id":\d*, "file":{.*?}',html_text)
# 再清洗一次,循环将字典放进列表
result = []
data_dict = {}
# re.findall要用字符串格式
data = str(data)
# 设置遍历长度,也可用re.findall('"file_id":".\d*"',data)查询长度'"key":".*?"'
data_length = len(re.findall('"key":".*?"',data))
for i in range(data_length):
# file_id的值均为数字,转为(json格式的)字符串(或者用re.sub(pattern,newString,string))
if re.findall('"file_id":(\d*)',data)[i].isdigit():
data_id = '{"file_id":"' + re.findall('"file_id":(\d*)',data)[i] + '"}'
data_key = "{" + re.findall('"key":".*?"',data)[i] + "}"
# 发现width的值有些结果为数字,有些结果为字符串
if re.findall('"width":"*(\d*)"*',data)[i].isdigit():
data_width = '{"width":"' + re.findall('"width":"*(\d*)"*',data)[i] + '"}'
# 设置字典里的键对值
data_dict['file_id'] = json.loads(data_id)['file_id']
data_dict['key'] = json.loads(data_key)['key']
data_dict['width'] = json.loads(data_width)['width']
# 发现对data_dict重新赋值时,有深拷贝与浅拷贝的问题
copy_data_dict = copy.deepcopy(data_dict)
result.append(copy_data_dict)
#print(result)
return result
def downloadPic(pic_list, path):
# 创建文件夹
mkdirFile(path)
#下载文件
i = 0
for item in pic_list:
#print(item)
filename = str(item['file_id']) + ".jpg"
#print("文件名字:"+filename)
with open(path+"\\"+filename,'w+') as file:
print('正在开始下载···')
src = 'https://hbimg.huabanimg.com/' + item['key'] + '_fw' + item['width'] + '/format/webp'
print(src)
urlretrieve(src, path+'\\'+filename)
print(str(i+1)+ " 个图片保存完毕!")
# 避免下载速度过快,设置time.sleep
time.sleep(2)
i += 1
# 设置图片下载的最大数量
if(i == 20):
print("结束下载!")
break
def mkdirFile(path):
# 判断该路径的文件夹是否存在
folder = os.path.exists(path)
# 如果不存在则新建
if not folder:
os.makedirs(path)
print("正在新建文件夹···")
print("完成新建savePictures2!")
else:
print("已经存在该文件夹,可直接下载!")
# 开始执行
try:
main()
except Exception as e:
print(e)
(ps:其他网站注意图片懒加载与分页等问题)