python:爬图并下载到本地指定文件夹

(爬图片简易版)
环境:python3 IDLE

参考网站:
《Python爬虫入门教程》《Python3网络爬虫快速入门实战解析》

可能出现的问题:
将远程数据下载到本地的方法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位置
  1. 设置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)
  1. 连接网站
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
  1. 清洗数据(根据不同网站,清洗的方法也不同)
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)
  1. 新建文件夹
def mkdirFile(path):
    # 判断该路径的文件夹是否存在
    folder = os.path.exists(path)
    # 如果不存在则新建
    if not folder:
        os.makedirs(path)
        print("正在新建文件夹···")
        print("成功新建savePictures文件夹!")
    else:
        print("已经存在该文件夹,可直接下载!")
  1. 下载文件
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
  1. 执行函数
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:其他网站注意图片懒加载与分页等问题)

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

友情链接更多精彩内容