美文网首页
python:爬图并下载到本地指定文件夹

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

作者: 靗鲭 | 来源:发表于2022-01-07 12:46 被阅读0次

    (爬图片简易版)
    环境: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:其他网站注意图片懒加载与分页等问题)

    相关文章

      网友评论

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

          本文链接:https://www.haomeiwen.com/subject/bmaqcrtx.html