python二进制截图,图片存到本地

本文介绍了一个Python函数,用于实现网页截图,并将截图保存为本地二进制文件格式。该方法适用于需要批量处理截图的自动化任务。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

python二进制截图,图片存到本地

项目中截取的函数片段,仅供参考

    def send_img_data(self):
        Message.info('作废截图上传')
        try:
            for index, item in enumerate(self.screen_shot_list):
                if index == 0:
                    self.client.upload_cancel_img_to_backend(
                        self.declare_id,
                        self.client_info.get('customerid'),
                        item['tax_num'],
                        item['filename'],
                        item['file'],
                        is_first=1  # 如果图片is_first都是1,图片会被覆盖只剩1张
                    )
                else:
                    self.client.upload_cancel_img_to_backend(
                        self.declare_id,
                        self.client_info.get('customerid'),
                        item['tax_num'],
                        item['filename'],
                        item['file'],
                        is_first=0
                    )
        except Exception as e:
            Message.error(str(e) + '发生图片信息发生异常,对任务结果不影响,当前异常原因:{}'.format(traceback.format_exc()))

    def save_screen_shot_img(self, filename="error",  tax_num='', message='', is_first=0):
        """
        截图保存,产品要求,图片做一定处理,打水印
        :param is_first: 上传平台,如果有多张图片,多张图片时,都可以设为0,如果是1,表示图片放在第一位,不能同时设为1,会被覆盖
        :param message: 水印信息:申报作废
        :param tax_num: 税种类型:60,605
        :param filename: 图片名称
        :return:
        """
        try:
            binary_content = self.screenshot_png_bytes_client()
            # binary_content = self.driver.get_screenshot_as_png()
            file_binary_content = self.add_text_for_image_new(binary_content, message)
            self.save_bytes_img_to_file(file_binary_content, filename)
            time_name = time.strftime('%H:%M:%S', time.localtime())
            if tax_num in ['50', '51', '52', '500']:
                self.screen_shot_list.append({
                    'filename': time_name + filename + '.png',
                    'file': file_binary_content,
                    'tax_num': '500',
                    'is_first': is_first
                })
            else:
                self.screen_shot_list.append({
                    'filename': time_name + filename + '.png',
                    'file': file_binary_content,
                    'tax_num': tax_num,
                    'is_first': is_first
                })
            Message.info(f"截图成功:税号:{tax_num}====> 文件名{filename}")
        except Exception as e:
            Message.error(str(e) + '截图发生异常,但不影响程序申报、核查结果,当前异常原因:{}'.format(traceback.format_exc()))

    def save_bytes_img_to_file(self, binary_content, filename):
        """
        保存二进制图片数据为图片,存到本地
        :return:
        """
        content = binary_content
        byte_stream = io.BytesIO(content)  # 请求数据转化字节流
        roiImg = Image.open(byte_stream)  # Image打开二进制流Byte字节流数据
        imgByteArr = io.BytesIO()  # 创建一个空的Bytes对象
        roiImg.save(imgByteArr, format='PNG')  # PNG就是图片格式
        imgByteArr = imgByteArr.getvalue()  # 保存的二进制流
        # 生成文件目录
        file_path = os.path.join(os.getcwd(), 'images')
        if not os.path.exists(file_path):
            os.makedirs(file_path)
        filename = f"{filename}.png"
        # 创建图片
        with open(f"images/{filename}", "wb+") as f:
            f.write(imgByteArr)

    @retry(stop_max_attempt_number=3, retry_on_exception=is_stop_exception)
    def screenshot_png_bytes_client(self):
        """截取图片并转换为二进制流-客户端用"""
        # return self.driver.get_screenshot_as_png()
        im = ImageGrab.grab()
        img_byte = io.BytesIO()
        im.save(img_byte, 'PNG')
        binary_content = img_byte.getvalue()
        return binary_content

class CrawlerException(Exception):
    """
    基础异常类
    """

    def __init__(self, msg=None, task_state=TaskCode.UnknownError, value=None, node_msg=None):
        """
        :param msg:错误信息,传值会覆盖异常枚举类中的提示信息,不传值使用异常枚举类中的提示信息与value进行拼接合成提示信息
        :param task_state:异常枚举类
        :param value:==>tuple()
        :param node_msg:异常节点信息
        """
        self.error_info = msg
        # 异常枚举类
        self.task_state = task_state
        # 报错信息
        self.set_error_info(value)
        # 错误码
        self.task_code = task_state.task_code
        # 是否建单
        self.need_redmine = self.get_redmine_config()
        # 发生异常的节点
        self.node_msg = node_msg

    def __str__(self):
        return str(self.error_info)

    def set_error_info(self, value):
        if not self.error_info:
            if value:
                try:
                    self.error_info = self.task_state.prompt.replace('%s', '{}').format(*value)
                except:
                    Message.error('参数数量错误,报错枚举类:{}'.format(self.task_state))
                    self.error_info = self.task_state.prompt.replace('%s', '')
            else:
                if self.task_state == TaskCode.UnknownError:
                    # 临时处理
                    self.error_info = UNDEFINED_ERROR_TIPS
                    exec_str = format_exc()
                    # 将网络异常从未知异常中排除出来,并修改为网络异常
                    for sub in NETWORK_EXCEPTIONS:
                        if exec_str.count(sub):
                            self.error_info = NETWORK_ERROR_TIPS
                            break
                else:
                    self.error_info = self.task_state.prompt.replace('%s', '')

    def get_redmine_config(self):
        # 成功场景不建单,特殊场景不建单
        try:
            # SDK异常枚举类提供建单配置字段后:
            return self.task_state.need_redmine
        except:
            Message.info('SDK异常枚举类暂未提供建单配置字段')
            # 临时方法,SDK异常枚举类暂未提供建单配置字段
            return self.task_code.startswith('0302') and self.task_state not in no_redmine_list

    def get_error_info(self):
        if self.error_info in [NETWORK_ERROR_TIPS, UNDEFINED_ERROR_TIPS]:
            self.error_info += f'**{self.node_msg}**'
        return self.error_info

    def get_status_code(self):
        return self.task_code

    def set_node_msg(self, node_msg):
        if self.node_msg is None and node_msg:
            self.node_msg = node_msg


def is_stop_exception(exception):
    """
    判断异常是否需要重试
    @param exception:  异常类
    @return:
    """
    Message.info(f"判断异常是否需要重试-is_stop_exception----{exception}")
    if isinstance(exception, CrawlerRetryException):
        # 指定重试异常
        return True
    elif isinstance(exception, CrawlerException):
        # 可控异常,根据需要是否选择,如果需要重试抛CrawlerRetryException
        if exception.get_status_code() == '030209':
            # 避免装饰器之后,变成 TaskCode.UnknownError的情况,无法重试
            return True
        else:
            return False
    else:
        # 非可控异常,都重试
        return True

class CrawlerRetryException(CrawlerException):
    """
    重试异常,与retrying模块的retry装饰器
    """
    description = "CrawlerRetryError"

    def __init__(self, msg, task_state=None):
        super().__init__()
        self.error_info = msg
        self.task_state = task_state or TaskCode.UnknownError
        # self.task_state = TaskCode.UnknownError
        self.task_code = self.task_state.task_code
        self.need_redmine = False

    def __str__(self):
        return str(self.error_info)
``
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值