Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
S
spider
Overview
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
selection-new
spider
Commits
d7f6ddab
Commit
d7f6ddab
authored
Nov 18, 2025
by
PC-20230618BYKI\Administrator
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
no message
parent
dfdb4f08
Show whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
776 additions
and
372 deletions
+776
-372
amazon_configs.py
...pider_code/app_amazon_image_recognition/amazon_configs.py
+467
-0
app_amazon_image_recognition.py
..._amazon_image_recognition/app_amazon_image_recognition.py
+0
-175
app_img_search_api_new.py
...de/app_amazon_image_recognition/app_img_search_api_new.py
+115
-61
threading_image_demo.py
...code/app_amazon_image_recognition/threading_image_demo.py
+194
-136
No files found.
hjm_spider_code/app_amazon_image_recognition/amazon_configs.py
0 → 100644
View file @
d7f6ddab
# 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"}
hjm_spider_code/app_amazon_image_recognition/app_amazon_image_recognition.py
deleted
100644 → 0
View file @
dfdb4f08
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
hjm_spider_code/app_amazon_image_recognition/app_img_search_api.py
→
hjm_spider_code/app_amazon_image_recognition/app_img_search_api
_new
.py
View file @
d7f6ddab
import
hashlib
import
hashlib
import
os
import
time
import
time
import
uuid
import
uuid
import
random
import
random
...
@@ -18,11 +19,18 @@ from amazon_configs import (
...
@@ -18,11 +19,18 @@ from amazon_configs import (
uk_cookie_dict
,
uk_cookie_dict
,
de_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
=
{
SITE_CONFIG_MAPPER
=
{
"us"
:
{
"us"
:
{
"devices"
:
us_devices_list
,
"devices"
:
us_devices_list
,
...
@@ -41,9 +49,10 @@ SITE_CONFIG_MAPPER = {
...
@@ -41,9 +49,10 @@ SITE_CONFIG_MAPPER = {
# asin 网页端打开 url
# asin 网页端打开 url
AMAZON_SEARCH_BASE_URL
=
"https://www.amazon.com/s?rh=p_78:{bbx_asin_list}&rank=asin-scores-asc-rank&searchMethod=CameraSearch"
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
GLOBAL_RETRY_TIMES
=
5
# 整体流程重试次数(含Cookie更新)
RETRY_DELAY
=
1
STEP_RETRY_TIMES
=
5
# 单步请求重试次数
RETRY_DELAY
=
1
# 重试延迟(秒)
def
get_image_size
(
image_path
:
str
)
->
Optional
[
Dict
[
str
,
int
]]:
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]]:
...
@@ -62,6 +71,9 @@ def get_image_size(image_path: str) -> Optional[Dict[str, int]]:
class
AmazonImageSearch
:
class
AmazonImageSearch
:
def
__init__
(
self
,
site_name
:
str
):
def
__init__
(
self
,
site_name
:
str
):
'''
:param site_name: 站点名 如 uk us de
'''
# 验证站点合法性
# 验证站点合法性
if
site_name
not
in
site_name_secret_dict
:
if
site_name
not
in
site_name_secret_dict
:
raise
ValueError
(
f
"不支持的站点: {site_name},支持站点:{list(site_name_secret_dict.keys())}"
)
raise
ValueError
(
f
"不支持的站点: {site_name},支持站点:{list(site_name_secret_dict.keys())}"
)
...
@@ -69,16 +81,12 @@ class AmazonImageSearch:
...
@@ -69,16 +81,12 @@ class AmazonImageSearch:
raise
ValueError
(
f
"站点 {site_name} 缺少设备或Cookie配置"
)
raise
ValueError
(
f
"站点 {site_name} 缺少设备或Cookie配置"
)
self
.
site_name
=
site_name
self
.
site_name
=
site_name
# 加载站点基础配置(secret等)
self
.
site_config
=
site_name_secret_dict
[
site_name
]
self
.
site_config
=
site_name_secret_dict
[
site_name
]
# 加载站点设备列表和Cookie
self
.
site_specific
=
SITE_CONFIG_MAPPER
[
site_name
]
self
.
site_specific
=
SITE_CONFIG_MAPPER
[
site_name
]
self
.
cookies
=
self
.
site_specific
[
"cookies"
]
self
.
session_id
=
self
.
cookies
.
get
(
"session-id"
,
''
)
#
从站点设备列表随机选择一个设备(用于query_metadata)
#
初始化Cookie和设备信息
self
.
device_info
=
self
.
_get_random_device
()
self
.
_update_cookie
()
# 初始加载Cookie
# 生成客户端设备ID
self
.
_update_device
()
# 初始加载设备
self
.
client_device_id
=
str
(
uuid
.
uuid4
())
self
.
client_device_id
=
str
(
uuid
.
uuid4
())
logger
.
info
(
logger
.
info
(
...
@@ -87,7 +95,27 @@ class AmazonImageSearch:
...
@@ -87,7 +95,27 @@ class AmazonImageSearch:
f
"clientDeviceId: {self.client_device_id}"
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
=
{
self
.
headers
=
{
"x-amz-access-token"
:
""
,
"x-amz-access-token"
:
""
,
"x-amz-lens-session-auth-token"
:
self
.
cookies
.
get
(
"session-token"
,
""
),
"x-amz-lens-session-auth-token"
:
self
.
cookies
.
get
(
"session-token"
,
""
),
...
@@ -97,15 +125,6 @@ class AmazonImageSearch:
...
@@ -97,15 +125,6 @@ class AmazonImageSearch:
"user-agent"
:
"okhttp/4.9.1"
,
"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
]:
def
_generate_auth_params
(
self
)
->
Dict
[
str
,
str
]:
"""生成认证所需的 authtoken 和 ts"""
"""生成认证所需的 authtoken 和 ts"""
ts
=
str
(
int
(
time
.
time
()))
ts
=
str
(
int
(
time
.
time
()))
...
@@ -137,8 +156,16 @@ class AmazonImageSearch:
...
@@ -137,8 +156,16 @@ class AmazonImageSearch:
return
json
.
dumps
(
base_params
)
return
json
.
dumps
(
base_params
)
def
_parse_response
(
self
,
response_json
:
Dict
[
str
,
Any
])
->
Optional
[
Dict
[
str
,
Any
]]:
def
_parse_response
(
self
,
response_json
:
Dict
[
str
,
Any
])
->
Optional
[
Dict
[
str
,
Any
]]:
"""从API响应中解析ASIN列表并构建结果"""
"""从API响应中解析ASIN列表并构建结果
,缺失关键字段视为解析失败
"""
try
:
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
]
search_result
=
response_json
[
"style-snap"
][
"searchResult"
][
0
]
bbx_asin_list
=
search_result
.
get
(
"bbxAsinList"
,
[])
bbx_asin_list
=
search_result
.
get
(
"bbxAsinList"
,
[])
...
@@ -155,31 +182,30 @@ class AmazonImageSearch:
...
@@ -155,31 +182,30 @@ class AmazonImageSearch:
"search_url"
:
AMAZON_SEARCH_BASE_URL
.
format
(
bbx_asin_list
=
joined_asins
),
"search_url"
:
AMAZON_SEARCH_BASE_URL
.
format
(
bbx_asin_list
=
joined_asins
),
}
}
except
(
KeyError
,
IndexError
,
TypeError
)
as
e
:
except
(
KeyError
,
IndexError
,
TypeError
)
as
e
:
logger
.
error
(
f
"解析响应失败: {e}. 响应内容: {
response_json}
"
)
logger
.
error
(
f
"解析响应失败: {e}. 响应内容: {
json.dumps(response_json, ensure_ascii=False)}...
"
)
return
None
return
None
# 返回None表示解析失败,触发重试
def
_perform_request
(
self
,
**
kwargs
)
->
Dict
[
str
,
Any
]:
def
_perform_request
(
self
,
**
kwargs
)
->
Dict
[
str
,
Any
]:
"""
统一的请求发送方法,包含重试逻辑
"""
"""
单步请求的重试逻辑(不更新Cookie,仅处理网络错误)
"""
for
attempt
in
range
(
RETRY_TIMES
):
for
attempt
in
range
(
STEP_
RETRY_TIMES
):
try
:
try
:
response
=
requests
.
post
(
**
kwargs
,
timeout
=
10
)
response
=
requests
.
post
(
**
kwargs
,
timeout
=
10
)
response
.
raise_for_status
()
# 对非2xx响应抛出HTTPError
response
.
raise_for_status
()
# 对非2xx响应抛出HTTPError
return
response
.
json
()
return
response
.
json
()
except
JSONDecodeError
:
except
JSONDecodeError
:
logger
.
error
(
f
"请求失败 (第 {attempt + 1}/{
RETRY_TIMES} 次): 响应不是有效的JSON格式。
"
)
logger
.
error
(
f
"请求失败 (第 {attempt + 1}/{
STEP_RETRY_TIMES} 次): 响应不是有效的JSON格式
"
)
except
RequestException
as
e
:
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} 秒后重试..."
)
logger
.
warning
(
f
"将在 {RETRY_DELAY} 秒后重试..."
)
time
.
sleep
(
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
]:
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
:
try
:
with
open
(
image_path
,
"rb"
)
as
f
:
with
open
(
image_path
,
"rb"
)
as
f
:
...
@@ -189,18 +215,18 @@ class AmazonImageSearch:
...
@@ -189,18 +215,18 @@ class AmazonImageSearch:
raise
raise
auth_params
=
self
.
_generate_auth_params
()
auth_params
=
self
.
_generate_auth_params
()
query_metadata
=
self
.
_build_query_metadata
({
"orientation"
:
"-1"
})
# 默认图片搜索 额外传 orientation
query_metadata
=
self
.
_build_query_metadata
({
"orientation"
:
"-1"
})
files
=
{
files
=
{
"application"
:
(
None
,
self
.
site_config
[
'application'
]),
"application"
:
(
None
,
self
.
site_config
[
'application'
]),
"query_metadata"
:
(
None
,
query_metadata
),
"query_metadata"
:
(
None
,
query_metadata
),
"authtoken"
:
(
None
,
auth_params
[
'authtoken'
]),
"authtoken"
:
(
None
,
auth_params
[
'authtoken'
]),
# "authtoken": (None, ''), # 为空失请求失败 测试重试功能
"lang"
:
(
None
,
"en_US"
),
"lang"
:
(
None
,
"en_US"
),
"username"
:
(
None
,
self
.
site_config
[
'username'
]),
"username"
:
(
None
,
self
.
site_config
[
'username'
]),
"ts"
:
(
None
,
auth_params
[
'ts'
]),
"ts"
:
(
None
,
auth_params
[
'ts'
]),
"file"
:
(
"image.jpg"
,
image_data
,
"image/jpeg"
),
"file"
:
(
"image.jpg"
,
image_data
,
"image/jpeg"
),
}
}
return
self
.
_perform_request
(
url
=
self
.
snap_url
,
files
=
files
,
headers
=
self
.
headers
)
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
]:
def
_full_image_search
(
self
,
query_id
:
str
,
image_path
:
str
)
->
Dict
[
str
,
Any
]:
...
@@ -209,7 +235,7 @@ class AmazonImageSearch:
...
@@ -209,7 +235,7 @@ class AmazonImageSearch:
image_size
=
get_image_size
(
image_path
)
image_size
=
get_image_size
(
image_path
)
if
not
image_size
:
if
not
image_size
:
raise
ValueError
(
"无法获取图片尺寸,无法进行全图搜索
。
"
)
raise
ValueError
(
"无法获取图片尺寸,无法进行全图搜索"
)
# 生成随机裁剪框
# 生成随机裁剪框
offset
=
random
.
randint
(
0
,
2
)
offset
=
random
.
randint
(
0
,
2
)
...
@@ -242,54 +268,80 @@ class AmazonImageSearch:
...
@@ -242,54 +268,80 @@ class AmazonImageSearch:
def
search
(
self
,
image_path
:
str
,
search_mode
:
str
=
"default"
)
->
Dict
[
str
,
Any
]:
def
search
(
self
,
image_path
:
str
,
search_mode
:
str
=
"default"
)
->
Dict
[
str
,
Any
]:
"""
"""
执行图片搜索
执行图片搜索
(包含全局重试逻辑,解析失败时更新Cookie重试)
:param image_path: 本地图片文件路径
:param image_path: 本地图片文件路径
:param search_mode: 搜索模式 ('default' 或 'full_image')
:param search_mode: 搜索模式 ('default' 或 'full_image')
:return: 包含搜索结果的字典
:return: 包含搜索结果的字典
"""
"""
# 默认的返回值字典
base_result
=
{
base_result
=
{
"is_web"
:
0
,
"is_app"
:
0
,
"asin_list_web"
:
""
,
"asin_list_app"
:
""
,
"is_web"
:
0
,
"is_app"
:
0
,
"asin_list_web"
:
""
,
"asin_list_app"
:
""
,
"asin_list_join"
:
""
,
"site_name"
:
self
.
site_name
,
"asin_list_join"
:
""
,
"site_name"
:
self
.
site_name
,
"search_url"
:
None
,
"mode"
:
search_mode
"search_url"
:
None
,
"mode"
:
search_mode
,
"retry_count"
:
0
# 记录重试次数
}
}
# 全局重试逻辑(包含Cookie更新)
for
global_attempt
in
range
(
GLOBAL_RETRY_TIMES
):
try
:
# 检查Cookie有效性(每次重试前确认)
if
not
self
.
session_id
:
if
not
self
.
session_id
:
logger
.
error
(
"Cookies中缺少'session-id',无法继续。"
)
logger
.
warning
(
"Cookie中缺少'session-id',尝试更新Cookie..."
)
return
base_result
self
.
_update_cookie
()
self
.
_update_headers
()
# 同步更新请求头
try
:
# 步骤1: 执行默认搜索(全图模式依赖此步骤的query_id)
# 步骤 1: 执行默认搜索(全图模式需依赖此步骤的query_id)
default_response
=
self
.
_default_search
(
image_path
)
default_response
=
self
.
_default_search
(
image_path
)
# 得到首次以图搜物响应
# 处理默认模式结果
# 处理默认模式
if
search_mode
==
"default"
:
if
search_mode
==
"default"
:
parsed_result
=
self
.
_parse_response
(
default_response
)
parsed_result
=
self
.
_parse_response
(
default_response
)
if
parsed_result
:
if
parsed_result
:
# 解析成功才返回
base_result
.
update
(
parsed_result
)
# 更新返回值
base_result
.
update
(
parsed_result
)
base_result
[
"asin_list_join"
]
=
parsed_result
[
"asin_list_app"
]
base_result
[
"asin_list_join"
]
=
parsed_result
[
"asin_list_app"
]
base_result
[
"retry_count"
]
=
global_attempt
return
base_result
return
base_result
else
:
# 解析失败,准备重试
raise
ValueError
(
"默认模式响应解析失败,触发重试"
)
# 处理全图模式结果
# 处理全图模式
elif
search_mode
==
"full_image"
:
elif
search_mode
==
"full_image"
:
query_id
=
default_response
.
get
(
"queryId"
)
query_id
=
default_response
.
get
(
"queryId"
)
if
not
query_id
:
if
not
query_id
:
logger
.
error
(
"默认识别未返回 queryId,无法进行全图搜索。"
)
raise
ValueError
(
"默认识别未返回queryId,无法进行全图搜索"
)
return
base_result
full_image_response
=
self
.
_full_image_search
(
query_id
,
image_path
)
# 带上queryId 第二次请求 获取全图识别结果
full_image_response
=
self
.
_full_image_search
(
query_id
,
image_path
)
parsed_result
=
self
.
_parse_response
(
full_image_response
)
parsed_result
=
self
.
_parse_response
(
full_image_response
)
if
parsed_result
:
if
parsed_result
:
# 解析成功才返回
base_result
.
update
(
parsed_result
)
base_result
.
update
(
parsed_result
)
base_result
[
"asin_list_join"
]
=
parsed_result
[
"asin_list_app"
]
base_result
[
"asin_list_join"
]
=
parsed_result
[
"asin_list_app"
]
base_result
[
"retry_count"
]
=
global_attempt
return
base_result
return
base_result
else
:
# 解析失败,准备重试
raise
ValueError
(
"全图模式响应解析失败,触发重试"
)
else
:
else
:
logger
.
error
(
f
"不支持的搜索模式: {search_mode}"
)
logger
.
error
(
f
"不支持的搜索模式: {search_mode}"
)
return
base_result
return
base_result
except
Exception
as
e
:
except
Exception
as
e
:
logger
.
error
(
f
"处理 '{search_mode}' 模式搜索时发生异常: {e}"
)
logger
.
error
(
f
"第 {global_attempt + 1}/{GLOBAL_RETRY_TIMES} 次尝试失败: {e}"
)
# 最后一次重试失败则返回基础结果
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
)
return
base_result
return
base_result
...
@@ -298,20 +350,22 @@ if __name__ == "__main__":
...
@@ -298,20 +350,22 @@ if __name__ == "__main__":
image_file_path
=
"temp_img/B0BYNB2J6W.jpg"
image_file_path
=
"temp_img/B0BYNB2J6W.jpg"
try
:
try
:
# 测试不同站点(如"us"、"uk"、"de")
# 测试不同站点
for
site
in
[
"us"
,
"uk"
,
"de"
]:
for
site
in
[
"us"
,
"uk"
,
"de"
]:
logger
.
info
(
f
"
\n
{'=' * 20} 测试站点: {site} {'=' * 20}"
)
logger
.
info
(
f
"
\n
{'=' * 40}"
)
logger
.
info
(
f
"开始测试站点: {site}"
)
logger
.
info
(
f
"{'=' * 40}"
)
client
=
AmazonImageSearch
(
site_name
=
site
)
client
=
AmazonImageSearch
(
site_name
=
site
)
# 测试默认识别模式
# 测试默认识别模式
logger
.
info
(
"
\n
--- 默认识别模式 ---"
)
logger
.
info
(
"
\n
---
测试
默认识别模式 ---"
)
default_result
=
client
.
search
(
image_file_path
,
search_mode
=
"default"
)
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"
)
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
:
except
ValueError
as
e
:
logger
.
error
(
f
"初始化失败: {e}"
)
logger
.
error
(
f
"初始化失败: {e}"
)
...
...
hjm_spider_code/app_amazon_image_recognition/threading_image_demo.py
View file @
d7f6ddab
...
@@ -2,209 +2,267 @@ import os
...
@@ -2,209 +2,267 @@ import os
import
time
import
time
import
threading
import
threading
import
queue
import
queue
import
csv
import
random
import
json
from
datetime
import
datetime
from
datetime
import
datetime
from
typing
import
List
,
Dict
,
Tuple
from
typing
import
List
,
Dict
import
app_amazon_image_recognition
as
amazon_recog
from
loguru
import
logger
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"
# 图片文件夹路径
TEST_FOLDER
=
"temp_img"
# 图片文件夹路径
REQUESTS_PER_IMAGE
=
1
# 每张图片请求次数
REQUESTS_PER_IMAGE
=
1
# 每张图片每个站点的请求次数(每种模式各执行一次)
THREAD_COUNT
=
10
# 线程数量
THREAD_COUNT
=
30
# 线程数量
RESULT_CSV
=
"test_results.csv"
# 结果保存文件
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
()
task_queue
=
queue
.
Queue
()
# 结果存储(线程安全)
result_lock
=
threading
.
Lock
()
result_lock
=
threading
.
Lock
()
test_results
=
[]
test_results
=
[]
def
worker
(
cookies
:
dict
):
def
worker
():
"""线程工作函数,处理队列中的任务"""
"""线程工作函数:先执行默认模式,再执行全图模式,记录两种模式结果"""
thread_name
=
threading
.
current_thread
()
.
name
# 获取线程名称(如Worker-1)
thread_id
=
threading
.
current_thread
()
.
ident
thread_name
=
threading
.
current_thread
()
.
name
while
not
task_queue
.
empty
():
while
not
task_queue
.
empty
():
try
:
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
)
image_name
=
os
.
path
.
basename
(
image_path
)
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
()
start_time
=
time
.
time
()
# 执行对应模式的搜索
start_datetime
=
datetime
.
now
()
result_data
=
client
.
search
(
image_path
=
image_path
,
# 打印开始请求的日志(关键:展示线程、图片、序号)
search_mode
=
mode
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
=
round
(
time
.
time
()
-
mode_start
,
4
)
duration
=
end_time
-
start_time
save_time
=
datetime
.
now
()
.
strftime
(
"
%
Y-
%
m-
%
d
%
H:
%
M:
%
S"
)
# 标记请求是否成功(1=成功,0=失败)
success
=
1
if
result_url
else
0
# 记录结果
# 锁定并保存结果(保持原有数据格式,新增mode字段)
with
result_lock
:
with
result_lock
:
test_results
.
append
({
test_results
.
append
({
"thread_name"
:
thread_name
,
# 记录线程名
"image"
:
image_name
,
"image"
:
image_name
,
# 图片文件名
"request_index"
:
request_idx
,
# 同一请求序号关联两种模式
"request_index"
:
request_idx
,
# 第几次请求(1到1000)
"mode"
:
mode
,
# 新增:标记当前模式
"start_time"
:
start_datetime
.
strftime
(
"
%
Y-
%
m-
%
d
%
H:
%
M:
%
S.
%
f"
),
# 开始时间
"duration"
:
duration
,
"duration"
:
round
(
duration
,
4
),
# 耗时 保留4位小数)
"success"
:
result_data
.
get
(
"is_app"
,
0
),
"success"
:
success
,
# 是否成功
"result_url"
:
result_data
.
get
(
"search_url"
,
"None"
),
"result_url"
:
result_url
if
success
else
"None"
,
# 成功时的URL,失败为None
"thread_id"
:
thread_id
,
"thread_id"
:
threading
.
current_thread
()
.
ident
# 处理线程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}秒)"
)
# 每完成100次请求打印进度
except
Exception
as
e
:
if
request_idx
%
100
==
0
:
logger
.
error
(
f
"[{thread_name}] {mode}模式处理出错: {str(e)}"
)
logger
.
info
(
f
"图片 {os.path.basename(image_path)} 完成第 {request_idx} 次请求,耗时 {duration:.2f}s"
)
# 记录模式失败结果
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
:
except
queue
.
Empty
:
# 队列已空,退出循环
break
break
except
Exception
as
e
:
except
Exception
as
e
:
logger
.
error
(
f
"
线程处理
出错: {str(e)}"
)
logger
.
error
(
f
"
[{thread_name}] 整体任务
出错: {str(e)}"
)
finally
:
finally
:
# 队列已空,退出循环
task_queue
.
task_done
()
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
]:
def
collect_image_paths
(
folder
:
str
)
->
List
[
str
]:
"""收集文件夹中的
所有图片路径
"""
"""收集文件夹中的
图片路径(仅支持常见图片格式)
"""
image_extensions
=
(
'.png'
,
'.jpg'
,
'.jpeg'
,
'.gif'
,
'.bmp'
)
image_extensions
=
(
'.png'
,
'.jpg'
,
'.jpeg'
,
'.gif'
,
'.bmp'
)
if
not
os
.
path
.
exists
(
folder
):
if
not
os
.
path
.
exists
(
folder
):
logger
.
error
(
f
"图片文件夹不存在: {folder}"
)
logger
.
error
(
f
"图片文件夹不存在: {folder}"
)
return
[]
return
[]
image_paths
=
[
return
[
os
.
path
.
join
(
folder
,
f
)
os
.
path
.
join
(
folder
,
f
)
for
f
in
os
.
listdir
(
folder
)
for
f
in
os
.
listdir
(
folder
)
if
f
.
lower
()
.
endswith
(
image_extensions
)
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
]):
def
init_task_queue
(
image_paths
:
List
[
str
]):
"""初始化任务队列 将每张图片的N次请求加入队列"""
"""初始化任务队列:包含所有站点、所有图片、所有请求次数(一次任务对应两种模式)"""
# for image_path in image_paths:
for
site
in
ALL_SITES
:
# 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
request_idx
in
range
(
1
,
REQUESTS_PER_IMAGE
+
1
):
for
image_path
in
image_paths
:
for
image_path
in
image_paths
:
task_queue
.
put
((
image_path
,
request_idx
))
task_queue
.
put
((
image_path
,
request_idx
,
site
))
logger
.
info
(
f
"任务队列初始化完成,总任务数: {task_queue.qsize()}"
)
total_tasks
=
task_queue
.
qsize
()
logger
.
info
(
f
"任务队列初始化完成 - 总任务数: {total_tasks} "
def
save_results_to_csv
(
results
:
List
[
Dict
],
filename
:
str
):
f
"(每个任务包含{len(ALL_MODES)}种模式),"
"""将结果保存到CSV文件"""
f
"站点数: {len(ALL_SITES)}, 图片数: {len(image_paths)}, "
f
"单图单站请求数: {REQUESTS_PER_IMAGE}"
)
def
save_results_to_excel
(
results
:
List
[
Dict
]):
"""将结果写入Excel,新增mode字段区分模式"""
if
not
results
:
if
not
results
:
logger
.
warning
(
"
没有
结果可保存"
)
logger
.
warning
(
"
无
结果可保存"
)
return
return
with
open
(
filename
,
'w'
,
newline
=
''
,
encoding
=
'utf-8'
)
as
f
:
# 转换为DataFrame,确保字段顺序(新增mode字段)
# 以结果列表中第一个字典的键作为CSV表头
df
=
pd
.
DataFrame
(
results
)[[
fieldnames
=
results
[
0
]
.
keys
()
"image"
,
"request_index"
,
"mode"
,
"duration"
,
"success"
,
"result_url"
,
writer
=
csv
.
DictWriter
(
f
,
fieldnames
=
fieldnames
)
"thread_id"
,
"is_web"
,
"is_app"
,
"asin_list_web"
,
"asin_list_app"
,
"asin_list_join"
,
"site_name"
,
"device_info"
,
"save_time"
]]
writer
.
writeheader
()
# 保存到Excel
for
row
in
results
:
df
.
to_excel
(
RESULT_EXCEL
,
index
=
False
,
engine
=
"openpyxl"
)
writer
.
writerow
(
row
)
# 写入每行数据
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
]):
def
print_summary
(
results
:
List
[
Dict
]):
"""打印测试总结(
成功率、耗时等关键指标
)"""
"""打印测试总结(
按站点和模式分组统计
)"""
if
not
results
:
if
not
results
:
return
return
total
=
len
(
results
)
total
=
len
(
results
)
success
=
sum
(
1
for
r
in
test_results
if
r
[
"success"
])
total_duration
=
sum
(
r
[
"duration"
]
for
r
in
results
)
logger
.
info
(
f
"
\n
===== 测试总结 ====="
)
logger
.
info
(
"
\n
===== 测试总结 ====="
)
logger
.
info
(
f
"总请求: {total},成功: {success},成功率: {success/total*100:.2f}
%
"
)
logger
.
info
(
f
"总请求数: {total}(含{len(ALL_MODES)}种模式),"
f
"总耗时: {total_duration:.2f}秒,"
# 按图片分组统计 (每张图片的单独表现)
f
"平均耗时: {total_duration / total:.4f}秒"
)
image_stats
=
{}
for
r
in
results
:
# 按站点分组统计
img
=
r
[
"image"
]
for
site
in
ALL_SITES
:
if
img
not
in
image_stats
:
site_results
=
[
r
for
r
in
results
if
r
[
"site_name"
]
==
site
]
image_stats
[
img
]
=
{
"total"
:
0
,
"success"
:
0
,
"duration"
:
[]}
site_total
=
len
(
site_results
)
image_stats
[
img
][
"total"
]
+=
1
if
site_total
==
0
:
image_stats
[
img
][
"success"
]
+=
r
[
"success"
]
continue
image_stats
[
img
][
"duration"
]
.
append
(
r
[
"duration"
])
logger
.
info
(
f
"
\n
----- 站点: {site} 统计 -----"
)
# 按线程统计
logger
.
info
(
f
"总请求数: {site_total},平均耗时: {sum(r['duration'] for r in site_results) / site_total:.4f}秒"
)
thread_stats
=
{}
for
r
in
test_results
:
# 按模式分组统计
t
=
r
[
"thread_name"
]
for
mode
in
ALL_MODES
:
thread_stats
[
t
]
=
thread_stats
.
get
(
t
,
0
)
+
1
mode_results
=
[
r
for
r
in
site_results
if
r
[
"mode"
]
==
mode
]
logger
.
info
(
"
\n
线程任务分配:"
)
mode_total
=
len
(
mode_results
)
for
t
,
cnt
in
thread_stats
.
items
():
if
mode_total
==
0
:
logger
.
info
(
f
" {t}: {cnt} 次请求"
)
continue
mode_success
=
sum
(
1
for
r
in
mode_results
if
r
[
"is_app"
]
==
1
)
def
main
():
mode_success_rate
=
(
mode_success
/
mode_total
)
*
100
if
mode_total
else
0
# 初始化日志
logger
.
info
(
logger
.
add
(
"stability_test.log"
,
rotation
=
"10 MB"
,
level
=
"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
)
init_task_queue
(
image_paths
)
# 记录测试开始时间
# 启动多线程
test_start_time
=
time
.
time
()
start_time
=
time
.
time
()
# 创建并启动线程
threads
=
[]
threads
=
[]
for
i
in
range
(
THREAD_COUNT
):
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
)
threads
.
append
(
t
)
t
.
start
()
t
.
start
()
logger
.
info
(
f
"启动线程: {t.name}"
)
logger
.
info
(
f
"启动线程: {t.name}"
)
# 等待所有任务完成
# 等待所有任务完成
task_queue
.
join
()
task_queue
.
join
()
# 等待所有线程结束
for
t
in
threads
:
for
t
in
threads
:
t
.
join
()
t
.
join
()
# 计算总耗时
total_time
=
time
.
time
()
-
start_time
total_test_time
=
time
.
time
()
-
test_start_time
logger
.
info
(
f
"所有任务完成,总耗时: {total_time:.2f}秒"
)
logger
.
info
(
f
"所有测试完成,总耗时: {total_test_time:.2f}秒"
)
# 保存结果并打印总结
# 保存结果并打印总结
save_results_to_
csv
(
test_results
,
RESULT_CSV
)
save_results_to_
excel
(
test_results
)
print_summary
(
test_results
)
print_summary
(
test_results
)
\ No newline at end of file
if
__name__
==
"__main__"
:
main
()
\ No newline at end of file
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment