美文网首页Python软件技巧
用Python爬虫批量下载百度图片

用Python爬虫批量下载百度图片

作者: zhyuzh3d | 来源:发表于2020-05-24 19:47 被阅读0次

    怎样用Pyhon编写爬虫程序,下载1000张鹿晗图片?其实很简单,不到50行代码就能实现任意关键词的批量图片抓取。

    编码工具

    推荐安装Anaconda,然后使用它自带的JupyterNotebook即可。其次推荐使用VS Code工具,也可以使用Pycharm或者其他。

    地址分析

    先打开百度图片搜索“鹿晗”,可以搜到很多小图,往下滚动页面的时候会自动加载新的一批小图,所以第一步是怎么一批批的搞到小图。点击小图可以打开大图,真正大图的链接地址是附在小图上的。所以第二步我们要找到每个小图上面的大图链接地址,然后下载这个大图保存。

    谷歌浏览器中,页面图片上【右键-检查】打开开发工具,选【Network】选项卡,点击红色按钮右边的那个禁止按钮清空记录。然后鼠标往下滚动,可以看到出现很多新的信息,带你【Type】类型我们只找xhr格式的,点击看一下。

    点击一个xhr邮件可以复制这个链接的地址,如下图所示。

    可以把这个地址粘贴到Notebook里面仔细看一下,如下图,每个xhrpn值不同,总是30-60-90-120这样变化,就是说我们每次往下滚动一下,就出现一个xhr请求,每个xhr请求会获取30个小图。除了pn还有两个乱码的搜索词queryWord,word,它们的乱码就是中文的鹿晗。另外一个有趣的是face,如果它是1那么就只抓去有人脸的图片,只有后脑勺的图片不要。

    回到浏览器开发工具,点击【Preview】数据预览,可以看到data下面有大概30个数据,每个数据代表一个鹿晗小图信息。

    仔细看其中一个信息,并把地址类型的文字复制到浏览器窗口查看,就会发现真正的大图链接地址在【replaceURL】的第2个(1号)数据的【ObjectURL】,如下图所示的那个地址就是大图地址。

    抓一次30张的函数

    先写一个批量抓取的函数getBNaiduImgs(word,pn,face=0),这个函数的作用就是根据pn抓取30张鹿晗图片,当然也可以是吴亦凡图片,关键看word

    import time
    import requests
    import json
    import urllib
    import os
    
    def getBaiduImgs(word,pn,face=0):  #根据不同的pn数字获取并保存批量图片
        url = f'http://image.baidu.com/search/acjson?tn=resultjson_com&ipn=rj&ct=201326592&is=&fp=result&queryWord={word}&cl=2&lm=-1&ie=utf-8&oe=utf-8&adpicid=&st=&z=9&ic=&hd=&latest=&copyright=&word={word}&s=&se=&tab=&width=0&height=0&face={face}&istype=&qc=&nc=1&fr=&expermode=&force=&pn={pn}&rn=30&gsm=3c&1590168124018='#复制百度图片网页开发面板Network里的xhr对应的RequestURL类似地址,替换pn={pn}word={word}
        folderPath=f'{os.getcwd()}/imgs/{word}/'
        if not os.path.exists(folderPath):
            os.makedirs(folderPath)
        
        res = requests.get(url, timeout=3)  #获取上面地址对应的批量缩略图数据    
        resjson = ''
        try:
            resjson = json.loads(res.text.replace('\\\'',''))  #解析批量缩略图数据
        except ValueError:
            print(f'>>JSON ERR:{ValueError}')
            return
    
        for m in resjson['data']:  #针对每个缩略图信息执行下面内容
            #为了防止出错,要检查各个数据都正常存在
            if ('replaceUrl' in m) and (len(m['replaceUrl'])>1) and ('ObjURL' in m['replaceUrl'][1]):
                imgurl = m['replaceUrl'][1]['ObjURL'].split('?')[0]  #获取真正的图片地址
                fname = str(random.random()).replace('0.','')+'.jpg' #随机文件名
                if imgurl.split('/')[-1]: 
                    fname=imgurl.split('/')[-1]  #图片地址中最后一个斜杠后面的,就是图片文件名,类似http:.../adf.jpg
                    if fname.find('.')==-1:
                        fname=fname+'.jpg'
                print(f'正在抓取:{imgurl}') 
                
                try:
                    imgres = requests.get(imgurl,timeout=3)
                    if sys.getsizeof(imgres.content)>15000:
                        with open(f'imgs/{word}/{fname}','wb') as f:  #打开即新建一个图片文件,wb,write binnary
                            f.write(imgres.content)  #写入文件,即保存
                            time.sleep(1)  #获取每张图片后停一下
                except Exception as e:
                    msg=e.message if (hasattr(e, 'message')) else e
                    print(f'>>抓取失败:{imgurl}\n{msg}')
                    pass 
        return url
    

    上面的代码里有很多注释,这里就不重复解释啦。总之,有很多图片链接其实已经失效是打不开的,还有很多是假的图片,比如那种白色的网站占位小图,所以加了很多判断,还判断了图片的大小要大于15k才保存。

    总之,虽然有30个链接,但可能抓到的合格图片只有十几张。

    如果要明确限制抓1000张结束,那么就不能根据小图链接的数量判断结束抓取,而是根据文件夹中图片的数量来判断。但还是会有不少不合格的图片,比如白图或者抓到了关晓彤的图片。

    批量抓取

    这个代码很简单,不解释。

    for i in range(0, 120, 30): #[0,30,60,90,120]
        print('>> GETTING', i)
        getBaiduImgs('鹿晗',i,1) #使用上面的函数
    print('>> ALL OK!')
    

    运行起来的话偶尔会有抓取失败的情况,慢慢等十几分钟就能够下载上千张图片啦!

    那个xhr地址其实还有更多参数,比如限制宽高weight,height之类,大家可以自己尝试探索。


    欢迎关注我的专栏( つ•̀ω•́)つ【人工智能通识】

    每个人的智能新时代

    如果您发现文章错误,请不吝留言指正;
    如果您觉得有用,请点喜欢;
    如果您觉得很有用,欢迎转载~

    相关文章

      网友评论

        本文标题:用Python爬虫批量下载百度图片

        本文链接:https://www.haomeiwen.com/subject/jxwjahtx.html