我正在研究Python 4/5个月,这是我从头开始构建的第三个项目,但我无法自行解决此问题。

该脚本为给定的每个URL下载1张图片。
我无法在此脚本中找到有关如何实现线程池执行程序或异步的解决方案。我不知道如何将带有图像编号的URL链接到保存图像部分。
我为需要下载的所有网址构建了一个字典,但是我如何实际以正确的名称保存图像?
还有其他建议吗?

PS。目前提供的网址只是假的。

同步版本:


    汇入要求
    导入argparse
    汇入
    导入操作系统
    导入日志

    从bs4导入BeautifulSoup


    解析器= argparse.ArgumentParser()
    parser.add_argument(“-n”,“ --num”,help =“书号”,类型=整数,必填=真)
    parser.add_argument(“-p”,dest = r“ path_name”,默认= r“ F:\ Users \ 123”,help =“保存到目录”,)
    args = parser.parse_args()



    logging.basicConfig(format ='%(asctime)s-%(name)s-%(levelname)s-%(message)s',
                        level = logging.ERROR)
    logger = logging.getLogger(__ name__)


    def get_parser(url_c):
        url = f'https://test.net/g/ {url_c} / 1'
        logger.info(f'主网址:{url_c}')
        responce = requests.get(url,timeout = 5)#超时将引发异常
        如果responce.status_code == 200:
            页面= requests.get(URL,timeout = 5).content
            汤= BeautifulSoup(页面,'html.parser')
            回汤
        其他:
            responce.raise_for_status()


    def get_locators(soup):#取get_parser
        #提取首页/末页编号
        first = int(soup.select_one('span.current')。string)
        logger.info(f'第一页:{第一}')
        last = int(soup.select_one('span.num-pages')。string)+ 1

        #提取img_code和扩展名
        链接= soup.find('img',{'class':'fit-horizo​​ntal'})。attrs [“ src”]
        logger.info(f'定位符代码:{link}')
        代码= re.search('画廊。([0-9] +)\ /。\。(\ w {3})',链接)
        book_code = code.group(1)#内部代码
        扩展名= code.group(2)#png或jpg

        #提取目录名称
        模式= re.compile('pretty“:”(。*)“')
        找到= soup.find('script',text = pattern)
        字符串= pattern.search(found.text).group(1)
        dir_name = string.split('“')[0]
        logger.info(f'Dir名称:{dir_name}')

        logger.info(f'隐藏代码:{book_code}')
        print(f'Extension:{extension}')
        打印(f“总页数:{last}”)
        打印(f'')

        返回{'first_p':首先,
                'last_p':最后,
                'book_code':book_code,
                'ext':扩展名,
                'dir':dir_name
                }


    def setup_download_dir(path,dir):#(args.path_name,locator ['dir'])
        #创建文件夹(如果不存在)
        filepath = os.path.join(f'{path} \ {dir}')
        如果不是os.path.exists(filepath):
            尝试:
                os.makedirs(文件路径)
                print(f'目录创建于{filepath}')
            除了OSError作为err:
                print(f“无法创建{filepath}:{err}”)
         返回文件路径


    def main(定位符,文件路径):
        对于范围内的image_n(locator ['first_p'],locator ['last_p']):
            url = f“https://i.test.net/galleries/{locator['book_code']}//{image_n}。{locator['ext']}”“
            logger.info(f'Url Img:{url}')
            响应= request.get(URL,超时= 3)
            如果responce.status_code == 200:
                img_data = requests.get(URL,timeout = 3).content
            其他:
                responce.raise_for_status()#提高执行力

            使用open((os.path.join(filepath,f“ {image_n}。{locator ['ext']}”))),'wb')作为处理程序:
                handler.write(img_data)#写图片
                打印(f'Img {image_n}-完成')


    如果__name__ =='__main__':
        尝试:
            locator = get_locators(get_parser(args.num))#args.num例如。 241461
            main(定位符,setup_download_dir(args.path_name,locator ['dir']))
        除了KeyboardInterrupt:
            打印(f'程序中止...'+'\ n')



网址清单:


    def img_links(定位符):
        image_url = []
        对于范围内的num(locator ['first_p'],locator ['last_p']):
            url = f“https://i.test.net/galleries/{locator['book_code']}/{num}。{locator['ext']}”“
            image_url.append(url)
        logger.info(f'网址列表:{image_url}')
        返回image_url

最佳答案

我在流利的python书中找到了解决方案。以下是代码段:

    def download_many(cc_list,base_url,verbose,concur_req):
        计数器= collections.Counter()
        使用futures.ThreadPoolExecutor(max_workers = concur_req)作为执行者:
            to_do_map = {}
            对于已排序(cc_list)中的cc:
                未来= executor.submit(download_one,cc,base_url,详细)
                to_do_map [future] = cc
            done_iter = futures.as_completed(to_do_map)
            如果不冗长:
                done_iter = tqdm.tqdm(done_iter,total = len(cc_list))
            为了将来在done_iter中:
                尝试:
                    res = future.result()
                除了request.exceptions.HTTPError除外:
                    error_msg ='HTTP {res.status_code}-{res.reason}'
                    error_msg = error_msg.format(res = exc.response)
                除了request.exceptions.ConnectionError除外:
                    error_msg ='连接错误'
                其他:
                    error_msg =''
                    状态= res.status
                如果error_msg:
                    状态= HTTPStatus.error
                计数器[状态] + = 1
                如果冗长和error_msg:
                    cc = to_do_map [未来]
                    print('*** {}的错误:{}'。format(cc,error_msg))
        退货柜台

关于python - python异步图像下载(多个URL),我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/52430038/

10-09 13:39