怎样用Pyhon编写爬虫程序,下载1000张鹿晗图片?其实很简单,不到50行代码就能实现任意关键词的批量图片抓取。
编码工具
推荐安装Anaconda,然后使用它自带的JupyterNotebook即可。其次推荐使用VS Code工具,也可以使用Pycharm或者其他。
地址分析
先打开百度图片搜索“鹿晗”,可以搜到很多小图,往下滚动页面的时候会自动加载新的一批小图,所以第一步是怎么一批批的搞到小图。点击小图可以打开大图,真正大图的链接地址是附在小图上的。所以第二步我们要找到每个小图上面的大图链接地址,然后下载这个大图保存。
谷歌浏览器中,页面图片上【右键-检查】打开开发工具,选【Network】选项卡,点击红色按钮右边的那个禁止按钮清空记录。然后鼠标往下滚动,可以看到出现很多新的信息,带你【Type】类型我们只找xhr
格式的,点击看一下。
点击一个xhr
邮件可以复制这个链接的地址,如下图所示。
可以把这个地址粘贴到Notebook里面仔细看一下,如下图,每个xhr
的pn
值不同,总是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=©right=&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
之类,大家可以自己尝试探索。
欢迎关注我的专栏( つ•̀ω•́)つ【人工智能通识】
每个人的智能新时代
如果您发现文章错误,请不吝留言指正;
如果您觉得有用,请点喜欢;
如果您觉得很有用,欢迎转载~
网友评论