diff --git a/.gitignore b/.gitignore index 6fc332ca..6f093a9e 100644 --- a/.gitignore +++ b/.gitignore @@ -5,4 +5,5 @@ images .vscode download_images build -dist \ No newline at end of file +dist +.DS_Store diff --git a/Image-Downloader-master.pyproj b/Image-Downloader-master.pyproj new file mode 100644 index 00000000..7fc6d0e7 --- /dev/null +++ b/Image-Downloader-master.pyproj @@ -0,0 +1,11835 @@ + + + + Debug + 2.0 + {df3acfb9-3979-40d6-aaf4-912a01ecb210} + + image_downloader_gui.py + + . + . + {888888a0-9f3d-457c-b088-3a5042f75d52} + Standard Python launcher + MSBuild|envImageDownloaderEnv|$(MSBuildProjectFullPath) + + + + + 10.0 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + envImageDownloaderEnv + 3.10 + envImageDownloaderEnv (Python 3.10 (64-bit)) + Scripts\python.exe + Scripts\pythonw.exe + PYTHONPATH + X64 + + + + \ No newline at end of file diff --git a/README.md b/README.md index a027e67a..c7cb471c 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,7 @@ +Commit 848cd37 uses exclusive mode, which fails if a file exists. It seems like the best way to check, to avoid a race condition. This is to avoid overwriting any file. + +The remainder of this readme is the original. + # Image Downloader [![996.icu](https://img.shields.io/badge/link-996.icu-red.svg)](https://996.icu) diff --git a/crawler.py b/crawler.py index d94b763c..7e23eee2 100644 --- a/crawler.py +++ b/crawler.py @@ -5,18 +5,17 @@ from __future__ import print_function +import json +import os import re -import time import sys -import os -import json -import shutil +import time +from concurrent import futures +from urllib.parse import quote, unquote -from urllib.parse import unquote, quote +import requests from selenium import webdriver from selenium.webdriver.common.by import By -import requests -from concurrent import futures g_headers = { "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8", @@ -27,7 +26,10 @@ # 'Connection': 'close', } -if getattr(sys, 'frozen', False): +session = requests.Session() +session.headers = g_headers + +if getattr(sys, "frozen", False): bundle_dir = sys._MEIPASS else: bundle_dir = os.path.dirname(os.path.abspath(__file__)) @@ -38,16 +40,18 @@ def my_print(msg, quiet=False): print(msg) -def google_gen_query_url(keywords, face_only=False, safe_mode=False, image_type=None, color=None): +def google_gen_query_url( + keywords, face_only=False, safe_mode=False, image_type=None, color=None +): base_url = "https://www.google.com/search?tbm=isch&hl=en" keywords_str = "&q=" + quote(keywords) query_url = base_url + keywords_str - + if safe_mode is True: query_url += "&safe=on" else: query_url += "&safe=off" - + filter_url = "&tbs=" if color is not None: @@ -55,12 +59,12 @@ def google_gen_query_url(keywords, face_only=False, safe_mode=False, image_type= filter_url += "ic:gray%2C" else: filter_url += "ic:specific%2Cisc:{}%2C".format(color.lower()) - + if image_type is not None: if image_type.lower() == "linedrawing": image_type = "lineart" filter_url += "itp:{}".format(image_type) - + if face_only is True: filter_url += "itp:face" @@ -73,7 +77,12 @@ def google_image_url_from_webpage(driver, max_number, quiet=False): thumb_elements = [] while True: try: - thumb_elements = driver.find_elements(By.CLASS_NAME, "rg_i") + # tuankg1028 + # thumb_elements = driver.find_elements(By.CLASS_NAME, "ivg-i") + # old way to get thumb_elements + # thumb_elements = driver.find_elements(By.CLASS_NAME, "rg_i") + # Adapt to the updated Google image search page + thumb_elements = driver.find_elements(By.CSS_SELECTOR, ".H8Rx8c > g-img > img") my_print("Find {} images.".format(len(thumb_elements)), quiet) if len(thumb_elements) >= max_number: break @@ -81,20 +90,26 @@ def google_image_url_from_webpage(driver, max_number, quiet=False): break thumb_elements_old = thumb_elements driver.execute_script("window.scrollTo(0, document.body.scrollHeight);") - time.sleep(2) + time.sleep(10) show_more = driver.find_elements(By.CLASS_NAME, "mye4qd") - if len(show_more) == 1 and show_more[0].is_displayed() and show_more[0].is_enabled(): + if ( + len(show_more) == 1 + and show_more[0].is_displayed() + and show_more[0].is_enabled() + ): my_print("Click show_more button.", quiet) show_more[0].click() time.sleep(3) except Exception as e: print("Exception ", e) pass - + if len(thumb_elements) == 0: return [] - my_print("Click on each thumbnail image to get image url, may take a moment ...", quiet) + my_print( + "Click on each thumbnail image to get image url, may take a moment ...", quiet + ) retry_click = [] for i, elem in enumerate(thumb_elements): @@ -109,7 +124,7 @@ def google_image_url_from_webpage(driver, max_number, quiet=False): print("Error while clicking in thumbnail:", e) retry_click.append(elem) - if len(retry_click) > 0: + if len(retry_click) > 0: my_print("Retry some failed clicks ...", quiet) for elem in retry_click: try: @@ -117,31 +132,41 @@ def google_image_url_from_webpage(driver, max_number, quiet=False): elem.click() except Exception as e: print("Error while retrying click:", e) - - image_elements = driver.find_elements(By.CLASS_NAME, "islib") + + + # image_elements = driver.find_elements(By.CLASS_NAME, "islib") + # tuankg1028 + # image_elements = driver.find_elements(By.CLASS_NAME, "ivg-i") + image_elements = driver.find_elements(By.CSS_SELECTOR, ".ob5Hkd > a") image_urls = list() - url_pattern = r"imgurl=\S*&imgrefurl" + #url_pattern = r"imgurl=\S*&imgrefurl" + # bluelul/Image-Downloader + url_pattern = r"imgurl=\S*&tbnid" for image_element in image_elements[:max_number]: outer_html = image_element.get_attribute("outerHTML") re_group = re.search(url_pattern, outer_html) if re_group is not None: - image_url = unquote(re_group.group()[7:-14]) + # image_url = unquote(re_group.group()[7:-14]) + # bluelul/Image-Downloader + image_url = unquote(re_group.group()[7:-10]) image_urls.append(image_url) return image_urls -def bing_gen_query_url(keywords, face_only=False, safe_mode=False, image_type=None, color=None): +def bing_gen_query_url( + keywords, face_only=False, safe_mode=False, image_type=None, color=None +): base_url = "https://www.bing.com/images/search?" keywords_str = "&q=" + quote(keywords) query_url = base_url + keywords_str filter_url = "&qft=" if face_only is True: filter_url += "+filterui:face-face" - + if image_type is not None: filter_url += "+filterui:photo-{}".format(image_type) - + if color is not None: if color == "bw" or color == "color": filter_url += "+filterui:color2-{}".format(color.lower()) @@ -163,8 +188,7 @@ def bing_image_url_from_webpage(driver): image_elements = driver.find_elements(By.CLASS_NAME, "iusc") if len(image_elements) > img_count: img_count = len(image_elements) - driver.execute_script( - "window.scrollTo(0, document.body.scrollHeight);") + driver.execute_script("window.scrollTo(0, document.body.scrollHeight);") else: smb = driver.find_elements(By.CLASS_NAME, "btn_seemore") if len(smb) > 0 and smb[0].is_displayed(): @@ -178,30 +202,48 @@ def bing_image_url_from_webpage(driver): image_urls.append(m_json["murl"]) return image_urls -def bing_get_image_url_using_api(keywords, max_number=10000, face_only=False, - proxy=None, proxy_type=None): + +def bing_get_image_url_using_api( + keywords, max_number=10000, face_only=False, proxy=None, proxy_type=None +): proxies = None if proxy and proxy_type: - proxies = {"http": "{}://{}".format(proxy_type, proxy), - "https": "{}://{}".format(proxy_type, proxy)} + proxies = { + "http": "{}://{}".format(proxy_type, proxy), + "https": "{}://{}".format(proxy_type, proxy), + } start = 1 image_urls = [] while start <= max_number: - url = 'https://www.bing.com/images/async?q={}&first={}&count=35'.format(keywords, start) - res = requests.get(url, proxies=proxies, headers=g_headers) + url = "https://www.bing.com/images/async?q={}&first={}&count=35".format( + keywords, start + ) + res = session.get(url, proxies=proxies, headers=g_headers) res.encoding = "utf-8" - image_urls_batch = re.findall('murl":"(.*?)"', res.text) - if len(image_urls) > 0 and image_urls_batch[-1] == image_urls[-1]: + image_urls_batch = re.findall("murl":"(.*?)"", res.text) + if len(image_urls) > 0 and len(image_urls_batch) > 0 and image_urls_batch[-1] == image_urls[-1]: break image_urls += image_urls_batch start += len(image_urls_batch) return image_urls + baidu_color_code = { - "white": 1024, "bw": 2048, "black": 512, "pink": 64, "blue": 16, "red": 1, - "yellow": 2, "purple": 32, "green": 4, "teal": 8, "orange": 256, "brown": 128 + "white": 1024, + "bw": 2048, + "black": 512, + "pink": 64, + "blue": 16, + "red": 1, + "yellow": 2, + "purple": 32, + "green": 4, + "teal": 8, + "orange": 256, + "brown": 128, } + def baidu_gen_query_url(keywords, face_only=False, safe_mode=False, color=None): base_url = "https://image.baidu.com/search/index?tn=baiduimage" keywords_str = "&word=" + quote(keywords) @@ -227,21 +269,23 @@ def baidu_image_url_from_webpage(driver): return image_urls -def baidu_get_image_url_using_api(keywords, max_number=10000, face_only=False, - proxy=None, proxy_type=None): +def baidu_get_image_url_using_api( + keywords, max_number=10000, face_only=False, proxy=None, proxy_type=None +): def decode_url(url): - in_table = '0123456789abcdefghijklmnopqrstuvw' - out_table = '7dgjmoru140852vsnkheb963wtqplifca' + in_table = "0123456789abcdefghijklmnopqrstuvw" + out_table = "7dgjmoru140852vsnkheb963wtqplifca" translate_table = str.maketrans(in_table, out_table) - mapping = {'_z2C$q': ':', '_z&e3B': '.', 'AzdH3F': '/'} + mapping = {"_z2C$q": ":", "_z&e3B": ".", "AzdH3F": "/"} for k, v in mapping.items(): url = url.replace(k, v) return url.translate(translate_table) - base_url = "https://image.baidu.com/search/acjson?tn=resultjson_com&ipn=rj&ct=201326592"\ - "&lm=7&fp=result&ie=utf-8&oe=utf-8&st=-1" - keywords_str = "&word={}&queryWord={}".format( - quote(keywords), quote(keywords)) + base_url = ( + "https://image.baidu.com/search/acjson?tn=resultjson_com&ipn=rj&ct=201326592" + "&lm=7&fp=result&ie=utf-8&oe=utf-8&st=-1" + ) + keywords_str = "&word={}&queryWord={}".format(quote(keywords), quote(keywords)) query_url = base_url + keywords_str query_url += "&face={}".format(1 if face_only else 0) @@ -249,12 +293,14 @@ def decode_url(url): proxies = None if proxy and proxy_type: - proxies = {"http": "{}://{}".format(proxy_type, proxy), - "https": "{}://{}".format(proxy_type, proxy)} + proxies = { + "http": "{}://{}".format(proxy_type, proxy), + "https": "{}://{}".format(proxy_type, proxy), + } - res = requests.get(init_url, proxies=proxies, headers=g_headers) + res = session.get(init_url, proxies=proxies, headers=g_headers) init_json = json.loads(res.text.replace(r"\'", "").encode("utf-8"), strict=False) - total_num = init_json['listNum'] + total_num = init_json["listNum"] target_num = min(max_number, total_num) crawl_num = min(target_num * 2, total_num) @@ -267,33 +313,32 @@ def decode_url(url): def process_batch(batch_no, batch_size): image_urls = list() - url = query_url + \ - "&pn={}&rn={}".format(batch_no * batch_size, batch_size) + url = query_url + "&pn={}&rn={}".format(batch_no * batch_size, batch_size) try_time = 0 while True: try: - response = requests.get(url, proxies=proxies, headers=g_headers) + response = session.get(url, proxies=proxies, headers=g_headers) break except Exception as e: try_time += 1 if try_time > 3: print(e) return image_urls - response.encoding = 'utf-8' + response.encoding = "utf-8" res_json = json.loads(response.text.replace(r"\'", ""), strict=False) - for data in res_json['data']: + for data in res_json["data"]: # if 'middleURL' in data.keys(): # url = data['middleURL'] # image_urls.append(url) - if 'objURL' in data.keys(): - url = unquote(decode_url(data['objURL'])) - if 'src=' in url: - url_p1 = url.split('src=')[1] - url = url_p1.split('&refer=')[0] + if "objURL" in data.keys(): + url = unquote(decode_url(data["objURL"])) + if "src=" in url: + url_p1 = url.split("src=")[1] + url = url_p1.split("&refer=")[0] image_urls.append(url) # print(url) - elif 'replaceUrl' in data.keys() and len(data['replaceUrl']) == 2: - image_urls.append(data['replaceUrl'][1]['ObjURL']) + elif "replaceUrl" in data.keys() and len(data["replaceUrl"]) == 2: + image_urls.append(data["replaceUrl"][1]["ObjURL"]) return image_urls @@ -305,12 +350,22 @@ def process_batch(batch_no, batch_size): else: print(future.exception()) - return crawled_urls[:min(len(crawled_urls), target_num)] - - -def crawl_image_urls(keywords, engine="Google", max_number=10000, - face_only=False, safe_mode=False, proxy=None, - proxy_type="http", quiet=False, browser="chrome_headless", image_type=None, color=None): + return crawled_urls[: min(len(crawled_urls), target_num)] + + +def crawl_image_urls( + keywords, + engine="Google", + max_number=10000, + face_only=False, + safe_mode=False, + proxy=None, + proxy_type="http", + quiet=False, + browser="chrome_headless", + image_type=None, + color=None, +): """ Scrape image urls of keywords from Google Image Search :param keywords: keywords you want to search @@ -323,6 +378,9 @@ def crawl_image_urls(keywords, engine="Google", max_number=10000, :param browser: browser to use when crawl image urls :return: list of scraped image urls """ + # Validate engine name + if engine not in ["Google", "Baidu", "Bing"]: + raise Exception(f"Unknown engine name: {engine}") my_print("\nScraping From {} Image Search ...\n".format(engine), quiet) my_print("Keywords: " + keywords, quiet) @@ -335,9 +393,13 @@ def crawl_image_urls(keywords, engine="Google", max_number=10000, my_print("Safe Mode: {}".format(str(safe_mode)), quiet) if engine == "Google": - query_url = google_gen_query_url(keywords, face_only, safe_mode, image_type, color) + query_url = google_gen_query_url( + keywords, face_only, safe_mode, image_type, color + ) elif engine == "Bing": - query_url = bing_gen_query_url(keywords, face_only, safe_mode, image_type, color) + query_url = bing_gen_query_url( + keywords, face_only, safe_mode, image_type, color + ) elif engine == "Baidu": query_url = baidu_gen_query_url(keywords, face_only, safe_mode, color) else: @@ -349,14 +411,19 @@ def crawl_image_urls(keywords, engine="Google", max_number=10000, if browser != "api": browser = str.lower(browser) - chrome_path = shutil.which("chromedriver") chrome_options = webdriver.ChromeOptions() + chrome_options.add_argument("--ignore-certificate-errors") if "headless" in browser: - chrome_options.add_argument("headless") + chrome_options.add_argument("--headless=old") # headless for v < 129 + # https://chromium-review.googlesource.com/c/chromium/src/+/5789117 ( if proxy is not None and proxy_type is not None: - chrome_options.add_argument("--proxy-server={}://{}".format(proxy_type, proxy)) - driver = webdriver.Chrome(chrome_path, chrome_options=chrome_options) + chrome_options.add_argument( + "--proxy-server={}://{}".format(proxy_type, proxy) + ) + # driver = webdriver.Chrome(chrome_path, chrome_options=chrome_options) + service = webdriver.ChromeService() + driver = webdriver.Chrome(service=service, options=chrome_options) if engine == "Google": driver.set_window_size(1920, 1080) driver.get(query_url) @@ -365,18 +432,29 @@ def crawl_image_urls(keywords, engine="Google", max_number=10000, driver.set_window_size(1920, 1080) driver.get(query_url) image_urls = bing_image_url_from_webpage(driver) - else: # Baidu + elif engine == "Baidu": driver.set_window_size(10000, 7500) driver.get(query_url) image_urls = baidu_image_url_from_webpage(driver) - driver.close() - else: # api + # driver.close() just closes the window. quit() does much more cleanup + driver.quit() + else: # api if engine == "Baidu": - image_urls = baidu_get_image_url_using_api(keywords, max_number=max_number, face_only=face_only, - proxy=proxy, proxy_type=proxy_type) + image_urls = baidu_get_image_url_using_api( + keywords, + max_number=max_number, + face_only=face_only, + proxy=proxy, + proxy_type=proxy_type, + ) elif engine == "Bing": - image_urls = bing_get_image_url_using_api(keywords, max_number=max_number, face_only=face_only, - proxy=proxy, proxy_type=proxy_type) + image_urls = bing_get_image_url_using_api( + keywords, + max_number=max_number, + face_only=face_only, + proxy=proxy, + proxy_type=proxy_type, + ) else: my_print("Engine {} is not supported on API mode.".format(engine)) @@ -385,7 +463,12 @@ def crawl_image_urls(keywords, engine="Google", max_number=10000, else: output_num = max_number - my_print("\n== {0} out of {1} crawled images urls will be used.\n".format( - output_num, len(image_urls)), quiet) + my_print( + "\n== {0} out of {1} crawled images urls will be used.\n".format( + output_num, len(image_urls) + ), + quiet, + ) - return image_urls[0:output_num] +# return image_urls[0:output_num] + return image_urls diff --git a/downloader.py b/downloader.py index abe69f6b..81c7d572 100644 --- a/downloader.py +++ b/downloader.py @@ -4,6 +4,9 @@ # Email: sczhengyabin@hotmail.com from __future__ import print_function +from urllib.parse import unquote +from pathlib import Path +from hashlib import sha256 import shutil import imghdr @@ -21,6 +24,71 @@ # 'Connection': 'close', } +# additional checks for imghdr.what() +# default tests: +# test_bmp +# test_exr +# test_gif +# test_jpeg +# test_pbm +# test_pgm +# test_png +# test_ppm +# test_rast +# test_rgb +# test_tiff +# test_webp +# test_xbm + +def test_html(h, f): + if b" {}".format(file_name, new_file_name)) + return new_file_name + + else: + # os.remove(file_path) + print("## Err: TYPE({}) {}".format(file_type, file_name)) + return file_name def download_images(image_urls, dst_dir, file_prefix="img", concurrency=50, timeout=20, proxy_type=None, proxy=None): @@ -70,7 +200,7 @@ def download_images(image_urls, dst_dir, file_prefix="img", concurrency=50, time :param dst_dir: output the downloaded images to dst_dir :param file_prefix: if set to "img", files will be in format "img_xxx.jpg" :param concurrency: number of requests process simultaneously - :return: none + :return: the number of successful downloads """ socket.setdefaulttimeout(timeout) @@ -78,11 +208,52 @@ def download_images(image_urls, dst_dir, file_prefix="img", concurrency=50, time with concurrent.futures.ThreadPoolExecutor(max_workers=concurrency) as executor: future_list = list() count = 0 + success_downloads = 0 + if not os.path.exists(dst_dir): os.makedirs(dst_dir) for image_url in image_urls: - file_name = file_prefix + "_" + "%04d" % count - future_list.append(executor.submit( - download_image, image_url, dst_dir, file_name, timeout, proxy_type, proxy)) + # file_name = file_prefix + "_" + "%04d" % count + print("## URL : {}".format(image_url)) + file_name = image_url + file_name = split_string(file_name, "?", 0) + file_name = split_string(file_name, "&", 0) + file_name = split_string(file_name, "/", -1) + print("## FILE: {}".format(file_name)) + future_list.append( + executor.submit( + download_image, + image_url, + dst_dir, + file_name, + timeout, + proxy_type, + proxy, + ) + ) count += 1 - concurrent.futures.wait(future_list, timeout=180) + concurrent.futures.wait(future_list, timeout=90) + + # Count the number of successful downloads + for future in future_list: + if future.result(): + success_downloads += 1 + + return success_downloads + + +def split_string(str, delimiter, index): + s = str + while delimiter in s: + s, _, t = s.partition(delimiter) + if index == 0: + break + if t == "": + break + index = index - 1 + s = t + + if s == "": + s = str + + return s diff --git a/image_downloader.py b/image_downloader.py index 21a50315..67e37057 100644 --- a/image_downloader.py +++ b/image_downloader.py @@ -11,39 +11,98 @@ import downloader import utils + def main(argv): parser = argparse.ArgumentParser(description="Image Downloader") - parser.add_argument("keywords", type=str, - help='Keywords to search. ("in quotes")') - parser.add_argument("--engine", "-e", type=str, default="Google", - help="Image search engine.", choices=["Google", "Bing", "Baidu"]) - parser.add_argument("--driver", "-d", type=str, default="chrome_headless", - help="Image search engine.", choices=["chrome_headless", "chrome", "api"]) - parser.add_argument("--max-number", "-n", type=int, default=100, - help="Max number of images download for the keywords.") - parser.add_argument("--num-threads", "-j", type=int, default=50, - help="Number of threads to concurrently download images.") - parser.add_argument("--timeout", "-t", type=int, default=10, - help="Seconds to timeout when download an image.") - parser.add_argument("--output", "-o", type=str, default="./download_images", - help="Output directory to save downloaded images.") - parser.add_argument("--safe-mode", "-S", action="store_true", default=False, - help="Turn on safe search mode. (Only effective in Google)") - parser.add_argument("--face-only", "-F", action="store_true", default=False, - help="Only search for ") - parser.add_argument("--proxy_http", "-ph", type=str, default=None, - help="Set http proxy (e.g. 192.168.0.2:8080)") - parser.add_argument("--proxy_socks5", "-ps", type=str, default=None, - help="Set socks5 proxy (e.g. 192.168.0.2:1080)") + parser.add_argument("keywords", type=str, help='Keywords to search. ("in quotes")') + parser.add_argument( + "--engine", + "-e", + type=str, + default="Google", + help="Image search engine.", + choices=["Google", "Bing", "Baidu"], + ) + parser.add_argument( + "--driver", + "-d", + type=str, + default="chrome_headless", + help="Image search engine.", + choices=["chrome_headless", "chrome", "api"], + ) + parser.add_argument( + "--max-number", + "-n", + type=int, + default=100, + help="Max number of images download for the keywords.", + ) + parser.add_argument( + "--num-threads", + "-j", + type=int, + default=50, + help="Number of threads to concurrently download images.", + ) + parser.add_argument( + "--timeout", + "-t", + type=int, + default=10, + help="Seconds to timeout when download an image.", + ) + parser.add_argument( + "--output", + "-o", + type=str, + default="./download_images", + help="Output directory to save downloaded images.", + ) + parser.add_argument( + "--safe-mode", + "-S", + action="store_true", + default=False, + help="Turn on safe search mode. (Only effective in Google)", + ) + parser.add_argument( + "--face-only", "-F", action="store_true", default=False, help="Only search for faces (only available in Google)" + ) + parser.add_argument( + "--proxy_http", + "-ph", + type=str, + default=None, + help="Set http proxy (e.g. 192.168.0.2:8080)", + ) + parser.add_argument( + "--proxy_socks5", + "-ps", + type=str, + default=None, + help="Set socks5 proxy (e.g. 192.168.0.2:1080)", + ) # type is not supported for Baidu - parser.add_argument("--type", "-ty", type=str, default=None, - help="What kinds of images to download.", choices=["clipart", "linedrawing", "photograph"]) + parser.add_argument( + "--type", + "-ty", + type=str, + default=None, + help="What kinds of images to download.", + choices=["clipart", "linedrawing", "photograph"], + ) # Bing: color for colored images, bw for black&white images, other color contains Red, orange, yellow, green # Teal, Blue, Purple, Pink, Brown, Black, Gray, White # Baidu: white, bw, black, pink, blue, red, yellow, purple, green, teal, orange, brown # Google: bw, red, orange, yellow, green, teal, blue, purple, pink, white, gray, black, brown - parser.add_argument("--color", "-cl", type=str, default=None, - help="Specify the color of desired images.") + parser.add_argument( + "--color", + "-cl", + type=str, + default=None, + help="Specify the color of desired images.", + ) args = parser.parse_args(args=argv) @@ -60,18 +119,30 @@ def main(argv): print("Dependencies not resolved, exit.") return - crawled_urls = crawler.crawl_image_urls(args.keywords, - engine=args.engine, max_number=args.max_number, - face_only=args.face_only, safe_mode=args.safe_mode, - proxy_type=proxy_type, proxy=proxy, - browser=args.driver, image_type=args.type, color=args.color) - downloader.download_images(image_urls=crawled_urls, dst_dir=args.output, - concurrency=args.num_threads, timeout=args.timeout, - proxy_type=proxy_type, proxy=proxy, - file_prefix=args.engine) + crawled_urls = crawler.crawl_image_urls( + args.keywords, + engine=args.engine, + max_number=args.max_number, + face_only=args.face_only, + safe_mode=args.safe_mode, + proxy_type=proxy_type, + proxy=proxy, + browser=args.driver, + image_type=args.type, + color=args.color, + ) + downloader.download_images( + image_urls=crawled_urls, + dst_dir=args.output, + concurrency=args.num_threads, + timeout=args.timeout, + proxy_type=proxy_type, + proxy=proxy, + file_prefix=args.keywords + "_" + args.engine, + ) print("Finished.") -if __name__ == '__main__': +if __name__ == "__main__": main(sys.argv[1:]) diff --git a/requirements.txt b/requirements.txt index fa29d1ec..3f2e15f0 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,5 +1,5 @@ -chromedriver-autoinstaller==0.4.0 -pyinstaller==5.9.0 +chromedriver-autoinstaller==0.6.2 +pyinstaller==5.13.1 PyQt5==5.15.9 -requests==2.31.0 -selenium==4.8.3 +requests==2.32.2 +selenium==4.11.0 diff --git a/utils.py b/utils.py index ba4f7038..4c8723a8 100644 --- a/utils.py +++ b/utils.py @@ -13,7 +13,7 @@ def gen_valid_dir_name_for_keywords(keywords): class AppConfig(object): def __init__(self): self.engine = "Google" - + self.driver = "chrome_headless" self.keywords = "" @@ -33,23 +33,28 @@ def __init__(self): def to_command_paras(self): str_paras = "" - - str_paras += ' -e ' + self.engine - str_paras += ' -d ' + self.driver + str_paras += " -e " + self.engine + + str_paras += " -d " + self.driver - str_paras += ' -n ' + str(self.max_number) + str_paras += " -n " + str(self.max_number) - str_paras += ' -j ' + str(self.num_threads) + str_paras += " -j " + str(self.num_threads) - str_paras += ' -o "' + self.output_dir + '/' + \ - gen_valid_dir_name_for_keywords(self.keywords) + '"' + str_paras += ( + ' -o "' + + self.output_dir + + "/" + + gen_valid_dir_name_for_keywords(self.keywords) + + '"' + ) if self.face_only: - str_paras += ' -F ' + str_paras += " -F " if self.safe_mode: - str_paras += ' -S ' + str_paras += " -S " if self.proxy_type == "http": str_paras += ' -ph "' + self.proxy + '"'