"""
Shutterstock 图片下载器
从 stock_image_detail_wj 表读取 state=1 的下载URL，下载图片到服务器本地目录
下载成功后 state 从2改为3
运行顺序：xnj_url.py（获取URL） → 第2步（下载） → upload_pic.py（上传）
注意：下载URL有时效性，xnj_url.py 跑完后需尽快运行本脚本
"""
from all_connect import ConnectSpider
Con = ConnectSpider()
import os
os.environ['NO_PROXY'] = 'stackoverflow.com'
import logging
logging.captureWarnings(True)
import json
import requests
import re
import time
from datetime import datetime

class Download():
    def __init__(self):
        self.account = ''
        self.pwd = ''
        self.headers = {
    'accept': 'application/json',
    'accept-language': 'zh-CN,zh;q=0.9',
    'content-type': 'application/json',
    'newrelic': 'eyJ2IjpbMCwxXSwiZCI6eyJ0eSI6IkJyb3dzZXIiLCJhYyI6Ijk2NzIzMiIsImFwIjoiMTU4ODYzMjc5MiIsImlkIjoiMDdjNDZhYTI3ZTBlMTAyZiIsInRyIjoiOGI4ODQ3MzNiNjFjNDNlY2YxMGEzOTQ2MzQ4MDE2NzQiLCJ0aSI6MTczNTk5NzEzNjEyOH19',
    'origin': 'https://www.shutterstock.com',
    'priority': 'u=1, i',
    'referer': 'https://www.shutterstock.com/zh/catalog/',
    'sec-ch-ua': '"Not)A;Brand";v="99", "Google Chrome";v="127", "Chromium";v="127"',
    'sec-ch-ua-mobile': '?0',
    'sec-ch-ua-platform': '"Windows"',
    'sec-fetch-dest': 'empty',
    'sec-fetch-mode': 'cors',
    'sec-fetch-site': 'same-origin',
    'traceparent': '00-8b884733b61c43ecf10a394634801674-07c46aa27e0e102f-01',
    'tracestate': '967232@nr=0-1-967232-1588632792-07c46aa27e0e102f----1735997136128',
    'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/127.0.0.0 Safari/537.36',
    'x-end-app-name': 'next-web',
    'x-end-app-version': '5ca4a4c05d8',
    'x-newrelic-id': 'XQAAU1VRGwIEVVhaBgYGUlI=',
    'x-request-id': '15754a73-f152-4983-99b4-6af058379880',
}


    def download_image(self, file_path, res):
        with open(file_path, "wb") as f:
            f.write(res.content)

    def analyze_pic(self, account_id, image_id, image_url, image_title):
            try:
                start_time = datetime.now().strftime("%m-%d %H:%M:%S")
                if '@' in account_id:
                    file_name = account_id.split('@')[0]
                else:
                    file_name = account_id
                save_folder = f'/home/wangjing/picture_material/stock_summery/all_pic/{file_name}'
                pic_name = f'{str(image_id)}+{image_title}'.replace(':', '_').replace('\t', '').replace('\r', '').replace('|', '').replace('/', '').replace('"', "'").replace(' ', '_').replace(',', '_').replace('.','_').replace('\n', '_')

                if any('\u4e00' <= char <= '\u9fff' for char in pic_name):
                    # 如果包含中文，截取前80个字符
                    pic_name = pic_name[:50] + '.jpg'
                else:
                    # 不包含中文时，按照原策略处理，但总长不超过160字符
                    pic_name = re.sub(r'[\\/*?:"<>|]', '_', pic_name)[:160] + '.jpg'
                print('image_url:',image_url)
                res = requests.get(image_url, timeout=600)
                content_type = res.headers.get("Content-Type", "")
                print('content_type: 查看返回的类型：',content_type)

                if res.status_code != 200 or not content_type.startswith("image/"):
                    print(f'下载失败 image_id:{image_id} status:{res.status_code} content_type:{content_type}')
                    return

                # 构建完整的文件路径
                os.makedirs(save_folder, exist_ok=True)
                file_path = os.path.join(save_folder, pic_name)
                self.download_image(file_path, res)
                Con.update_url_state_to_3(image_id)
                now_time = datetime.now().strftime("%m-%d %H:%M:%S")
                print(f'pic_name:{pic_name[:38]},time:{start_time}——{now_time}下载成功')

            except Exception as e:
                print(e)

    def process_item_id(self, item_id):
        has_new_data = False  # 用于标记当前item_id是否有新数据被处理
        print(f"开始处理item_id: {item_id}")

        retry_count = 0  # 初始化重试计数器
        max_retries = 3  # 最大重试次数

        while True:  # 在每次处理一个item_id时，使用while True来确保可以重复检查新增的任务
            try:
                account_list = Con.get_cookie_account(item_id,state=1)
                if not account_list:  # 如果没有获取到账号信息，则跳过
                    account_list = Con.get_cookie_account(item_id, state=3)
                    if not account_list:
                        break

                account = account_list[0]
                pic_data_list = Con.get_pic_urls(account)

                if pic_data_list:
                    has_new_data = True  # 标记有新数据被处理
                    print(f'{account}有{len(pic_data_list)}个需要下载')
                    for pic_data in pic_data_list:
                        image_url, image_id, image_title = pic_data.split("||", 2)
                        try:
                            self.analyze_pic(account, image_id, image_url, image_title)
                        except Exception as e:
                            if 'Expected axis has 0 elements, new values have 2 elements' in str(e):
                                print(f'{account}已全部下载完成')
                            else:
                                print(f"处理图片时出错: {e}")
                else:
                    print(f"{account} 没有新的图片需要下载")
                    break  # 如果没有新的图片需要下载，退出当前item_id的处理循环

                # 再次检查是否有新增的任务需要处理
                new_pic_data_list = Con.get_pic_urls(account)
                if new_pic_data_list == pic_data_list or not new_pic_data_list:
                    break  # 如果没有新增任务或与之前相同，则退出循环

                pic_data_list = new_pic_data_list  # 更新pic_data_list为最新的列表，准备下一轮处理

            except Exception as e:
                if 'server closed the connection unexpectedly' in str(e) and retry_count < max_retries:
                    retry_count += 1
                    print(f"连接中断，正在第{retry_count}次重试...")
                    time.sleep(5)  # 等待5秒后重试
                    continue
                else:
                    print(f"处理item_id: {item_id}时发生错误: {e}")
                    break

        # 完成一个item_id的所有任务后，打印通知
        print(f"item_id: {item_id} 的所有任务已完成")
        return has_new_data  # 返回是否有新数据被处理

    def run(self):
        while True:
            all_completed = True  # 标记是否所有item_id都已完成处理
            for item_id in range(1, 40):  # 循环遍历所有item_id
                if self.process_item_id(item_id):
                    all_completed = False  # 如果任何一个item_id有任务处理，则标记为未全部完成

            if all_completed:
                print('目前没有需要下载的，等待半小时')
                time.sleep(1800)  # 等待30分钟后再次检查

if __name__ == '__main__':
    Download().run()










