no message

parent dfdb4f08
# uk de 的站点 没测过
site_name_secret_dict = {
"us": {'application':'amzn-mbl-cscan-us','username':'amzn-mbl-cscan-us','secret':'5b6874d3a20417591bd5464a25a37bc6','snap_url':'https://match-visualsearch.amazon.com'},
"uk": {'application':'amzn-mbl-cscan-uk','username':'amzn-mbl-cscan-uk','secret':'c1a79f745bbe6a8824ce3178c8b549ad','snap_url':'https://match-visualsearch-uk.amazon.com'},
"de": {'application':'amzn-mbl-cscan-de','username':'amzn-mbl-cscan-de','secret':'9e6d6d6c2c823012c493885a95cc5bf2','snap_url':'https://match-visualsearch-de.amazon.com'},
}
us_devices_list = [
{"clientDevice":"iOS - iPhone 16 Pro","deviceManufacturer":"Apple","clientDeviceVersion":"18"},
{"clientDevice":"iOS - iPhone 16","deviceManufacturer":"Apple","clientDeviceVersion":"18"},
{"clientDevice":"iOS - iPhone 15 Pro Max","deviceManufacturer":"Apple","clientDeviceVersion":"17"},
{"clientDevice":"iOS - iPhone 15 Plus","deviceManufacturer":"Apple","clientDeviceVersion":"17"},
{"clientDevice":"iOS - iPhone 14 Pro","deviceManufacturer":"Apple","clientDeviceVersion":"16"},
{"clientDevice":"iOS - iPhone 14","deviceManufacturer":"Apple","clientDeviceVersion":"16"},
{"clientDevice":"iOS - iPhone 13 Pro","deviceManufacturer":"Apple","clientDeviceVersion":"15"},
{"clientDevice":"iOS - iPhone 13","deviceManufacturer":"Apple","clientDeviceVersion":"15"},
{"clientDevice":"iOS - iPhone 12 Pro Max","deviceManufacturer":"Apple","clientDeviceVersion":"14"},
{"clientDevice":"iOS - iPhone 12","deviceManufacturer":"Apple","clientDeviceVersion":"14"},
{"clientDevice":"iOS - iPhone SE (2022)","deviceManufacturer":"Apple","clientDeviceVersion":"15"},
{"clientDevice":"iOS - iPhone SE 3rd Gen","deviceManufacturer":"Apple","clientDeviceVersion":"16"},
{"clientDevice":"Android - Pixel 9 Pro","deviceManufacturer":"Google","clientDeviceVersion":"14"},
{"clientDevice":"Android - Pixel 9","deviceManufacturer":"Google","clientDeviceVersion":"14"},
{"clientDevice":"Android - Pixel 8 Pro","deviceManufacturer":"Google","clientDeviceVersion":"14"},
{"clientDevice":"Android - Pixel 8","deviceManufacturer":"Google","clientDeviceVersion":"14"},
{"clientDevice":"Android - Pixel 7 Pro","deviceManufacturer":"Google","clientDeviceVersion":"13"},
{"clientDevice":"Android - Pixel 7a","deviceManufacturer":"Google","clientDeviceVersion":"13"},
{"clientDevice":"Android - Pixel 6 Pro","deviceManufacturer":"Google","clientDeviceVersion":"12"},
{"clientDevice":"Android - Pixel 6a","deviceManufacturer":"Google","clientDeviceVersion":"12"},
{"clientDevice":"Android - Pixel 5a","deviceManufacturer":"Google","clientDeviceVersion":"11"},
{"clientDevice":"Android - Pixel 5","deviceManufacturer":"Google","clientDeviceVersion":"11"},
{"clientDevice":"Android - Galaxy S25 Ultra","deviceManufacturer":"Samsung","clientDeviceVersion":"14"},
{"clientDevice":"Android - Galaxy S25","deviceManufacturer":"Samsung","clientDeviceVersion":"14"},
{"clientDevice":"Android - Galaxy S24 Ultra","deviceManufacturer":"Samsung","clientDeviceVersion":"14"},
{"clientDevice":"Android - Galaxy S24","deviceManufacturer":"Samsung","clientDeviceVersion":"14"},
{"clientDevice":"Android - Galaxy S23 Ultra","deviceManufacturer":"Samsung","clientDeviceVersion":"13"},
{"clientDevice":"Android - Galaxy S23","deviceManufacturer":"Samsung","clientDeviceVersion":"13"},
{"clientDevice":"Android - Galaxy A55","deviceManufacturer":"Samsung","clientDeviceVersion":"13"},
{"clientDevice":"Android - Galaxy A54","deviceManufacturer":"Samsung","clientDeviceVersion":"13"},
{"clientDevice":"Android - Galaxy Z Fold5","deviceManufacturer":"Samsung","clientDeviceVersion":"13"},
{"clientDevice":"Android - Galaxy Z Flip5","deviceManufacturer":"Samsung","clientDeviceVersion":"13"},
{"clientDevice":"Android - Galaxy A34","deviceManufacturer":"Samsung","clientDeviceVersion":"13"},
{"clientDevice":"Android - Galaxy A14","deviceManufacturer":"Samsung","clientDeviceVersion":"13"},
{"clientDevice":"Android - Galaxy S22 Ultra","deviceManufacturer":"Samsung","clientDeviceVersion":"12"},
{"clientDevice":"Android - Galaxy A53","deviceManufacturer":"Samsung","clientDeviceVersion":"12"},
{"clientDevice":"Android - Galaxy S21 Ultra","deviceManufacturer":"Samsung","clientDeviceVersion":"11"},
{"clientDevice":"Android - Galaxy A71","deviceManufacturer":"Samsung","clientDeviceVersion":"11"},
{"clientDevice":"Android - Moto Edge 60","deviceManufacturer":"Motorola","clientDeviceVersion":"14"},
{"clientDevice":"Android - Moto Edge 50 Pro","deviceManufacturer":"Motorola","clientDeviceVersion":"14"},
{"clientDevice":"Android - Moto G Power (2024)","deviceManufacturer":"Motorola","clientDeviceVersion":"13"},
{"clientDevice":"Android - Moto G Stylus 5G (2023)","deviceManufacturer":"Motorola","clientDeviceVersion":"13"},
{"clientDevice":"Android - Moto Razr 40 Ultra","deviceManufacturer":"Motorola","clientDeviceVersion":"13"},
{"clientDevice":"Android - Moto Edge 30 Fusion","deviceManufacturer":"Motorola","clientDeviceVersion":"12"},
{"clientDevice":"Android - Moto G Pure (2023)","deviceManufacturer":"Motorola","clientDeviceVersion":"12"},
{"clientDevice":"Android - Moto One 5G Ace","deviceManufacturer":"Motorola","clientDeviceVersion":"11"},
{"clientDevice":"Android - OnePlus 12","deviceManufacturer":"OnePlus","clientDeviceVersion":"14"},
{"clientDevice":"Android - OnePlus 11","deviceManufacturer":"OnePlus","clientDeviceVersion":"13"},
{"clientDevice":"Android - OnePlus 10 Pro","deviceManufacturer":"OnePlus","clientDeviceVersion":"12"},
{"clientDevice":"Android - OnePlus 9 Pro","deviceManufacturer":"OnePlus","clientDeviceVersion":"11"},
{"clientDevice":"Android - OnePlus Nord N30","deviceManufacturer":"OnePlus","clientDeviceVersion":"13"},
{"clientDevice":"Android - OnePlus Nord 3","deviceManufacturer":"OnePlus","clientDeviceVersion":"13"},
{"clientDevice":"Android - OnePlus Ace 2","deviceManufacturer":"OnePlus","clientDeviceVersion":"13"},
{"clientDevice":"Android - OnePlus Nord CE 3","deviceManufacturer":"OnePlus","clientDeviceVersion":"13"},
{"clientDevice":"Android - Xiaomi 14 Ultra","deviceManufacturer":"Xiaomi","clientDeviceVersion":"14"},
{"clientDevice":"Android - Xiaomi 14","deviceManufacturer":"Xiaomi","clientDeviceVersion":"14"},
{"clientDevice":"Android - Xiaomi 13 Pro","deviceManufacturer":"Xiaomi","clientDeviceVersion":"13"},
{"clientDevice":"Android - Redmi Note 13 Pro","deviceManufacturer":"Xiaomi","clientDeviceVersion":"13"},
{"clientDevice":"Android - Redmi Note 12 Pro","deviceManufacturer":"Xiaomi","clientDeviceVersion":"13"},
{"clientDevice":"Android - Redmi K70","deviceManufacturer":"Xiaomi","clientDeviceVersion":"14"},
{"clientDevice":"Android - Redmi K60","deviceManufacturer":"Xiaomi","clientDeviceVersion":"13"},
{"clientDevice":"Android - Asus ROG Phone 8","deviceManufacturer":"Asus","clientDeviceVersion":"14"},
{"clientDevice":"Android - Asus Zenfone 11","deviceManufacturer":"Asus","clientDeviceVersion":"14"},
{"clientDevice":"Android - Asus ROG Phone 7","deviceManufacturer":"Asus","clientDeviceVersion":"13"},
{"clientDevice":"Android - Asus Zenfone 10","deviceManufacturer":"Asus","clientDeviceVersion":"13"},
{"clientDevice":"Android - TCL 40 SE","deviceManufacturer":"TCL","clientDeviceVersion":"13"},
{"clientDevice":"Android - TCL Stylus 5G","deviceManufacturer":"TCL","clientDeviceVersion":"13"},
{"clientDevice":"Android - TCL 30 V 5G","deviceManufacturer":"TCL","clientDeviceVersion":"12"},
{"clientDevice":"Android - Nokia X30 5G","deviceManufacturer":"Nokia","clientDeviceVersion":"13"},
{"clientDevice":"Android - Nokia G42 5G","deviceManufacturer":"Nokia","clientDeviceVersion":"13"},
{"clientDevice":"Android - Nokia G22","deviceManufacturer":"Nokia","clientDeviceVersion":"12"},
{"clientDevice":"Android - Vivo X100 Pro","deviceManufacturer":"Vivo","clientDeviceVersion":"14"},
{"clientDevice":"Android - Vivo X100","deviceManufacturer":"Vivo","clientDeviceVersion":"14"},
{"clientDevice":"Android - Vivo V30 Pro","deviceManufacturer":"Vivo","clientDeviceVersion":"13"},
{"clientDevice":"Android - Oppo Find X7 Ultra","deviceManufacturer":"Oppo","clientDeviceVersion":"14"},
{"clientDevice":"Android - Oppo Find X6 Pro","deviceManufacturer":"Oppo","clientDeviceVersion":"13"},
{"clientDevice":"Android - Oppo Reno 11 Pro","deviceManufacturer":"Oppo","clientDeviceVersion":"13"},
{"clientDevice":"Android - Realme GT5 Pro","deviceManufacturer":"Realme","clientDeviceVersion":"14"},
{"clientDevice":"Android - Realme 11 Pro+","deviceManufacturer":"Realme","clientDeviceVersion":"13"},
{"clientDevice":"Android - Realme 10 Pro+","deviceManufacturer":"Realme","clientDeviceVersion":"12"},
{"clientDevice":"iOS - iPhone 16 Plus","deviceManufacturer":"Apple","clientDeviceVersion":"18"},
{"clientDevice":"iOS - iPhone 15 Pro","deviceManufacturer":"Apple","clientDeviceVersion":"17"},
{"clientDevice":"iOS - iPhone 15","deviceManufacturer":"Apple","clientDeviceVersion":"17"},
{"clientDevice":"iOS - iPhone 14 Plus","deviceManufacturer":"Apple","clientDeviceVersion":"16"},
{"clientDevice":"iOS - iPhone 14 Pro Max","deviceManufacturer":"Apple","clientDeviceVersion":"16"},
{"clientDevice":"iOS - iPhone 13 Mini","deviceManufacturer":"Apple","clientDeviceVersion":"15"},
{"clientDevice":"iOS - iPhone 13 Pro Max","deviceManufacturer":"Apple","clientDeviceVersion":"15"},
{"clientDevice":"iOS - iPhone 12 Mini","deviceManufacturer":"Apple","clientDeviceVersion":"14"},
{"clientDevice":"iOS - iPhone 12 Pro","deviceManufacturer":"Apple","clientDeviceVersion":"14"},
{"clientDevice":"Android - Pixel Fold","deviceManufacturer":"Google","clientDeviceVersion":"14"},
{"clientDevice":"Android - Pixel 8a","deviceManufacturer":"Google","clientDeviceVersion":"14"},
{"clientDevice":"Android - Pixel 7","deviceManufacturer":"Google","clientDeviceVersion":"13"},
{"clientDevice":"Android - Pixel 6","deviceManufacturer":"Google","clientDeviceVersion":"12"},
{"clientDevice":"Android - Pixel 4a (5G)","deviceManufacturer":"Google","clientDeviceVersion":"11"},
{"clientDevice":"Android - Galaxy S25 Plus","deviceManufacturer":"Samsung","clientDeviceVersion":"14"},
{"clientDevice":"Android - Galaxy S24 Plus","deviceManufacturer":"Samsung","clientDeviceVersion":"14"},
{"clientDevice":"Android - Galaxy S23 Plus","deviceManufacturer":"Samsung","clientDeviceVersion":"13"},
{"clientDevice":"Android - Galaxy A74 5G","deviceManufacturer":"Samsung","clientDeviceVersion":"13"},
{"clientDevice":"Android - Galaxy Z Fold4","deviceManufacturer":"Samsung","clientDeviceVersion":"12"},
{"clientDevice":"Android - Galaxy Z Flip4","deviceManufacturer":"Samsung","clientDeviceVersion":"12"},
{"clientDevice":"Android - Galaxy A33 5G","deviceManufacturer":"Samsung","clientDeviceVersion":"12"},
{"clientDevice":"Android - Galaxy A23 5G","deviceManufacturer":"Samsung","clientDeviceVersion":"12"},
{"clientDevice":"Android - Galaxy S22","deviceManufacturer":"Samsung","clientDeviceVersion":"12"},
{"clientDevice":"Android - Galaxy S21","deviceManufacturer":"Samsung","clientDeviceVersion":"11"},
{"clientDevice":"Android - Moto Edge 40 Pro","deviceManufacturer":"Motorola","clientDeviceVersion":"13"},
{"clientDevice":"Android - Moto G Stylus (2024)","deviceManufacturer":"Motorola","clientDeviceVersion":"13"},
{"clientDevice":"Android - Moto Razr 40","deviceManufacturer":"Motorola","clientDeviceVersion":"13"},
{"clientDevice":"Android - Moto G54 5G","deviceManufacturer":"Motorola","clientDeviceVersion":"13"},
{"clientDevice":"Android - Moto Edge 30 Ultra","deviceManufacturer":"Motorola","clientDeviceVersion":"12"},
{"clientDevice":"Android - Moto G34 5G","deviceManufacturer":"Motorola","clientDeviceVersion":"13"},
{"clientDevice":"Android - Moto E32","deviceManufacturer":"Motorola","clientDeviceVersion":"12"},
{"clientDevice":"Android - OnePlus 12R","deviceManufacturer":"OnePlus","clientDeviceVersion":"14"},
{"clientDevice":"Android - OnePlus 11R","deviceManufacturer":"OnePlus","clientDeviceVersion":"13"},
{"clientDevice":"Android - OnePlus 9","deviceManufacturer":"OnePlus","clientDeviceVersion":"11"},
{"clientDevice":"Android - OnePlus Nord N200 5G","deviceManufacturer":"OnePlus","clientDeviceVersion":"11"},
{"clientDevice":"Android - OnePlus Nord 2T","deviceManufacturer":"OnePlus","clientDeviceVersion":"12"},
{"clientDevice":"Android - OnePlus Ace","deviceManufacturer":"OnePlus","clientDeviceVersion":"12"},
{"clientDevice":"Android - Xiaomi 13 Ultra","deviceManufacturer":"Xiaomi","clientDeviceVersion":"13"},
{"clientDevice":"Android - Xiaomi 12S Ultra","deviceManufacturer":"Xiaomi","clientDeviceVersion":"13"},
{"clientDevice":"Android - Redmi Note 13","deviceManufacturer":"Xiaomi","clientDeviceVersion":"13"},
{"clientDevice":"Android - Redmi Note 12","deviceManufacturer":"Xiaomi","clientDeviceVersion":"13"},
{"clientDevice":"Android - Redmi K50 Ultra","deviceManufacturer":"Xiaomi","clientDeviceVersion":"12"},
{"clientDevice":"Android - Redmi 12C","deviceManufacturer":"Xiaomi","clientDeviceVersion":"13"},
{"clientDevice":"Android - Asus ROG Phone 6","deviceManufacturer":"Asus","clientDeviceVersion":"12"},
{"clientDevice":"Android - Asus Zenfone 9","deviceManufacturer":"Asus","clientDeviceVersion":"12"},
{"clientDevice":"Android - TCL 405","deviceManufacturer":"TCL","clientDeviceVersion":"13"},
{"clientDevice":"Android - TCL 30 SE","deviceManufacturer":"TCL","clientDeviceVersion":"12"},
{"clientDevice":"Android - Nokia X20 5G","deviceManufacturer":"Nokia","clientDeviceVersion":"12"},
{"clientDevice":"Android - Nokia G50 5G","deviceManufacturer":"Nokia","clientDeviceVersion":"12"},
{"clientDevice":"Android - Vivo V29 Pro","deviceManufacturer":"Vivo","clientDeviceVersion":"13"},
{"clientDevice":"Android - Vivo S18 Pro","deviceManufacturer":"Vivo","clientDeviceVersion":"13"},
{"clientDevice":"Android - Oppo Find X5 Pro","deviceManufacturer":"Oppo","clientDeviceVersion":"12"},
{"clientDevice":"Android - Oppo Reno 10 Pro+","deviceManufacturer":"Oppo","clientDeviceVersion":"13"},
{"clientDevice":"Android - Realme GT Neo5","deviceManufacturer":"Realme","clientDeviceVersion":"13"},
{"clientDevice":"Android - Realme 9 Pro+","deviceManufacturer":"Realme","clientDeviceVersion":"12"}
]
uk_devices_list = [
{"clientDevice":"iOS - iPhone 16","deviceManufacturer":"Apple","clientDeviceVersion":"18"},
{"clientDevice":"iOS - iPhone 16 Pro Max","deviceManufacturer":"Apple","clientDeviceVersion":"18"},
{"clientDevice":"iOS - iPhone 15","deviceManufacturer":"Apple","clientDeviceVersion":"17"},
{"clientDevice":"iOS - iPhone 15 Pro","deviceManufacturer":"Apple","clientDeviceVersion":"17"},
{"clientDevice":"iOS - iPhone 14 Pro","deviceManufacturer":"Apple","clientDeviceVersion":"16"},
{"clientDevice":"iOS - iPhone 14 Plus","deviceManufacturer":"Apple","clientDeviceVersion":"16"},
{"clientDevice":"iOS - iPhone 13 Pro Max","deviceManufacturer":"Apple","clientDeviceVersion":"15"},
{"clientDevice":"iOS - iPhone 13 Mini","deviceManufacturer":"Apple","clientDeviceVersion":"15"},
{"clientDevice":"iOS - iPhone SE (2022)","deviceManufacturer":"Apple","clientDeviceVersion":"15"},
{"clientDevice":"iOS - iPad Air (2024)","deviceManufacturer":"Apple","clientDeviceVersion":"18"},
{"clientDevice":"iOS - iPad Pro 11-inch (2024)","deviceManufacturer":"Apple","clientDeviceVersion":"18"},
{"clientDevice":"iOS - iPad 10th Gen","deviceManufacturer":"Apple","clientDeviceVersion":"17"},
{"clientDevice":"Android - Samsung Galaxy S25 Ultra","deviceManufacturer":"Samsung","clientDeviceVersion":"14"},
{"clientDevice":"Android - Samsung Galaxy S25","deviceManufacturer":"Samsung","clientDeviceVersion":"14"},
{"clientDevice":"Android - Samsung Galaxy S24 Ultra","deviceManufacturer":"Samsung","clientDeviceVersion":"14"},
{"clientDevice":"Android - Samsung Galaxy S24","deviceManufacturer":"Samsung","clientDeviceVersion":"14"},
{"clientDevice":"Android - Samsung Galaxy A56","deviceManufacturer":"Samsung","clientDeviceVersion":"13"},
{"clientDevice":"Android - Samsung Galaxy A55","deviceManufacturer":"Samsung","clientDeviceVersion":"13"},
{"clientDevice":"Android - Samsung Galaxy Z Fold5","deviceManufacturer":"Samsung","clientDeviceVersion":"13"},
{"clientDevice":"Android - Samsung Galaxy Z Flip5","deviceManufacturer":"Samsung","clientDeviceVersion":"13"},
{"clientDevice":"Android - Google Pixel 10 Pro XL","deviceManufacturer":"Google","clientDeviceVersion":"14"},
{"clientDevice":"Android - Google Pixel 10 Pro","deviceManufacturer":"Google","clientDeviceVersion":"14"},
{"clientDevice":"Android - Google Pixel 9 Pro","deviceManufacturer":"Google","clientDeviceVersion":"14"},
{"clientDevice":"Android - Google Pixel 9","deviceManufacturer":"Google","clientDeviceVersion":"14"},
{"clientDevice":"Android - Google Pixel 8 Pro","deviceManufacturer":"Google","clientDeviceVersion":"13"},
{"clientDevice":"Android - Google Pixel 8a","deviceManufacturer":"Google","clientDeviceVersion":"13"},
{"clientDevice":"Android - OnePlus Nord N100","deviceManufacturer":"OnePlus","clientDeviceVersion":"11"},
{"clientDevice":"Android - OnePlus 12","deviceManufacturer":"OnePlus","clientDeviceVersion":"14"},
{"clientDevice":"Android - OnePlus 11","deviceManufacturer":"OnePlus","clientDeviceVersion":"13"},
{"clientDevice":"Android - OnePlus Nord 2 5G","deviceManufacturer":"OnePlus","clientDeviceVersion":"12"},
{"clientDevice":"Android - OnePlus 8 Pro","deviceManufacturer":"OnePlus","clientDeviceVersion":"11"},
{"clientDevice":"Android - OnePlus 7t","deviceManufacturer":"OnePlus","clientDeviceVersion":"11"},
{"clientDevice":"Android - Nokia 2.1","deviceManufacturer":"Nokia","clientDeviceVersion":"11"},
{"clientDevice":"Android - Nokia X30 5G","deviceManufacturer":"Nokia","clientDeviceVersion":"13"},
{"clientDevice":"Android - Nokia G42 5G","deviceManufacturer":"Nokia","clientDeviceVersion":"13"},
{"clientDevice":"Android - Oppo A54s 2021","deviceManufacturer":"Oppo","clientDeviceVersion":"11"},
{"clientDevice":"Android - Oppo Find X7 Ultra","deviceManufacturer":"Oppo","clientDeviceVersion":"14"},
{"clientDevice":"Android - Oppo Find X6 Pro","deviceManufacturer":"Oppo","clientDeviceVersion":"13"},
{"clientDevice":"Android - Oppo Reno 11 Pro","deviceManufacturer":"Oppo","clientDeviceVersion":"13"},
{"clientDevice":"Android - Vivo X100 Pro","deviceManufacturer":"Vivo","clientDeviceVersion":"14"},
{"clientDevice":"Android - Vivo V30 Pro","deviceManufacturer":"Vivo","clientDeviceVersion":"13"},
{"clientDevice":"Android - Vivo S18 Pro","deviceManufacturer":"Vivo","clientDeviceVersion":"13"},
{"clientDevice":"Android - Huawei P20","deviceManufacturer":"Huawei","clientDeviceVersion":"10"},
{"clientDevice":"Android - Huawei Mate 20 Lite","deviceManufacturer":"Huawei","clientDeviceVersion":"10"},
{"clientDevice":"Android - Huawei Y6ii Compact","deviceManufacturer":"Huawei","clientDeviceVersion":"10"},
{"clientDevice":"Android - Huawei Ascend G510","deviceManufacturer":"Huawei","clientDeviceVersion":"10"},
{"clientDevice":"Android - Motorola Razr 5G 2nd Gen","deviceManufacturer":"Motorola","clientDeviceVersion":"11"},
{"clientDevice":"Android - Motorola Edge 60","deviceManufacturer":"Motorola","clientDeviceVersion":"14"},
{"clientDevice":"Android - Motorola G Power (2024)","deviceManufacturer":"Motorola","clientDeviceVersion":"13"},
{"clientDevice":"Android - Vodafone V1230","deviceManufacturer":"Vodafone","clientDeviceVersion":"11"},
{"clientDevice":"Android - Vodafone V1210","deviceManufacturer":"Vodafone","clientDeviceVersion":"10"},
{"clientDevice":"Android - Vodafone Smart III","deviceManufacturer":"Vodafone","clientDeviceVersion":"10"},
{"clientDevice":"Android - HTC One Mini LTE 601n","deviceManufacturer":"HTC","clientDeviceVersion":"10"},
{"clientDevice":"Android - Samsung Galaxy S21 Ultra 5G","deviceManufacturer":"Samsung","clientDeviceVersion":"11"},
{"clientDevice":"Android - Samsung Galaxy S9 Plus","deviceManufacturer":"Samsung","clientDeviceVersion":"10"},
{"clientDevice":"Android - Samsung Galaxy Note 8","deviceManufacturer":"Samsung","clientDeviceVersion":"10"},
{"clientDevice":"Android - Samsung Galaxy Express 2","deviceManufacturer":"Samsung","clientDeviceVersion":"10"},
{"clientDevice":"Android - Samsung Galaxy S5","deviceManufacturer":"Samsung","clientDeviceVersion":"10"},
{"clientDevice":"Android - Realme GT5 Pro","deviceManufacturer":"Realme","clientDeviceVersion":"14"},
{"clientDevice":"Android - Realme 11 Pro+","deviceManufacturer":"Realme","clientDeviceVersion":"13"},
{"clientDevice":"Android - Realme GT Neo5","deviceManufacturer":"Realme","clientDeviceVersion":"13"},
{"clientDevice":"iOS - iPhone XS","deviceManufacturer":"Apple","clientDeviceVersion":"14"},
{"clientDevice":"iOS - iPhone 11 Pro Max","deviceManufacturer":"Apple","clientDeviceVersion":"14"},
{"clientDevice":"iOS - iPhone 12 5G","deviceManufacturer":"Apple","clientDeviceVersion":"14"},
{"clientDevice":"iOS - iPhone 12 Pro","deviceManufacturer":"Apple","clientDeviceVersion":"14"},
{"clientDevice":"iOS - iPad Pro 11-inch 2021","deviceManufacturer":"Apple","clientDeviceVersion":"15"},
{"clientDevice":"iOS - iPad Pro 11-inch 2020","deviceManufacturer":"Apple","clientDeviceVersion":"14"},
{"clientDevice":"iOS - iPad Air CDMA A1475","deviceManufacturer":"Apple","clientDeviceVersion":"14"},
{"clientDevice":"Android - Google Pixel 3a","deviceManufacturer":"Google","clientDeviceVersion":"11"},
{"clientDevice":"Android - Google Pixel 4a (5G)","deviceManufacturer":"Google","clientDeviceVersion":"11"},
{"clientDevice":"Android - Google Pixel 5a","deviceManufacturer":"Google","clientDeviceVersion":"11"},
{"clientDevice":"Android - OnePlus Nord N20","deviceManufacturer":"OnePlus","clientDeviceVersion":"12"},
{"clientDevice":"Android - OnePlus Nord N30","deviceManufacturer":"OnePlus","clientDeviceVersion":"13"},
{"clientDevice":"Android - Samsung Galaxy A54","deviceManufacturer":"Samsung","clientDeviceVersion":"13"},
{"clientDevice":"Android - Samsung Galaxy A34","deviceManufacturer":"Samsung","clientDeviceVersion":"13"},
{"clientDevice":"Android - Samsung Galaxy A14","deviceManufacturer":"Samsung","clientDeviceVersion":"13"},
{"clientDevice":"Android - Samsung Galaxy S22 Ultra","deviceManufacturer":"Samsung","clientDeviceVersion":"12"},
{"clientDevice":"Android - Samsung Galaxy S22","deviceManufacturer":"Samsung","clientDeviceVersion":"12"},
{"clientDevice":"Android - Samsung Galaxy A53 5G","deviceManufacturer":"Samsung","clientDeviceVersion":"12"},
{"clientDevice":"Android - Samsung Galaxy A33 5G","deviceManufacturer":"Samsung","clientDeviceVersion":"12"},
{"clientDevice":"Android - Xiaomi 14 Ultra","deviceManufacturer":"Xiaomi","clientDeviceVersion":"14"},
{"clientDevice":"Android - Xiaomi 14","deviceManufacturer":"Xiaomi","clientDeviceVersion":"14"},
{"clientDevice":"Android - Xiaomi 13 Pro","deviceManufacturer":"Xiaomi","clientDeviceVersion":"13"},
{"clientDevice":"Android - Redmi Note 13 Pro","deviceManufacturer":"Xiaomi","clientDeviceVersion":"13"},
{"clientDevice":"Android - Redmi K70","deviceManufacturer":"Xiaomi","clientDeviceVersion":"14"},
{"clientDevice":"Android - Redmi K60","deviceManufacturer":"Xiaomi","clientDeviceVersion":"13"},
{"clientDevice":"Android - Asus ROG Phone 8","deviceManufacturer":"Asus","clientDeviceVersion":"14"},
{"clientDevice":"Android - Asus ROG Phone 7","deviceManufacturer":"Asus","clientDeviceVersion":"13"},
{"clientDevice":"Android - Asus Zenfone 11","deviceManufacturer":"Asus","clientDeviceVersion":"14"},
{"clientDevice":"Android - Asus Zenfone 10","deviceManufacturer":"Asus","clientDeviceVersion":"13"},
{"clientDevice":"Android - TCL 40 SE","deviceManufacturer":"TCL","clientDeviceVersion":"13"},
{"clientDevice":"Android - TCL Stylus 5G","deviceManufacturer":"TCL","clientDeviceVersion":"13"},
{"clientDevice":"Android - TCL 30 V 5G","deviceManufacturer":"TCL","clientDeviceVersion":"12"},
{"clientDevice":"Android - Blackberry Key2","deviceManufacturer":"Blackberry","clientDeviceVersion":"10"},
{"clientDevice":"Android - Blackberry Key2 Red Edition","deviceManufacturer":"Blackberry","clientDeviceVersion":"10"},
{"clientDevice":"Android - Blackberry Keyone","deviceManufacturer":"Blackberry","clientDeviceVersion":"10"},
{"clientDevice":"Android - Motorola Razr 40 Ultra","deviceManufacturer":"Motorola","clientDeviceVersion":"13"},
{"clientDevice":"Android - Motorola Moto G54 5G","deviceManufacturer":"Motorola","clientDeviceVersion":"13"},
{"clientDevice":"Android - Motorola Moto Edge 40 Pro","deviceManufacturer":"Motorola","clientDeviceVersion":"13"},
{"clientDevice":"iOS - iPhone 16 Plus","deviceManufacturer":"Apple","clientDeviceVersion":"18"},
{"clientDevice":"iOS - iPhone 15 Plus","deviceManufacturer":"Apple","clientDeviceVersion":"17"},
{"clientDevice":"iOS - iPhone 14 Pro Max","deviceManufacturer":"Apple","clientDeviceVersion":"16"},
{"clientDevice":"iOS - iPhone 13 Pro","deviceManufacturer":"Apple","clientDeviceVersion":"15"},
{"clientDevice":"iOS - iPhone 12 Mini","deviceManufacturer":"Apple","clientDeviceVersion":"14"},
{"clientDevice":"iOS - iPhone SE 3rd Gen","deviceManufacturer":"Apple","clientDeviceVersion":"16"},
{"clientDevice":"iOS - iPad Pro 5G 11-inch 2021","deviceManufacturer":"Apple","clientDeviceVersion":"15"},
{"clientDevice":"iOS - iPad Air (2022)","deviceManufacturer":"Apple","clientDeviceVersion":"16"},
{"clientDevice":"Android - Samsung Galaxy S23 Ultra","deviceManufacturer":"Samsung","clientDeviceVersion":"13"},
{"clientDevice":"Android - Samsung Galaxy S23","deviceManufacturer":"Samsung","clientDeviceVersion":"13"},
{"clientDevice":"Android - Samsung Galaxy Z Fold4","deviceManufacturer":"Samsung","clientDeviceVersion":"12"},
{"clientDevice":"Android - Samsung Galaxy Z Flip4","deviceManufacturer":"Samsung","clientDeviceVersion":"12"},
{"clientDevice":"Android - Google Pixel 7 Pro","deviceManufacturer":"Google","clientDeviceVersion":"13"},
{"clientDevice":"Android - Google Pixel 7a","deviceManufacturer":"Google","clientDeviceVersion":"13"},
{"clientDevice":"Android - Google Pixel 6 Pro","deviceManufacturer":"Google","clientDeviceVersion":"12"},
{"clientDevice":"Android - Google Pixel 6a","deviceManufacturer":"Google","clientDeviceVersion":"12"},
{"clientDevice":"Android - OnePlus 12R","deviceManufacturer":"OnePlus","clientDeviceVersion":"14"},
{"clientDevice":"Android - OnePlus 11R","deviceManufacturer":"OnePlus","clientDeviceVersion":"13"},
{"clientDevice":"Android - OnePlus Nord CE 3","deviceManufacturer":"OnePlus","clientDeviceVersion":"13"},
{"clientDevice":"Android - Oppo Reno 10 Pro+","deviceManufacturer":"Oppo","clientDeviceVersion":"13"},
{"clientDevice":"Android - Oppo Find X5 Pro","deviceManufacturer":"Oppo","clientDeviceVersion":"12"},
{"clientDevice":"Android - Vivo V29 Pro","deviceManufacturer":"Vivo","clientDeviceVersion":"13"},
{"clientDevice":"Android - Realme 9 Pro+","deviceManufacturer":"Realme","clientDeviceVersion":"12"},
{"clientDevice":"Android - Xiaomi 13 Ultra","deviceManufacturer":"Xiaomi","clientDeviceVersion":"13"},
{"clientDevice":"Android - Redmi Note 12","deviceManufacturer":"Xiaomi","clientDeviceVersion":"13"},
{"clientDevice":"Android - Redmi K50 Ultra","deviceManufacturer":"Xiaomi","clientDeviceVersion":"12"},
{"clientDevice":"Android - Asus Zenfone 9","deviceManufacturer":"Asus","clientDeviceVersion":"12"},
{"clientDevice":"Android - Asus ROG Phone 6","deviceManufacturer":"Asus","clientDeviceVersion":"12"},
{"clientDevice":"Android - TCL 405","deviceManufacturer":"TCL","clientDeviceVersion":"13"},
{"clientDevice":"Android - TCL 30 SE","deviceManufacturer":"TCL","clientDeviceVersion":"12"},
{"clientDevice":"Android - Nokia X20 5G","deviceManufacturer":"Nokia","clientDeviceVersion":"12"},
{"clientDevice":"Android - Nokia G50 5G","deviceManufacturer":"Nokia","clientDeviceVersion":"12"},
{"clientDevice":"Android - Motorola Moto G Stylus 5G (2023)","deviceManufacturer":"Motorola","clientDeviceVersion":"13"},
{"clientDevice":"Android - Motorola Moto One 5G Ace","deviceManufacturer":"Motorola","clientDeviceVersion":"11"},
{"clientDevice":"Android - Vodafone Smart V10","deviceManufacturer":"Vodafone","clientDeviceVersion":"11"},
{"clientDevice":"Android - HTC U23 Pro","deviceManufacturer":"HTC","clientDeviceVersion":"13"},
{"clientDevice":"Android - HTC Wildfire E5 Plus","deviceManufacturer":"HTC","clientDeviceVersion":"12"},
{"clientDevice":"iOS - iPhone 17 Pro","deviceManufacturer":"Apple","clientDeviceVersion":"19"},
{"clientDevice":"iOS - iPhone 17","deviceManufacturer":"Apple","clientDeviceVersion":"19"},
{"clientDevice":"iOS - iPad Pro 12.9-inch (2024)","deviceManufacturer":"Apple","clientDeviceVersion":"18"},
{"clientDevice":"iOS - iPad Mini 6th Gen","deviceManufacturer":"Apple","clientDeviceVersion":"17"},
{"clientDevice":"Android - Samsung Galaxy S26 Ultra","deviceManufacturer":"Samsung","clientDeviceVersion":"14"},
{"clientDevice":"Android - Samsung Galaxy A57 5G","deviceManufacturer":"Samsung","clientDeviceVersion":"14"},
{"clientDevice":"Android - Google Pixel 11 Pro","deviceManufacturer":"Google","clientDeviceVersion":"14"},
{"clientDevice":"Android - OnePlus 13","deviceManufacturer":"OnePlus","clientDeviceVersion":"14"},
{"clientDevice":"Android - Oppo Find X8 Pro","deviceManufacturer":"Oppo","clientDeviceVersion":"14"},
{"clientDevice":"Android - Vivo X110 Pro","deviceManufacturer":"Vivo","clientDeviceVersion":"14"},
{"clientDevice":"Android - Xiaomi 15 Pro","deviceManufacturer":"Xiaomi","clientDeviceVersion":"14"},
{"clientDevice":"Android - Realme GT6 Pro","deviceManufacturer":"Realme","clientDeviceVersion":"14"},
{"clientDevice":"Android - Asus ROG Phone 9","deviceManufacturer":"Asus","clientDeviceVersion":"14"},
{"clientDevice":"Android - Motorola Edge 70 Pro","deviceManufacturer":"Motorola","clientDeviceVersion":"14"},
{"clientDevice":"Android - Nokia X40 5G","deviceManufacturer":"Nokia","clientDeviceVersion":"14"},
{"clientDevice":"Android - TCL 50 SE","deviceManufacturer":"TCL","clientDeviceVersion":"14"}
]
de_devices_list = [
{"clientDevice":"iOS - iPhone 16 Pro Max","deviceManufacturer":"Apple","clientDeviceVersion":"18"},
{"clientDevice":"iOS - iPhone 16","deviceManufacturer":"Apple","clientDeviceVersion":"18"},
{"clientDevice":"iOS - iPhone 15 Pro Max","deviceManufacturer":"Apple","clientDeviceVersion":"17"},
{"clientDevice":"iOS - iPhone 15","deviceManufacturer":"Apple","clientDeviceVersion":"17"},
{"clientDevice":"iOS - iPhone 14 Pro","deviceManufacturer":"Apple","clientDeviceVersion":"16"},
{"clientDevice":"iOS - iPhone 14","deviceManufacturer":"Apple","clientDeviceVersion":"16"},
{"clientDevice":"iOS - iPhone 13 Pro Max","deviceManufacturer":"Apple","clientDeviceVersion":"15"},
{"clientDevice":"iOS - iPhone 13","deviceManufacturer":"Apple","clientDeviceVersion":"15"},
{"clientDevice":"iOS - iPhone 12 Pro","deviceManufacturer":"Apple","clientDeviceVersion":"14"},
{"clientDevice":"iOS - iPhone 12","deviceManufacturer":"Apple","clientDeviceVersion":"14"},
{"clientDevice":"iOS - iPhone SE (2022)","deviceManufacturer":"Apple","clientDeviceVersion":"15"},
{"clientDevice":"iOS - iPhone SE 3rd Gen","deviceManufacturer":"Apple","clientDeviceVersion":"16"},
{"clientDevice":"iOS - iPhone Air","deviceManufacturer":"Apple","clientDeviceVersion":"18"},
{"clientDevice":"Android - Samsung Galaxy S26 Ultra","deviceManufacturer":"Samsung","clientDeviceVersion":"14"},
{"clientDevice":"Android - Samsung Galaxy S26 Pro","deviceManufacturer":"Samsung","clientDeviceVersion":"14"},
{"clientDevice":"Android - Samsung Galaxy S26 FE","deviceManufacturer":"Samsung","clientDeviceVersion":"14"},
{"clientDevice":"Android - Samsung Galaxy S25 Ultra","deviceManufacturer":"Samsung","clientDeviceVersion":"14"},
{"clientDevice":"Android - Samsung Galaxy S25","deviceManufacturer":"Samsung","clientDeviceVersion":"14"},
{"clientDevice":"Android - Samsung Galaxy S24 Ultra","deviceManufacturer":"Samsung","clientDeviceVersion":"14"},
{"clientDevice":"Android - Samsung Galaxy S24 FE","deviceManufacturer":"Samsung","clientDeviceVersion":"13"},
{"clientDevice":"Android - Samsung Galaxy S23 Ultra","deviceManufacturer":"Samsung","clientDeviceVersion":"13"},
{"clientDevice":"Android - Samsung Galaxy A57 5G","deviceManufacturer":"Samsung","clientDeviceVersion":"14"},
{"clientDevice":"Android - Samsung Galaxy A56","deviceManufacturer":"Samsung","clientDeviceVersion":"13"},
{"clientDevice":"Android - Samsung Galaxy A55","deviceManufacturer":"Samsung","clientDeviceVersion":"13"},
{"clientDevice":"Android - Samsung Galaxy A54","deviceManufacturer":"Samsung","clientDeviceVersion":"13"},
{"clientDevice":"Android - Samsung Galaxy Z Fold5","deviceManufacturer":"Samsung","clientDeviceVersion":"13"},
{"clientDevice":"Android - Samsung Galaxy Z Flip5","deviceManufacturer":"Samsung","clientDeviceVersion":"13"},
{"clientDevice":"Android - Samsung Galaxy Tab S12 Ultra","deviceManufacturer":"Samsung","clientDeviceVersion":"14"},
{"clientDevice":"Android - Samsung Galaxy Tab S12","deviceManufacturer":"Samsung","clientDeviceVersion":"14"},
{"clientDevice":"Android - Samsung Galaxy Tab S11 Lite","deviceManufacturer":"Samsung","clientDeviceVersion":"13"},
{"clientDevice":"Android - Google Pixel 9 Pro Fold","deviceManufacturer":"Google","clientDeviceVersion":"14"},
{"clientDevice":"Android - Google Pixel 9 Pro","deviceManufacturer":"Google","clientDeviceVersion":"14"},
{"clientDevice":"Android - Google Pixel 9","deviceManufacturer":"Google","clientDeviceVersion":"14"},
{"clientDevice":"Android - Google Pixel 8 Pro","deviceManufacturer":"Google","clientDeviceVersion":"13"},
{"clientDevice":"Android - Google Pixel 8","deviceManufacturer":"Google","clientDeviceVersion":"13"},
{"clientDevice":"Android - Google Pixel 7 Pro","deviceManufacturer":"Google","clientDeviceVersion":"13"},
{"clientDevice":"Android - Google Pixel 7","deviceManufacturer":"Google","clientDeviceVersion":"13"},
{"clientDevice":"Android - Vivo X300 Pro","deviceManufacturer":"Vivo","clientDeviceVersion":"16"},
{"clientDevice":"Android - Vivo X300","deviceManufacturer":"Vivo","clientDeviceVersion":"16"},
{"clientDevice":"Android - Vivo X200","deviceManufacturer":"Vivo","clientDeviceVersion":"15"},
{"clientDevice":"Android - Vivo V50 Pro","deviceManufacturer":"Vivo","clientDeviceVersion":"15"},
{"clientDevice":"Android - Vivo V50","deviceManufacturer":"Vivo","clientDeviceVersion":"15"},
{"clientDevice":"Android - Vivo Y500","deviceManufacturer":"Vivo","clientDeviceVersion":"14"},
{"clientDevice":"Android - Vivo Y37 Pro","deviceManufacturer":"Vivo","clientDeviceVersion":"14"},
{"clientDevice":"Android - Vivo IQOO 12","deviceManufacturer":"Vivo","clientDeviceVersion":"15"},
{"clientDevice":"Android - Xiaomi 15 Ultra","deviceManufacturer":"Xiaomi","clientDeviceVersion":"14"},
{"clientDevice":"Android - Xiaomi 15","deviceManufacturer":"Xiaomi","clientDeviceVersion":"14"},
{"clientDevice":"Android - Xiaomi 14 Ultra","deviceManufacturer":"Xiaomi","clientDeviceVersion":"14"},
{"clientDevice":"Android - Xiaomi 14T Pro","deviceManufacturer":"Xiaomi","clientDeviceVersion":"14"},
{"clientDevice":"Android - Xiaomi 14","deviceManufacturer":"Xiaomi","clientDeviceVersion":"14"},
{"clientDevice":"Android - Xiaomi 13 Pro","deviceManufacturer":"Xiaomi","clientDeviceVersion":"13"},
{"clientDevice":"Android - Redmi Note 14 Pro","deviceManufacturer":"Xiaomi","clientDeviceVersion":"14"},
{"clientDevice":"Android - Redmi Note 13 Pro","deviceManufacturer":"Xiaomi","clientDeviceVersion":"13"},
{"clientDevice":"Android - Redmi Note 12 Pro","deviceManufacturer":"Xiaomi","clientDeviceVersion":"13"},
{"clientDevice":"Android - Redmi 14R","deviceManufacturer":"Xiaomi","clientDeviceVersion":"14"},
{"clientDevice":"Android - Redmi K70 Ultra","deviceManufacturer":"Xiaomi","clientDeviceVersion":"14"},
{"clientDevice":"Android - Redmi K60","deviceManufacturer":"Xiaomi","clientDeviceVersion":"13"},
{"clientDevice":"Android - Huawei Pura 70 Ultra","deviceManufacturer":"Huawei","clientDeviceVersion":"14"},
{"clientDevice":"Android - Huawei Pura 70 Pro+","deviceManufacturer":"Huawei","clientDeviceVersion":"14"},
{"clientDevice":"Android - Huawei Pura 70 Pro","deviceManufacturer":"Huawei","clientDeviceVersion":"14"},
{"clientDevice":"Android - Huawei Pura 70","deviceManufacturer":"Huawei","clientDeviceVersion":"14"},
{"clientDevice":"Android - Huawei Nova 12 Ultra","deviceManufacturer":"Huawei","clientDeviceVersion":"13"},
{"clientDevice":"Android - Huawei Nova 12 Pro","deviceManufacturer":"Huawei","clientDeviceVersion":"13"},
{"clientDevice":"Android - Huawei Nova 12","deviceManufacturer":"Huawei","clientDeviceVersion":"13"},
{"clientDevice":"Android - Huawei Nova 12 Lite","deviceManufacturer":"Huawei","clientDeviceVersion":"13"},
{"clientDevice":"Android - Huawei Nova Flip","deviceManufacturer":"Huawei","clientDeviceVersion":"14"},
{"clientDevice":"Android - Huawei Mate XT Ultimate","deviceManufacturer":"Huawei","clientDeviceVersion":"14"},
{"clientDevice":"Android - Huawei Enjoy 70","deviceManufacturer":"Huawei","clientDeviceVersion":"13"},
{"clientDevice":"Android - Oppo Find X8 Pro","deviceManufacturer":"Oppo","clientDeviceVersion":"14"},
{"clientDevice":"Android - Oppo Find X7 Ultra","deviceManufacturer":"Oppo","clientDeviceVersion":"14"},
{"clientDevice":"Android - Oppo Find X6 Pro","deviceManufacturer":"Oppo","clientDeviceVersion":"13"},
{"clientDevice":"Android - Oppo Reno 11 Pro","deviceManufacturer":"Oppo","clientDeviceVersion":"13"},
{"clientDevice":"Android - Oppo Reno 10 Pro+","deviceManufacturer":"Oppo","clientDeviceVersion":"13"},
{"clientDevice":"Android - Oppo A6 Pro","deviceManufacturer":"Oppo","clientDeviceVersion":"13"},
{"clientDevice":"Android - Oppo A6 GT 5G","deviceManufacturer":"Oppo","clientDeviceVersion":"13"},
{"clientDevice":"Android - Oppo A6i 5G","deviceManufacturer":"Oppo","clientDeviceVersion":"13"},
{"clientDevice":"Android - Oppo F31","deviceManufacturer":"Oppo","clientDeviceVersion":"14"},
{"clientDevice":"Android - OnePlus 13","deviceManufacturer":"OnePlus","clientDeviceVersion":"14"},
{"clientDevice":"Android - OnePlus 12","deviceManufacturer":"OnePlus","clientDeviceVersion":"14"},
{"clientDevice":"Android - OnePlus 11","deviceManufacturer":"OnePlus","clientDeviceVersion":"13"},
{"clientDevice":"Android - OnePlus Nord N30","deviceManufacturer":"OnePlus","clientDeviceVersion":"13"},
{"clientDevice":"Android - OnePlus Nord 3","deviceManufacturer":"OnePlus","clientDeviceVersion":"13"},
{"clientDevice":"Android - OnePlus Nord CE 3","deviceManufacturer":"OnePlus","clientDeviceVersion":"13"},
{"clientDevice":"Android - Realme 13 4G","deviceManufacturer":"Realme","clientDeviceVersion":"13"},
{"clientDevice":"Android - Realme 11 Pro+","deviceManufacturer":"Realme","clientDeviceVersion":"13"},
{"clientDevice":"Android - Realme GT6 Pro","deviceManufacturer":"Realme","clientDeviceVersion":"14"},
{"clientDevice":"Android - Realme GT5 Pro","deviceManufacturer":"Realme","clientDeviceVersion":"14"},
{"clientDevice":"Android - Realme GT Neo5","deviceManufacturer":"Realme","clientDeviceVersion":"13"},
{"clientDevice":"Android - Realme Narzo N61","deviceManufacturer":"Realme","clientDeviceVersion":"13"},
{"clientDevice":"Android - Realme V60","deviceManufacturer":"Realme","clientDeviceVersion":"13"},
{"clientDevice":"Android - Motorola Edge 70 Pro","deviceManufacturer":"Motorola","clientDeviceVersion":"14"},
{"clientDevice":"Android - Motorola Edge 60 Neo","deviceManufacturer":"Motorola","clientDeviceVersion":"14"},
{"clientDevice":"Android - Motorola Edge 60","deviceManufacturer":"Motorola","clientDeviceVersion":"14"},
{"clientDevice":"Android - Motorola Edge 50 Pro","deviceManufacturer":"Motorola","clientDeviceVersion":"14"},
{"clientDevice":"Android - Motorola Moto G06 Power","deviceManufacturer":"Motorola","clientDeviceVersion":"13"},
{"clientDevice":"Android - Motorola Moto G Power (2024)","deviceManufacturer":"Motorola","clientDeviceVersion":"13"},
{"clientDevice":"Android - Motorola Moto G Stylus 5G (2023)","deviceManufacturer":"Motorola","clientDeviceVersion":"13"},
{"clientDevice":"Android - Honor 500 Pro","deviceManufacturer":"Honor","clientDeviceVersion":"14"},
{"clientDevice":"Android - Honor 500","deviceManufacturer":"Honor","clientDeviceVersion":"14"},
{"clientDevice":"Android - Asus ROG Phone 9","deviceManufacturer":"Asus","clientDeviceVersion":"14"},
{"clientDevice":"Android - Asus ROG Phone 8","deviceManufacturer":"Asus","clientDeviceVersion":"14"},
{"clientDevice":"Android - Asus ROG Phone 7","deviceManufacturer":"Asus","clientDeviceVersion":"13"},
{"clientDevice":"Android - Asus Zenfone 11","deviceManufacturer":"Asus","clientDeviceVersion":"14"},
{"clientDevice":"Android - Asus Zenfone 10","deviceManufacturer":"Asus","clientDeviceVersion":"13"},
{"clientDevice":"Android - ZTE Nubia Air","deviceManufacturer":"ZTE","clientDeviceVersion":"13"},
{"clientDevice":"Android - Ulefone Armor 26 Ultra","deviceManufacturer":"Ulefone","clientDeviceVersion":"13"},
{"clientDevice":"Android - Ulefone Armor 24","deviceManufacturer":"Ulefone","clientDeviceVersion":"13"},
{"clientDevice":"Android - Ulefone Power Armor 18 Ultra","deviceManufacturer":"Ulefone","clientDeviceVersion":"13"},
{"clientDevice":"Android - Ulefone Power Armor 18 T Ultra","deviceManufacturer":"Ulefone","clientDeviceVersion":"13"},
{"clientDevice":"Android - Ulefone Note 17 Pro","deviceManufacturer":"Ulefone","clientDeviceVersion":"13"},
{"clientDevice":"Android - TCL 50 SE","deviceManufacturer":"TCL","clientDeviceVersion":"14"},
{"clientDevice":"Android - TCL 40 SE","deviceManufacturer":"TCL","clientDeviceVersion":"13"},
{"clientDevice":"Android - TCL Stylus 5G","deviceManufacturer":"TCL","clientDeviceVersion":"13"},
{"clientDevice":"Android - TCL 30 V 5G","deviceManufacturer":"TCL","clientDeviceVersion":"12"},
{"clientDevice":"Android - Tecno Pova Slim","deviceManufacturer":"Tecno","clientDeviceVersion":"13"},
{"clientDevice":"Android - Tecno Megapad Pro","deviceManufacturer":"Tecno","clientDeviceVersion":"13"},
{"clientDevice":"Android - Nokia G42 5G","deviceManufacturer":"Nokia","clientDeviceVersion":"13"},
{"clientDevice":"Android - Nokia X30 5G","deviceManufacturer":"Nokia","clientDeviceVersion":"13"},
{"clientDevice":"Android - Nokia X40 5G","deviceManufacturer":"Nokia","clientDeviceVersion":"14"},
{"clientDevice":"Android - Nokia G50 5G","deviceManufacturer":"Nokia","clientDeviceVersion":"12"},
{"clientDevice":"Android - Vodafone Smart V10","deviceManufacturer":"Vodafone","clientDeviceVersion":"13"},
{"clientDevice":"iOS - iPad Pro 12.9-inch (2024)","deviceManufacturer":"Apple","clientDeviceVersion":"18"},
{"clientDevice":"iOS - iPad Pro 11-inch (2024)","deviceManufacturer":"Apple","clientDeviceVersion":"18"},
{"clientDevice":"iOS - iPad Air (2024)","deviceManufacturer":"Apple","clientDeviceVersion":"18"},
{"clientDevice":"iOS - iPad Mini 6th Gen","deviceManufacturer":"Apple","clientDeviceVersion":"17"},
{"clientDevice":"iOS - iPad 10th Gen","deviceManufacturer":"Apple","clientDeviceVersion":"17"},
{"clientDevice":"Android - Samsung Galaxy S22 Ultra","deviceManufacturer":"Samsung","clientDeviceVersion":"12"},
{"clientDevice":"Android - Samsung Galaxy A53 5G","deviceManufacturer":"Samsung","clientDeviceVersion":"12"},
{"clientDevice":"Android - Google Pixel 6 Pro","deviceManufacturer":"Google","clientDeviceVersion":"12"},
{"clientDevice":"Android - Google Pixel 6","deviceManufacturer":"Google","clientDeviceVersion":"12"},
{"clientDevice":"Android - Vivo V30 Pro","deviceManufacturer":"Vivo","clientDeviceVersion":"13"},
{"clientDevice":"Android - Vivo S18 Pro","deviceManufacturer":"Vivo","clientDeviceVersion":"13"},
{"clientDevice":"Android - Xiaomi 13 Ultra","deviceManufacturer":"Xiaomi","clientDeviceVersion":"13"},
{"clientDevice":"Android - Redmi K50 Ultra","deviceManufacturer":"Xiaomi","clientDeviceVersion":"12"},
{"clientDevice":"Android - Oppo Find X5 Pro","deviceManufacturer":"Oppo","clientDeviceVersion":"12"},
{"clientDevice":"Android - OnePlus 12R","deviceManufacturer":"OnePlus","clientDeviceVersion":"14"},
{"clientDevice":"Android - OnePlus 11R","deviceManufacturer":"OnePlus","clientDeviceVersion":"13"},
{"clientDevice":"Android - Realme 9 Pro+","deviceManufacturer":"Realme","clientDeviceVersion":"12"},
{"clientDevice":"Android - Motorola Moto Edge 40 Pro","deviceManufacturer":"Motorola","clientDeviceVersion":"13"},
{"clientDevice":"Android - Motorola Moto G54 5G","deviceManufacturer":"Motorola","clientDeviceVersion":"13"},
{"clientDevice":"Android - Nokia X20 5G","deviceManufacturer":"Nokia","clientDeviceVersion":"12"},
{"clientDevice":"Android - TCL 405","deviceManufacturer":"TCL","clientDeviceVersion":"13"},
{"clientDevice":"Android - Asus Zenfone 9","deviceManufacturer":"Asus","clientDeviceVersion":"12"},
{"clientDevice":"Android - Asus ROG Phone 6","deviceManufacturer":"Asus","clientDeviceVersion":"12"},
{"clientDevice":"Android - Huawei Nova 12i","deviceManufacturer":"Huawei","clientDeviceVersion":"13"},
{"clientDevice":"Android - Huawei Nova 12s","deviceManufacturer":"Huawei","clientDeviceVersion":"13"},
{"clientDevice":"Android - Huawei Nova 12 SE","deviceManufacturer":"Huawei","clientDeviceVersion":"13"},
{"clientDevice":"Android - Vivo V29 Pro","deviceManufacturer":"Vivo","clientDeviceVersion":"13"},
{"clientDevice":"Android - Vivo V40 Lite","deviceManufacturer":"Vivo","clientDeviceVersion":"14"},
{"clientDevice":"Android - Xiaomi Redmi 12C","deviceManufacturer":"Xiaomi","clientDeviceVersion":"13"},
{"clientDevice":"Android - Motorola Moto One 5G Ace","deviceManufacturer":"Motorola","clientDeviceVersion":"11"},
{"clientDevice":"Android - OnePlus Nord N200 5G","deviceManufacturer":"OnePlus","clientDeviceVersion":"11"},
{"clientDevice":"Android - Realme GT Neo5 SE","deviceManufacturer":"Realme","clientDeviceVersion":"13"},
{"clientDevice":"Android - Oppo A54s 2021","deviceManufacturer":"Oppo","clientDeviceVersion":"11"},
{"clientDevice":"Android - Nokia G22","deviceManufacturer":"Nokia","clientDeviceVersion":"12"},
{"clientDevice":"Android - TCL 30 SE","deviceManufacturer":"TCL","clientDeviceVersion":"12"},
{"clientDevice":"iOS - iPhone 17 Pro","deviceManufacturer":"Apple","clientDeviceVersion":"19"},
{"clientDevice":"iOS - iPhone 17","deviceManufacturer":"Apple","clientDeviceVersion":"19"},
{"clientDevice":"iOS - iPad Pro 11-inch 2021","deviceManufacturer":"Apple","clientDeviceVersion":"15"},
{"clientDevice":"iOS - iPad Air (2022)","deviceManufacturer":"Apple","clientDeviceVersion":"16"}
]
# us_cookie_dict ={"i18n-prefs": "USD", "lc-main": "en_US", "session-id": "137-6850115-5627367", "session-id-time": "2082787201l", "session-token": "NDR0kD9QBkk81plbn2yEFeEJ205I0LEzv9G4Q3nG90PVEmpZEtEiL6Ixj3alIu5KBvaiePi9IOHhzSh48qBNQH2yroklDf1+rDTtJ8HNzcfae0ZEL3/szlwFWXRsxH7UwfHip9R66v9ZoO5ni9mrz+4J6QgjTmrzCW7uVjTMthdesVgOk2SVmxyfoLQnmYuScp17v+ayrztH3VFIg/VyhzNBlVbkZDIHg2WB3F+U0JHkiQfiZB1q2uCMWOEIOwRkCGhaRrWHbBgpQtvHnf+Iw2KxVkl2gv1jZga2iNQUhO6cIr2Py5V7evAyuXXhjRaBzIl/STRh58Jr9ctbhdBXnTQsbThexXLn", "skin": "noskin", "ubid-main": "133-5836273-3821350"}
# uk_cookie_dict ={"i18n-prefs": "HKD", "lc-acbuk": "en_GB", "session-id": "521-9387816-0582061", "session-id-time": "2082787201l", "session-token": "\"ANvQ1SZ9VE6Y9cGcEdwhYcEpI1Jql7bOXZ7Q+qdBbb41IuuIFXvUzDSoaXOzPlcUTa3CIMoLIIzD2QOAWnN2h1E/c/iXEzpM8qd4LqR9otFV6PQecFkZKnC/i5v3QIguYgLt3KB9halOcaKi+KXcpG1b5jjYSicsMknbJMQVgfkiqMDXOLcxIns2cHs1xpXgf/DrjOHNpIB6Q24VKaqLTuKbWd8biHv86NGyoBNIs1kkjJxdwZhvWtQC/rHqoiz0e853W2lkrUrdr6Ko3dSIYojEBEgVuglCENJWLmkQzqEMxcIzNgcrpf4ZSlRHhMpmi2D14A6rwrwdo/JMozJSol+Wx3dL7j/AEGiXa1IWwrA=\"", "ubid-acbuk": "259-9451176-7460703"}
# de_cookie_dict ={"i18n-prefs": "HKD", "lc-acbde": "de_DE", "session-id": "258-7262769-1488647", "session-id-time": "2082787201l", "session-token": "RxPtESM/cUQ4JAxsgMz8crm9EMbFhHLK4vPgZzTj2w23v5yWkzjXZsVVsErU5Oi8qzT3Le8nxU1zxeDEWuAg2IL+5fb2VwhE9UOQpLMmnOBWaukpW0CKFMOTvJU6Fu7+IZhWpJWt+ypu5b0KEYVi7CyTsHKh38q8N2m7tGBwb94NyT4tLHyE69XovznI5HV7y19J0aJrDyEYBfk00m6/SwxxOhRbkOXWVIagnGK4N1uQ27n9827rd7o1TpHQc8sWnn1bDAvYbCtGOaUYUHJ8HxnZPsTjKZ2b8OgzIKE9nlvpoAAQOArarZlZxneJTfUY++ucym9Te+RUvPp6SrhpPJyP7W425mA9", "ubid-acbde": "257-6077242-9988057"}
import hashlib
import time
import uuid
from typing import Optional, List
from loguru import logger
import requests
from requests.exceptions import RequestException, ConnectionError, Timeout
# 配置日志
logger.add("amazon_search.log", rotation="10 MB", level="INFO")
# 全局变量(clientDeviceId 固定,cookie 失效时更新)
GLOBAL_CLIENT_DEVICE_ID = str(uuid.uuid4())
logger.info(f"初始化全局 clientDeviceId: {GLOBAL_CLIENT_DEVICE_ID}")
# 常量配置
AMAZON_STYLE_SNAP_URL = "https://match-visualsearch.amazon.com/style-snap/2.0"
AMAZON_SEARCH_BASE_URL = "https://www.amazon.com/s?rh=p_78:{bbx_asin_list}&rank=asin-scores-asc-rank&searchMethod=CameraSearch"
SECRET = "5b6874d3a20417591bd5464a25a37bc6"
APPLICATION = "amzn-mbl-cscan-us"
USERNAME = "amzn-mbl-cscan-us"
RETRY_TIMES = 5 # 重试次数
RETRY_DELAY = 1 # 重试间隔(秒)
def get_amazon_search_url(image_path: str, cookies: dict) -> Optional[str]:
"""
调用亚马逊以图搜物接口,获取搜索结果并生成最终搜索URL
:param image_path: 图片本地路径
:param cookies: 亚马逊请求所需的cookies
:return: 拼接后的搜索URL,失败时返回None
"""
for retry in range(RETRY_TIMES):
try:
logger.info(f"开始第 {retry + 1}/{RETRY_TIMES} 次请求")
# 1. 准备动态参数
session_id = cookies.get("session-id", "")
if not session_id:
logger.error("Cookies中缺少session-id")
return None
client_id = str(uuid.uuid4()) # 每次请求生成新的clientId
ts = str(int(time.time()))
# 2. 生成authtoken
combined = SECRET + USERNAME + APPLICATION + ts
authtoken = hashlib.sha512(combined.encode("utf-8")).hexdigest()
logger.debug(f"生成authtoken: {authtoken[:10]}...") # 只打印前10位避免过长
# 3. 构建query_metadata
query_metadata = (
'{"amznSessionId":"%s","clientVersion":"30.20.2.100","cardsVersion":"1.0",'
'"clientMessageVersion":"1.0","amznDirectedCustomerId":"","clientDeviceId":"%s",'
'"clientDevice":"Android - Pixel 2","deviceManufacturer":"Google","clientDeviceVersion":"10",'
'"clientId":"%s","orientation":"-1","sourceType":"Photo","ingressSource":"ctp","uiMode":"stylesnap"}'
% (session_id, GLOBAL_CLIENT_DEVICE_ID, client_id)
)
# logger.debug(f"构建query_metadata: {query_metadata[:50]}...") # 只打印前50位
# 4. 读取图片文件
try:
with open(image_path, "rb") as f:
image_data = f.read()
logger.info(f"成功读取图片: {image_path} (大小: {len(image_data)} bytes)")
except Exception as e:
logger.error(f"读取图片失败: {str(e)}", exc_info=True)
return None # 图片错误无需重试
# 5. 构建请求头
headers = {
"x-amz-access-token": "",
"x-amz-lens-session-auth-token": cookies.get("session-token", ""),
"x-amz-lens-session-id": session_id,
"x-amz-lens-ubid": cookies.get("ubid-main", ""),
"accept-encoding": "gzip",
"user-agent": "okhttp/4.9.1"
}
# 6. 构建表单数据
files = [
("application", (None, APPLICATION, "multipart/form-data; charset=utf-8")),
("query_metadata", (None, query_metadata, "multipart/form-data; charset=utf-8")),
("authtoken", (None, authtoken, "multipart/form-data; charset=utf-8")),
("lang", (None, "en_US", "multipart/form-data; charset=utf-8")),
("username", (None, USERNAME, "multipart/form-data; charset=utf-8")),
("ts", (None, ts, "multipart/form-data; charset=utf-8")),
("file", ("", image_data, "image/jpeg"))
]
# 7. 发送请求
logger.info("发送POST请求到亚马逊以图搜物接口")
response = requests.post(
url=AMAZON_STYLE_SNAP_URL,
headers=headers,
files=files,
cookies=cookies,
timeout=10 # 10秒超时
)
response.raise_for_status() # 抛出HTTP错误状态码
logger.info(f"请求成功,状态码: {response.status_code}")
# 8. 解析响应
try:
response_json = response.json()
# logger.debug(f"响应数据: {str(response_json)[:100]}...") # 打印前100字符
except ValueError:
logger.error("响应不是有效的JSON格式", exc_info=True)
if retry < RETRY_TIMES - 1:
logger.info(f"等待 {RETRY_DELAY} 秒后重试...")
time.sleep(RETRY_DELAY)
continue
return None
# 9. 提取bbxAsinList
try:
search_result = response_json.get("style-snap", {}).get("searchResult", [])
if not search_result:
logger.warning("searchResult列表为空")
return None
first_result = search_result[0]
bbx_asin_list = first_result.get("bbxAsinList", [])
if not bbx_asin_list:
logger.warning("bbxAsinList列表为空")
return None
logger.info(f"成功提取bbxAsinList,共 {len(bbx_asin_list)} 个元素,注意 实际有些不可用 打开网页数据少几个为正常现象")
joined_asin = "|".join(bbx_asin_list)
final_url = AMAZON_SEARCH_BASE_URL.format(bbx_asin_list=joined_asin)
logger.success(f"生成最终搜索URL: {final_url}")
return final_url
except (IndexError, KeyError) as e:
logger.error(f"解析响应结构失败: {str(e)}", exc_info=True)
if retry < RETRY_TIMES - 1:
logger.info(f"等待 {RETRY_DELAY} 秒后重试...")
time.sleep(RETRY_DELAY)
continue
return None
except (ConnectionError, Timeout) as e:
logger.error(f"网络错误: {str(e)}", exc_info=True)
except RequestException as e:
# 处理HTTP错误(如401/403可能是cookie过期)
status_code = getattr(e.response, "status_code", None)
logger.error(f"请求异常 (状态码: {status_code}): {str(e)}", exc_info=True)
# 401/403 通常是认证失效,直接终止重试(需要更新cookie)
if status_code in (401, 403):
logger.warning("检测到认证失效,终止重试")
return None
except Exception as e:
logger.error(f"未知错误: {str(e)}", exc_info=True)
# 重试前等待
if retry < RETRY_TIMES - 1:
logger.info(f"等待 {RETRY_DELAY} 秒后重试...")
time.sleep(RETRY_DELAY)
logger.error(f"经过 {RETRY_TIMES} 次重试后仍失败")
return None
if __name__ == "__main__":
sample_cookies = {"i18n-prefs": "USD", "lc-main": "en_US", "session-id": "131-0347800-4175077", "session-id-time": "2082787201l", "session-token": "Jo+AthxsQrcFH8qeii+sHhoo7puFd/cpJUEsjnWXtCLhr8ycF9TQSAv9zuyoAvFjfmXZuACFNa/D+i5et63EafMMPDK/825m8TUtNtlO88KmmEsm94fiyoPL0UakTyZsUBv/CzndcKB7h0K3NkbeFws9gZSdwYRGJFVeX+pPQ9ceN0WkE+XLwCt0plIIxG3BC+VtdFJWxPKxH+R5dlnbtxPso2S5zlrOf1FTEdGNNhNZvVq25XeydshrSp7AKG6VUOicnipgfAY0Qle3Y4bw72N1IqY9i3rXVZlkrkGePamBxew+Vel7U8ccVsEIT/vtOtLHPfsTljTgltlJU0bzk0YeoJ1LwI9S", "skin": "noskin", "ubid-main": "134-9889499-1876667"}
# 调用函数
result_url = get_amazon_search_url("test_image/amazon3.png", sample_cookies)
if result_url:
logger.success(f"最终搜索URL: {result_url}")
else:
logger.error("未能生成搜索URL")
\ No newline at end of file
import hashlib
import os
import time
import uuid
import random
......@@ -18,11 +19,18 @@ from amazon_configs import (
uk_cookie_dict,
de_cookie_dict
)
# 日志目录配置
# LOG_DIR = "log" # 日志文件夹名称
# 关键新增:判断日志目录是否存在,不存在则创建
# if not os.path.exists(LOG_DIR):
# os.makedirs(LOG_DIR, exist_ok=True) # exist_ok=True 避免目录已存在时报错
# 配置日志
# logger.add("amazon_search_optimized.log", rotation="10 MB", level="INFO")
# logger.add("log/amazon_search_optimized.log", rotation="10 MB", level="INFO", encoding="utf-8")
# log_file = os.path.join(LOG_DIR, "amazon_search_optimized.log")
# logger.add(log_file,rotation="10 MB", level="INFO",encoding="utf-8")
# 站点配置映射(关联设备列表和Cookie)
# 站点配置映射(关联设备列表和Cookie) uk 和de 未测试准确性
SITE_CONFIG_MAPPER = {
"us": {
"devices": us_devices_list,
......@@ -41,9 +49,10 @@ SITE_CONFIG_MAPPER = {
# asin 网页端打开 url
AMAZON_SEARCH_BASE_URL = "https://www.amazon.com/s?rh=p_78:{bbx_asin_list}&rank=asin-scores-asc-rank&searchMethod=CameraSearch"
# 重试策略配置
RETRY_TIMES = 5
RETRY_DELAY = 1
# 重试策略配置(全局重试次数,包含解析失败)
GLOBAL_RETRY_TIMES = 5 # 整体流程重试次数(含Cookie更新)
STEP_RETRY_TIMES = 5 # 单步请求重试次数
RETRY_DELAY = 1 # 重试延迟(秒)
def get_image_size(image_path: str) -> Optional[Dict[str, int]]:
......@@ -62,6 +71,9 @@ def get_image_size(image_path: str) -> Optional[Dict[str, int]]:
class AmazonImageSearch:
def __init__(self, site_name: str):
'''
:param site_name: 站点名 如 uk us de
'''
# 验证站点合法性
if site_name not in site_name_secret_dict:
raise ValueError(f"不支持的站点: {site_name},支持站点:{list(site_name_secret_dict.keys())}")
......@@ -69,16 +81,12 @@ class AmazonImageSearch:
raise ValueError(f"站点 {site_name} 缺少设备或Cookie配置")
self.site_name = site_name
# 加载站点基础配置(secret等)
self.site_config = site_name_secret_dict[site_name]
# 加载站点设备列表和Cookie
self.site_specific = SITE_CONFIG_MAPPER[site_name]
self.cookies = self.site_specific["cookies"]
self.session_id = self.cookies.get("session-id",'')
# 从站点设备列表随机选择一个设备(用于query_metadata)
self.device_info = self._get_random_device()
# 生成客户端设备ID
# 初始化Cookie和设备信息
self._update_cookie() # 初始加载Cookie
self._update_device() # 初始加载设备
self.client_device_id = str(uuid.uuid4())
logger.info(
......@@ -87,7 +95,27 @@ class AmazonImageSearch:
f"clientDeviceId: {self.client_device_id}"
)
# 构建请求头
# 构建请求头(依赖Cookie,初始化时生成)
self._update_headers()
self.snap_url = f"{self.site_config['snap_url']}/style-snap/2.0"
def _update_cookie(self) -> None:
"""更新Cookie(当前固定返回站点对应Cookie,后续可扩展为从数据库读取)"""
self.cookies = self.site_specific["cookies"].copy() # 复制一份避免修改原配置
self.session_id = self.cookies.get("session-id", "")
logger.info(f"站点 {self.site_name} Cookie已更新(session-id: {self.session_id[:20]}...)")
def _update_device(self) -> None:
"""更新随机设备信息"""
devices = self.site_specific["devices"]
if not devices:
raise ValueError(f"站点 {self.site_name} 的设备列表为空")
self.device_info = random.choice(devices)
logger.debug(f"设备已更新: {self.device_info.get('clientDevice')}")
def _update_headers(self) -> None:
"""更新请求头(依赖Cookie,Cookie变更后需重新生成)"""
self.headers = {
"x-amz-access-token": "",
"x-amz-lens-session-auth-token": self.cookies.get("session-token", ""),
......@@ -97,15 +125,6 @@ class AmazonImageSearch:
"user-agent": "okhttp/4.9.1",
}
self.snap_url = f"{self.site_config['snap_url']}/style-snap/2.0"
def _get_random_device(self) -> Dict[str, str]:
"""从站点设备列表中随机选择一个设备"""
devices = self.site_specific["devices"]
if not devices:
raise ValueError(f"站点 {self.site_name} 的设备列表为空")
return random.choice(devices)
def _generate_auth_params(self) -> Dict[str, str]:
"""生成认证所需的 authtoken 和 ts"""
ts = str(int(time.time()))
......@@ -137,8 +156,16 @@ class AmazonImageSearch:
return json.dumps(base_params)
def _parse_response(self, response_json: Dict[str, Any]) -> Optional[Dict[str, Any]]:
"""从API响应中解析ASIN列表并构建结果"""
"""从API响应中解析ASIN列表并构建结果,缺失关键字段视为解析失败"""
try:
# 严格检查必须存在的字段
if "style-snap" not in response_json:
raise KeyError("响应缺少 'style-snap' 字段")
if "searchResult" not in response_json["style-snap"]:
raise KeyError("响应缺少 'style-snap.searchResult' 字段")
if not response_json["style-snap"]["searchResult"]:
raise IndexError("'searchResult' 列表为空")
search_result = response_json["style-snap"]["searchResult"][0]
bbx_asin_list = search_result.get("bbxAsinList", [])
......@@ -155,31 +182,30 @@ class AmazonImageSearch:
"search_url": AMAZON_SEARCH_BASE_URL.format(bbx_asin_list=joined_asins),
}
except (KeyError, IndexError, TypeError) as e:
logger.error(f"解析响应失败: {e}. 响应内容: {response_json}")
return None
logger.error(f"解析响应失败: {e}. 响应内容: {json.dumps(response_json, ensure_ascii=False)}...")
return None # 返回None表示解析失败,触发重试
def _perform_request(self, **kwargs) -> Dict[str, Any]:
"""统一的请求发送方法,包含重试逻辑"""
for attempt in range(RETRY_TIMES):
"""单步请求的重试逻辑(不更新Cookie,仅处理网络错误)"""
for attempt in range(STEP_RETRY_TIMES):
try:
response = requests.post(**kwargs, timeout=10)
response.raise_for_status() # 对非2xx响应抛出HTTPError
return response.json()
except JSONDecodeError:
logger.error(f"请求失败 (第 {attempt + 1}/{RETRY_TIMES} 次): 响应不是有效的JSON格式。")
logger.error(f"请求失败 (第 {attempt + 1}/{STEP_RETRY_TIMES} 次): 响应不是有效的JSON格式")
except RequestException as e:
logger.error(f"请求失败 (第 {attempt + 1}/{RETRY_TIMES} 次): {e}")
logger.error(f"请求失败 (第 {attempt + 1}/{STEP_RETRY_TIMES} 次): {e}")
if attempt < RETRY_TIMES - 1:
if attempt < STEP_RETRY_TIMES - 1:
logger.warning(f"将在 {RETRY_DELAY} 秒后重试...")
time.sleep(RETRY_DELAY)
raise RequestException(f"API请求在 {RETRY_TIMES} 次尝试后最终失败。")
raise RequestException(f"单步API请求在 {STEP_RETRY_TIMES} 次尝试后最终失败")
def _default_search(self, image_path: str) -> Dict[str, Any]:
"""执行默认的图片识别请求(第一步)"""
logger.info(f"开始默认识别 (站点: {self.site_name}, 图片: {image_path}),站点链接:{self.snap_url}")
logger.info(f"开始默认识别 (站点: {self.site_name}, 图片: {image_path}), 站点链接:{self.snap_url}")
try:
with open(image_path, "rb") as f:
......@@ -189,18 +215,18 @@ class AmazonImageSearch:
raise
auth_params = self._generate_auth_params()
query_metadata = self._build_query_metadata({"orientation": "-1"}) # 默认图片搜索 额外传 orientation
query_metadata = self._build_query_metadata({"orientation": "-1"})
files = {
"application": (None, self.site_config['application']),
"query_metadata": (None, query_metadata),
"authtoken": (None, auth_params['authtoken']),
# "authtoken": (None, ''), # 为空失请求失败 测试重试功能
"lang": (None, "en_US"),
"username": (None, self.site_config['username']),
"ts": (None, auth_params['ts']),
"file": ("image.jpg", image_data, "image/jpeg"),
}
return self._perform_request(url=self.snap_url, files=files, headers=self.headers)
def _full_image_search(self, query_id: str, image_path: str) -> Dict[str, Any]:
......@@ -209,7 +235,7 @@ class AmazonImageSearch:
image_size = get_image_size(image_path)
if not image_size:
raise ValueError("无法获取图片尺寸,无法进行全图搜索")
raise ValueError("无法获取图片尺寸,无法进行全图搜索")
# 生成随机裁剪框
offset = random.randint(0, 2)
......@@ -242,55 +268,81 @@ class AmazonImageSearch:
def search(self, image_path: str, search_mode: str = "default") -> Dict[str, Any]:
"""
执行图片搜索
执行图片搜索(包含全局重试逻辑,解析失败时更新Cookie重试)
:param image_path: 本地图片文件路径
:param search_mode: 搜索模式 ('default' 或 'full_image')
:return: 包含搜索结果的字典
"""
# 默认的返回值字典
base_result = {
"is_web": 0, "is_app": 0, "asin_list_web": "", "asin_list_app": "",
"asin_list_join": "", "site_name": self.site_name,
"search_url": None, "mode": search_mode
"search_url": None, "mode": search_mode,
"retry_count": 0 # 记录重试次数
}
if not self.session_id:
logger.error("Cookies中缺少'session-id',无法继续。")
return base_result
try:
# 步骤 1: 执行默认搜索(全图模式需依赖此步骤的query_id)
default_response = self._default_search(image_path) # 得到首次以图搜物响应
# 处理默认模式结果
if search_mode == "default":
parsed_result = self._parse_response(default_response)
if parsed_result:
base_result.update(parsed_result) # 更新返回值
base_result["asin_list_join"] = parsed_result["asin_list_app"]
return base_result
# 处理全图模式结果
elif search_mode == "full_image":
query_id = default_response.get("queryId")
if not query_id:
logger.error("默认识别未返回 queryId,无法进行全图搜索。")
# 全局重试逻辑(包含Cookie更新)
for global_attempt in range(GLOBAL_RETRY_TIMES):
try:
# 检查Cookie有效性(每次重试前确认)
if not self.session_id:
logger.warning("Cookie中缺少'session-id',尝试更新Cookie...")
self._update_cookie()
self._update_headers() # 同步更新请求头
# 步骤1: 执行默认搜索(全图模式依赖此步骤的query_id)
default_response = self._default_search(image_path)
# 处理默认模式
if search_mode == "default":
parsed_result = self._parse_response(default_response)
if parsed_result: # 解析成功才返回
base_result.update(parsed_result)
base_result["asin_list_join"] = parsed_result["asin_list_app"]
base_result["retry_count"] = global_attempt
return base_result
else:
# 解析失败,准备重试
raise ValueError("默认模式响应解析失败,触发重试")
# 处理全图模式
elif search_mode == "full_image":
query_id = default_response.get("queryId")
if not query_id:
raise ValueError("默认识别未返回queryId,无法进行全图搜索")
full_image_response = self._full_image_search(query_id, image_path)
parsed_result = self._parse_response(full_image_response)
if parsed_result: # 解析成功才返回
base_result.update(parsed_result)
base_result["asin_list_join"] = parsed_result["asin_list_app"]
base_result["retry_count"] = global_attempt
return base_result
else:
# 解析失败,准备重试
raise ValueError("全图模式响应解析失败,触发重试")
else:
logger.error(f"不支持的搜索模式: {search_mode}")
return base_result
full_image_response = self._full_image_search(query_id, image_path) # 带上queryId 第二次请求 获取全图识别结果
parsed_result = self._parse_response(full_image_response)
if parsed_result:
base_result.update(parsed_result)
base_result["asin_list_join"] = parsed_result["asin_list_app"]
return base_result
except Exception as e:
logger.error(f"第 {global_attempt + 1}/{GLOBAL_RETRY_TIMES} 次尝试失败: {e}")
else:
logger.error(f"不支持的搜索模式: {search_mode}")
return base_result
# 最后一次重试失败则返回基础结果
if global_attempt == GLOBAL_RETRY_TIMES - 1:
base_result["error"] = str(e)
return base_result
# 非最后一次重试:更新Cookie和设备,延迟后重试
logger.info("准备更新Cookie和设备信息后重试...")
self._update_cookie() # 更新Cookie(当前固定站点Cookie,后续可从数据库读取)
self._update_device() # 更新设备信息
self._update_headers() # 同步更新请求头
self.client_device_id = str(uuid.uuid4()) # 更新客户端ID
logger.info(f"重试准备完成(下次是第 {global_attempt + 2} 次尝试)")
time.sleep(RETRY_DELAY)
except Exception as e:
logger.error(f"处理 '{search_mode}' 模式搜索时发生异常: {e}")
return base_result
return base_result
if __name__ == "__main__":
......@@ -298,20 +350,22 @@ if __name__ == "__main__":
image_file_path = "temp_img/B0BYNB2J6W.jpg"
try:
# 测试不同站点(如"us"、"uk"、"de")
for site in ["us", "uk", "de"]:
logger.info(f"\n{'=' * 20} 测试站点: {site} {'=' * 20}")
# 测试不同站点
for site in ["us","uk","de"]:
logger.info(f"\n{'=' * 40}")
logger.info(f"开始测试站点: {site}")
logger.info(f"{'=' * 40}")
client = AmazonImageSearch(site_name=site)
# 测试默认识别模式
logger.info("\n--- 默认识别模式 ---")
logger.info("\n--- 测试默认识别模式 ---")
default_result = client.search(image_file_path, search_mode="default")
logger.info(f"结果: {default_result}")
logger.info(f"默认模式结果: {json.dumps(default_result, ensure_ascii=False, indent=2)}")
# 测试全图识别模式
logger.info("\n--- 全图识别模式 ---")
# # 测试全图识别模式
logger.info("\n--- 测试全图识别模式 ---")
full_image_result = client.search(image_file_path, search_mode="full_image")
logger.info(f"结果: {full_image_result}")
logger.info(f"全图模式结果: {json.dumps(full_image_result, ensure_ascii=False, indent=2)}")
except ValueError as e:
logger.error(f"初始化失败: {e}")
......
......@@ -2,209 +2,267 @@ import os
import time
import threading
import queue
import csv
import random
import json
from datetime import datetime
from typing import List, Dict, Tuple
import app_amazon_image_recognition as amazon_recog
from typing import List, Dict
from loguru import logger
import pandas as pd
from app_img_search_api_new import AmazonImageSearch # 导入客户端类
from amazon_configs import (
site_name_secret_dict,
us_devices_list,
uk_devices_list,
de_devices_list
)
# 日志目录配置
LOG_DIR = "log" # 日志文件夹名称
# 判断日志目录是否存在,不存在则创建
if not os.path.exists(LOG_DIR):
os.makedirs(LOG_DIR, exist_ok=True) # exist_ok=True 避免目录已存在时报错
# 测试配置
TEST_FOLDER = "temp_img" # 图片文件夹路径
REQUESTS_PER_IMAGE = 1 # 每张图片请求次数
THREAD_COUNT = 10 # 线程数量
RESULT_CSV = "test_results.csv" # 结果保存文件
# 线程安全的队列用于分发任务
REQUESTS_PER_IMAGE = 1 # 每张图片每个站点的请求次数(每种模式各执行一次)
THREAD_COUNT = 30 # 线程数量
RESULT_EXCEL = "multi_mode_test_results3.xlsx" # 结果保存文件
ALL_SITES = ["us", "uk", "de"] # 要测试的三个站点
ALL_MODES = ["default", "full_image"] # 两种搜索模式
# 站点设备列表映射
SITE_DEVICES = {
"us": us_devices_list,
"uk": uk_devices_list,
"de": de_devices_list
}
# 线程安全组件
task_queue = queue.Queue()
# 结果存储(线程安全)
result_lock = threading.Lock()
test_results = []
def worker(cookies: dict):
"""线程工作函数,处理队列中的任务"""
thread_name = threading.current_thread().name # 获取线程名称(如Worker-1)
def worker():
"""线程工作函数:先执行默认模式,再执行全图模式,记录两种模式结果"""
thread_id = threading.current_thread().ident
thread_name = threading.current_thread().name
while not task_queue.empty():
try:
# # 从队列获取任务(图片路径+当前请求序号),非阻塞模式
image_path, request_idx = task_queue.get(block=False)
# 从队列获取任务:图片路径、请求序号、站点
image_path, request_idx, site_name = task_queue.get(block=False)
image_name = os.path.basename(image_path)
start_time = time.time()
start_datetime = datetime.now()
# 打印开始请求的日志(关键:展示线程、图片、序号)
logger.info(f"[{thread_name}] 开始处理 {image_name} 第 {request_idx} 次请求")
# 执行请求 传入cookies.copy()避免多线程共享同一字典导致的修改冲突
result_url = amazon_recog.get_amazon_search_url(image_path, cookies.copy())
# 计算耗时
end_time = time.time()
duration = end_time - start_time
# 标记请求是否成功(1=成功,0=失败)
success = 1 if result_url else 0
# 记录结果
with result_lock:
test_results.append({
"thread_name": thread_name, # 记录线程名
"image": image_name, # 图片文件名
"request_index": request_idx, # 第几次请求(1到1000)
"start_time": start_datetime.strftime("%Y-%m-%d %H:%M:%S.%f"), # 开始时间
"duration": round(duration, 4), # 耗时 保留4位小数)
"success": success, # 是否成功
"result_url": result_url if success else "None", # 成功时的URL,失败为None
"thread_id": threading.current_thread().ident # 处理线程ID
})
# 每完成100次请求打印进度
if request_idx % 100 == 0:
logger.info(f"图片 {os.path.basename(image_path)} 完成第 {request_idx} 次请求,耗时 {duration:.2f}s")
logger.info(
f"[{thread_name}] 开始处理 {image_name} 第 {request_idx} 次请求 "
f"(站点:{site_name},两种模式)"
)
# 初始化客户端(同一客户端实例,确保设备信息一致)
client = AmazonImageSearch(site_name=site_name)
device_info = client.device_info # 获取设备信息(两种模式共用)
device_str = (
f"设备: {device_info.get('clientDevice')}, "
f"厂商: {device_info.get('deviceManufacturer')}, "
f"系统版本: {device_info.get('clientDeviceVersion')}"
)
logger.debug(f"[{thread_name}] {device_str}")
# 依次执行两种模式
for mode in ALL_MODES:
try:
# 记录单次模式开始时间
mode_start = time.time()
# 执行对应模式的搜索
result_data = client.search(
image_path=image_path,
search_mode=mode
)
# 计算单次模式耗时
duration = round(time.time() - mode_start, 4)
save_time = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
# 锁定并保存结果(保持原有数据格式,新增mode字段)
with result_lock:
test_results.append({
"image": image_name,
"request_index": request_idx, # 同一请求序号关联两种模式
"mode": mode, # 新增:标记当前模式
"duration": duration,
"success": result_data.get("is_app", 0),
"result_url": result_data.get("search_url", "None"),
"thread_id": thread_id,
"is_web": result_data.get("is_web", 0),
"is_app": result_data.get("is_app", 0),
"asin_list_web": result_data.get("asin_list_web", ""),
"asin_list_app": result_data.get("asin_list_app", ""),
"asin_list_join": result_data.get("asin_list_join", ""),
"site_name": site_name,
"device_info": json.dumps(device_info, ensure_ascii=False),
# "device_summary": f"{device_info.get('clientDevice')} ({device_info.get('clientDeviceVersion')})",
"save_time": save_time
})
logger.info(f"[{thread_name}] {mode}模式完成(耗时{duration}秒)")
except Exception as e:
logger.error(f"[{thread_name}] {mode}模式处理出错: {str(e)}")
# 记录模式失败结果
with result_lock:
test_results.append({
"image": image_name,
"request_index": request_idx,
"mode": mode,
"duration": 0,
"success": 0,
"result_url": "None",
"thread_id": thread_id,
"is_web": 0,
"is_app": 0,
"asin_list_web": "",
"asin_list_app": "",
"asin_list_join": "",
"site_name": site_name,
"device_info": json.dumps(device_info, ensure_ascii=False),
# "device_summary": f"{device_info.get('clientDevice')} ({device_info.get('clientDeviceVersion')})",
"save_time": datetime.now().strftime("%Y-%m-%d %H:%M:%S"),
# "error": str(e)
})
except queue.Empty:
# 队列已空,退出循环
break
except Exception as e:
logger.error(f"线程处理出错: {str(e)}")
logger.error(f"[{thread_name}] 整体任务出错: {str(e)}")
finally:
# 队列已空,退出循环
task_queue.task_done()
def load_test_cookies() -> dict:
"""加载测试用的cookies"""
return {
"i18n-prefs": "USD",
"lc-main": "en_US",
"session-id": "131-0347800-4175077",
"session-id-time": "2082787201l",
"session-token": "Jo+AthxsQrcFH8qeii+sHhoo7puFd/cpJUEsjnWXtCLhr8ycF9TQSAv9zuyoAvFjfmXZuACFNa/D+i5et63EafMMPDK/825m8TUtNtlO88KmmEsm94fiyoPL0UakTyZsUBv/CzndcKB7h0K3NkbeFws9gZSdwYRGJFVeX+pPQ9ceN0WkE+XLwCt0plIIxG3BC+VtdFJWxPKxH+R5dlnbtxPso2S5zlrOf1FTEdGNNhNZvVq25XeydshrSp7AKG6VUOicnipgfAY0Qle3Y4bw72N1IqY9i3rXVZlkrkGePamBxew+Vel7U8ccVsEIT/vtOtLHPfsTljTgltlJU0bzk0YeoJ1LwI9S",
"skin": "noskin",
"ubid-main": "134-9889499-1876667"
}
def collect_image_paths(folder: str) -> List[str]:
"""收集文件夹中的所有图片路径"""
"""收集文件夹中的图片路径(仅支持常见图片格式)"""
image_extensions = ('.png', '.jpg', '.jpeg', '.gif', '.bmp')
if not os.path.exists(folder):
logger.error(f"图片文件夹不存在: {folder}")
return []
image_paths = [
return [
os.path.join(folder, f)
for f in os.listdir(folder)
if f.lower().endswith(image_extensions)
]
logger.info(f"发现 {len(image_paths)} 张图片: {[os.path.basename(p) for p in image_paths]}")
return image_paths
COLLECT_IMAGE_PATHS = collect_image_paths
def init_task_queue(image_paths: List[str]):
"""初始化任务队列 将每张图片的N次请求加入队列"""
# for image_path in image_paths:
# for i in range(1, REQUESTS_PER_IMAGE + 1):
# task_queue.put((image_path, i)) # 每个任务是(图片路径,请求序号)
# 轮询交替放任务(每张图片交替入队)
for request_idx in range(1, REQUESTS_PER_IMAGE + 1):
for image_path in image_paths:
task_queue.put((image_path, request_idx))
logger.info(f"任务队列初始化完成,总任务数: {task_queue.qsize()}")
def save_results_to_csv(results: List[Dict], filename: str):
"""将结果保存到CSV文件"""
"""初始化任务队列:包含所有站点、所有图片、所有请求次数(一次任务对应两种模式)"""
for site in ALL_SITES:
for request_idx in range(1, REQUESTS_PER_IMAGE + 1):
for image_path in image_paths:
task_queue.put((image_path, request_idx, site))
total_tasks = task_queue.qsize()
logger.info(
f"任务队列初始化完成 - 总任务数: {total_tasks} "
f"(每个任务包含{len(ALL_MODES)}种模式),"
f"站点数: {len(ALL_SITES)}, 图片数: {len(image_paths)}, "
f"单图单站请求数: {REQUESTS_PER_IMAGE}"
)
def save_results_to_excel(results: List[Dict]):
"""将结果写入Excel,新增mode字段区分模式"""
if not results:
logger.warning("没有结果可保存")
logger.warning("结果可保存")
return
with open(filename, 'w', newline='', encoding='utf-8') as f:
# 以结果列表中第一个字典的键作为CSV表头
fieldnames = results[0].keys()
writer = csv.DictWriter(f, fieldnames=fieldnames)
# 转换为DataFrame,确保字段顺序(新增mode字段)
df = pd.DataFrame(results)[[
"image", "request_index", "mode", "duration", "success", "result_url",
"thread_id", "is_web", "is_app", "asin_list_web", "asin_list_app",
"asin_list_join", "site_name", "device_info", "save_time"
]]
writer.writeheader()
for row in results:
writer.writerow(row) # 写入每行数据
# 保存到Excel
df.to_excel(RESULT_EXCEL, index=False, engine="openpyxl")
logger.info(f"结果已保存到 {RESULT_EXCEL}")
with open(RESULT_CSV, 'w', newline='', encoding='utf-8') as f:
writer = csv.DictWriter(f, fieldnames=test_results[0].keys())
writer.writeheader()
writer.writerows(test_results)
logger.info(f"结果已保存到 {RESULT_CSV}")
def print_summary(results: List[Dict]):
"""打印测试总结(成功率、耗时等关键指标)"""
"""打印测试总结(按站点和模式分组统计)"""
if not results:
return
total = len(results)
success = sum(1 for r in test_results if r["success"])
logger.info(f"\n===== 测试总结 =====")
logger.info(f"总请求: {total},成功: {success},成功率: {success/total*100:.2f}%")
# 按图片分组统计 (每张图片的单独表现)
image_stats = {}
for r in results:
img = r["image"]
if img not in image_stats:
image_stats[img] = {"total": 0, "success": 0, "duration": []}
image_stats[img]["total"] += 1
image_stats[img]["success"] += r["success"]
image_stats[img]["duration"].append(r["duration"])
# 按线程统计
thread_stats = {}
for r in test_results:
t = r["thread_name"]
thread_stats[t] = thread_stats.get(t, 0) + 1
logger.info("\n线程任务分配:")
for t, cnt in thread_stats.items():
logger.info(f" {t}: {cnt} 次请求")
def main():
# 初始化日志
logger.add("stability_test.log", rotation="10 MB", level="INFO")
total_duration = sum(r["duration"] for r in results)
logger.info("\n===== 测试总结 =====")
logger.info(f"总请求数: {total}(含{len(ALL_MODES)}种模式),"
f"总耗时: {total_duration:.2f}秒,"
f"平均耗时: {total_duration / total:.4f}秒")
# 按站点分组统计
for site in ALL_SITES:
site_results = [r for r in results if r["site_name"] == site]
site_total = len(site_results)
if site_total == 0:
continue
logger.info(f"\n----- 站点: {site} 统计 -----")
logger.info(f"总请求数: {site_total},平均耗时: {sum(r['duration'] for r in site_results) / site_total:.4f}秒")
# 按模式分组统计
for mode in ALL_MODES:
mode_results = [r for r in site_results if r["mode"] == mode]
mode_total = len(mode_results)
if mode_total == 0:
continue
mode_success = sum(1 for r in mode_results if r["is_app"] == 1)
mode_success_rate = (mode_success / mode_total) * 100 if mode_total else 0
logger.info(
f"模式 {mode}: "
f"请求数 {mode_total}, 成功数 {mode_success}, "
f"成功率 {mode_success_rate:.2f}%, "
f"平均耗时 {sum(r['duration'] for r in mode_results) / mode_total:.4f}秒"
)
# 设备多样性统计
# devices_used = {r["device_summary"] for r in site_results}
# logger.info(f"使用设备种类: {len(devices_used)} 种")
cookies = load_test_cookies()
image_paths = COLLECT_IMAGE_PATHS(TEST_FOLDER)
if not image_paths:
logger.error("没有找到图片,无法进行测试")
return
if __name__ == "__main__":
# 初始化日志
log_file = os.path.join(LOG_DIR, "multi_mode_stability_test.log")
logger.add(log_file,rotation="10 MB",level="INFO",encoding="utf-8")
# 验证所有站点的合法性
for site in ALL_SITES:
if site not in site_name_secret_dict:
logger.error(f"不支持的站点: {site},支持站点: {list(site_name_secret_dict.keys())}")
exit(1)
if not SITE_DEVICES.get(site, []):
logger.warning(f"站点 {site} 的设备列表为空,可能影响测试结果")
# 准备资源
image_paths = collect_image_paths(TEST_FOLDER)
if not image_paths:
logger.error("未找到图片,退出测试")
exit(1)
init_task_queue(image_paths)
# 记录测试开始时间
test_start_time = time.time()
# 创建并启动线程
# 启动多线程
start_time = time.time()
threads = []
for i in range(THREAD_COUNT):
t = threading.Thread(target=worker, args=(cookies,), name=f"Worker-{i + 1}")
t = threading.Thread( target=worker, name=f"Worker-{i + 1}")
threads.append(t)
t.start()
logger.info(f"启动线程: {t.name}")
# 等待所有任务完成
task_queue.join()
# 等待所有线程结束
for t in threads:
t.join()
# 计算总耗时
total_test_time = time.time() - test_start_time
logger.info(f"所有测试完成,总耗时: {total_test_time:.2f}秒")
total_time = time.time() - start_time
logger.info(f"所有任务完成,总耗时: {total_time:.2f}秒")
# 保存结果并打印总结
save_results_to_csv(test_results, RESULT_CSV)
print_summary(test_results)
if __name__ == "__main__":
main()
\ No newline at end of file
save_results_to_excel(test_results)
print_summary(test_results)
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment