点击上方蓝色字体,关注程序员zhenguo

你好,我是 zhenguo
这是我的第498篇原创
这是第六个Python小项目,做一个图片下载器。
之前项目:

输入关键词,即可批量下载对应关键词的图片。

项目环境

使用osjson内置模块,分别用于下载图片后文件系统建立,API的参数以json串封装。
requests模块是爬虫最常用的,用于建立session,下载对应url的图片资源。
Python版本是3.7.2
import
 os

import
 json

import
 requests

项目功能

图片下载器使用方便,只需执行下面一行代码,即可启动模块,在控制台输入:
python baidu_img.py

启动后,提示:请输入搜索关键词,按q退出:,输入关键词:美景
又提示:请输入下载图片数量,默认200(回车即取默认值):,此处直接回车,即默认下载200张;
最后提示:请输入图片保存路径,默认为img(回车即取默认值),此处也直接回车。
然后开始下载,控制台打印信息如下,截取部分信息:
开始下载.....

正在下载第1张图片,图片地址:https://img2.baidu.com/it/u=2384681520,223097820&fm=253&fmt=auto&app=138&f=JPEG?w=500&h=281

正在下载第2张图片,图片地址:https://img1.baidu.com/it/u=3647422399,1785273059&fm=253&fmt=auto&app=120&f=JPEG?w=1280&h=800

正在下载第3张图片,图片地址:https://img2.baidu.com/it/u=470784270,1455700935&fm=253&fmt=auto&app=138&f=JPEG?w=748&h=500

正在下载第4张图片,图片地址:https://img1.baidu.com/it/u=2917570607,1493521935&fm=253&fmt=auto&app=138&f=JPEG?w=667&h=500

正在下载第5张图片,图片地址:https://img2.baidu.com/it/u=1135644150,2997736855&fm=253&fmt=auto&app=138&f=JPEG?w=500&h=704

正在下载第6张图片,图片地址:https://img2.baidu.com/it/u=4088752237,542958201&fm=253&fmt=auto&app=138&f=JPEG?w=500&h=625

正在下载第7张图片,图片地址:https://img1.baidu.com/it/u=2570849327,1146996939&fm=253&fmt=auto&app=138&f=JPEG?w=800&h=500

正在下载第8张图片,图片地址:https://img1.baidu.com/it/u=2056884040,2357342393&fm=253&fmt=auto&app=120&f=JPEG?w=1280&h=800

正在下载第9张图片,图片地址:https://img1.baidu.com/it/u=4240260370,854376853&fm=253&fmt=auto&app=120&f=JPEG?w=1281&h=800

正在下载第10张图片,图片地址:https://img1.baidu.com/it/u=3916717742,3432876503&fm=253&fmt=auto&app=138&f=JPEG?w=500&h=332

正在下载第11张图片,图片地址:https://img1.baidu.com/it/u=2664935602,3318592316&fm=253&fmt=auto&app=138&f=JPEG?w=700&h=494

正在下载第12张图片,图片地址:https://img1.baidu.com/it/u=1914896228,578565857&fm=253&fmt=auto&app=138&f=JPEG?w=658&h=434

正在下载第13张图片,图片地址:https://img0.baidu.com/it/u=1749953353,1887143918&fm=253&fmt=auto&app=138&f=JPEG?w=500&h=313

正在下载第14张图片,图片地址:https://img1.baidu.com/it/u=912155388,1485322457&fm=253&fmt=auto&app=138&f=JPEG?w=658&h=439

正在下载第15张图片,图片地址:https://img1.baidu.com/it/u=1947167601,443342984&fm=253&fmt=auto&app=138&f=JPEG?w=889&h=500

正在下载第16张图片,图片地址:https://img0.baidu.com/it/u=1511507281,552216865&fm=253&fmt=auto&app=138&f=JPEG?w=500&h=209

正在下载第17张图片,图片地址:https://img1.baidu.com/it/u=3342591022,1114316885&fm=253&fmt=auto&app=138&f=JPEG?w=500&h=375

正在下载第18张图片,图片地址:https://img0.baidu.com/it/u=1620554767,3986196061&fm=253&fmt=auto&app=138&f=PNG?w=499&h=341

正在下载第19张图片,图片地址:https://img0.baidu.com/it/u=1795137323,1400650075&fm=253&fmt=auto&app=138&f=JPEG?w=858&h=500


很快下载完成后,默认保存到img文件夹,同时以关键词命名的文件夹中。
查看后应该会有200张美景图片,下面是前三张美景图:
输入关键词晚霞,输入1000,即下载1000张晚霞图,前五张晚霞图:
输入关键词高圆圆,输入100,前三张图:
你可以输入任意其他关键词,一次批量下载对应数量的图片。
下面介绍这个下载器的代码,完整代码见文末。

项目原理

输入美景,出来网页中,再点击百度图片,就会出现下面网页:
对应的url为:
https://image.baidu.com/search/index?ie=utf-8&tn=baiduimage&word=%E7%BE%8E%E6%99%AF

点击右键,选择检查,再选择Network,再刷新下网页,就可以看到使用的所有资源。
根据上面url,在左上角筛选框里,输入search,尝试筛选出真正请求的API,找到对应的参数:
在左侧不断滚动鼠标,看到下面图所示的acjson链接不断增多,这就是在不断请求服务器:
再点击右侧的payload,如下图所示,看到发送的json串参数:
tn: resultjson_com

logid: 
11341948550389857636
ipn: rj

ct: 
201326592
is: 

fp: result

fr: 

word: 美景

queryWord: 美景

cl: 

lm: 

ie: utf
-8
oe: utf
-8
adpicid: 

st: 

z: 

ic: 

hd: 

latest: 

copyright: 

s: 

se: 

tab: 

width: 

height: 

face: 

istype: 

qc: 

nc: 

expermode: 

nojc: 

isAsync: 

pn: 
90
rn: 
30
gsm: 
5
a

1642323736936

看到大部分参数是空的,wordqueryWord就是我们输入的关键词,ie是编码。
至于pn参数是最重要的一个参数,当不断滚动鼠标,依次加载图片时,发现pn参数以30步长累加,因此判断是分页相关的参数。
rngsm等参数先按照默认值取值。
有了API,再根据返回的数据,解析之即可。

代码解释

代码框架只有一个baidu_img模块组成,模块里主要有BaiduImgDownloader类。

BaiduImgDownloader类

类包括1个对外公开方法:downloader,用于下载图片,里面引用2个自定义方法:
其中__get_img_url用于获取每个图片文件的url,__download_img用于下载每张图片。

__get_img_url方法

主要包括构造发送的参数,返回得到图片数据data

def__get_img_url(self):
        print(
'开始下载.....'
)

        imgs_per_page = 
30
        page_nos = max(
1
, self.max_scrape_img_n // imgs_per_page + 
1
)

        parameters = [{
'tn'
'resultjson_com'
,

'ipn'
'rj'
,

'ct'
201326592
,

'is'
''
,

'fp'
'result'
,

'fr'
''
,

'word'
: self.keyword,

'queryWord'
: self.keyword,

'cl'
''
,

'lm'
''
,

'ie'
'utf-8'
,

'oe'
'utf-8'
,

'adpicid'
''
,

'st'
''
,

'z'
''
,

'ic'
''
,

'hd'
''
,

'latest'
''
,

'copyright'
''
,

's'
''
,

'se'
''
,

'tab'
''
,

'width'
''
,

'height'
''
,

'face'
''
,

'istype'
''
,

'qc'
''
,

'nc'
''
,

'expermode'
''
,

'nojc'
''
,

'isAsync'
''
,

'pn'
30
 * (page_no + 
1
),

'rn'
30
,

'gsm'
'5a'
,

'1642323736936'
''
for
 page_no 
in
 range(page_nos)]


        urls = []

for
 param 
in
 parameters:

try
:

                data = self.__sess.get(self.__original_url, params=param).json().get(
'data'
)

                img_urls = [d[
'thumbURL'
for
 d 
in
 data[:imgs_per_page]]

                urls.extend(img_urls)

except
 json.decoder.JSONDecodeError:

                print(
"解析错误"
)

return
 urls

main

启动一次模块,支持多次对应关键词的图片批量下载:
if
 __name__ == 
'__main__'
:

    bid = BaiduImgDownloader()


whileTrue
:

        keyword = input(
"请输入搜索关键词,按q退出:"
)

if
 keyword == 
'q'
:

break
        img_n = input(
"请输入下载图片数量,默认200(回车即取默认值):"
)

        img_n = 
200ifnot
 img_n 
else
 int(img_n)

        save = input(
"请输入图片保存路径,默认为img(回车即取默认值):"
)

        save = 
'img'ifnot
 save 
else
 save


        bid.downloader(keyword, img_n, save)

项目测试

截止2021年1月16日,测试未发现bug。

完整代码下载

上面完整py代码文件,可以在我的公众号后台回复:c,之前的所有项目代码也都在这个文件夹里:
长按关注,回复c
不用打赏,点个赞或在看

就心满意足了
继续阅读
阅读原文