python 爬取bing,百度检索到图片
一、前言
??我在进行视觉AI的训练时候,发现没有啥数据集是完美包含我要的类别,思来索去还是直接爬取互联网上的来的香。 ??检索图片的质量上就谷歌,bing,百度比较多也比较好,sogou和360做了些反爬,我突破不了就算了,谷歌需要翻墙比较麻烦。最终图片数据来源目标就定在bing和百度了。 ??谷歌爬取图片有需要的可以尝试一波
二、爬取百度引擎检索的图片程序设计
1、百度网页源码分析:检索网页源码中的哪个属性包含图片url
F12----》选择网络----》选择XHR----》F5刷新页面 点击抓包的请求----》预览
获取信息分析如下:
- 通过对属性middleURL的模式匹配得到图片的地址
- 每次请求,可以获取30个图片的下载地址
2、百度网页源码分析:根据上一步获取的属性middleURL寻找re模式
下载当前页面的网页源码
保存到txt文档中----》ctrl+F检索属性middleURL 获取信息分析如下:
- url就在属性middleURL的后面,且都有固定的格式
- 获取匹配图片url模式:r’“middleURL”:“(.*?)”’
3、百度网页源码分析:对比不同请求的链接差异
目的:以此达到自动“翻页”下载的效果
点击不同的请求,复制三个链接地址 粘贴到一个txt文档中进行对比 这样我们就知道怎么“伪造请求”了
4、爬取百度图片的程序设计
程序设计思路
- 创建文件夹,并将当前目录转化到该文件夹
- 根据模式r’“middleURL”:“(.*?)”',设计一个函数geturls,获取当前请求内的全部图片urls
- 设计函数DownloadImg(),输入urls,对每一个urls,进行访问并下载
- 如果下载图片个数达到定义的数量就自动终止
import re
import time
import requests
from urllib import parse
import os
import random
from fake_useragent import UserAgent
import urllib3
'''
函数功能
返回一个url页面里面全部图片超链接的列表
'''
dic={'bing':r'img.*src="(.*?)"','baidu':r'"middleURL":"(.*?)"','sogou':r'img.*src="(.*?)"','360':r'"img":"(.*?)"'}
def writeHtml(url,html):
with open(url,'w',encoding='utf-8') as f:
f.write(str(html))
def geturls(baseurl,enginPattern):
Img = re.compile(enginPattern)
headers ={'User-Agent':UserAgent().random}
urllib3.disable_warnings()
response = requests.get(baseurl, headers=headers)
html = response.text
data=re.findall(Img, html)
return data
def DownloadImg(imgUrls):
global i
headers={'User-Agent':UserAgent().random}
for ImgUrl in imgUrls:
if i < imgNum:
try:
resp = requests.get(ImgUrl, headers=headers)
except requests.ConnectionError as e:
continue
byte = resp.content
with open("{:0>4d}.jpg".format(i + 1), "wb") as f:
if resp.status_code==200 and len(str(byte)) > 1000 :
f.write(byte)
i = i + 1
time.sleep(0.5)
print("第{}张与{}有关的图片爬取成功!".format(i, search))
else:
break
search=input('请输入检索词:')
imgNum=int(input('请输入爬取图片数量:'))
engine='baidu'
i=0
def main():
if not os.path.isdir("./{}_{}".format(search,engine)):
os.mkdir("./{}_{}".format(search,engine))
os.chdir("./{}_{}".format(search,engine))
global i
while(i<imgNum):
for index in range(10000):
decteUrl='https://image.baidu.com/search/acjson?tn=resultjson_com&logid=7542812996841482750&ipn=rj&ct=201326592&is=&fp=result&fr=&word={}&queryWord={}&cl=2&lm=-1&ie=utf-8&oe=utf-8&adpicid=&st=-1&z=&ic=0&hd=&latest=©right=&s=&se=&tab=&width=&height=&face=0&istype=2&qc=&nc=1&expermode=&nojc=&isAsync=&pn={}&rn=30&gsm=1e&{}='.format(parse.quote(search),parse.quote(search),index*30,str(int(time.time()*1000)))
imgUrls=geturls(decteUrl,dic[engine])
DownloadImg(imgUrls)
if i>=imgNum:
break
if(i==imgNum):
print("已基于搜索引擎{}爬取了{}张与{}相关的图片,保存在文件夹{}\{}_{}".format(engine,imgNum,search,os.getcwd(),search,engine))
if __name__ == '__main__':
main()
三、利用字典综合bing、百度两个引擎爬取图片的程序设计
1、检索bing对当前页面html中匹配到图片链接的模式
F12查看当前网络源码,利用当鼠标移动到那个块,哪个块就会高亮标记的特点 锁定,该图片所对应的块,
将其复制到txt文件中 获取信息分析如下:
- 从html中获取图片的地址,模式为:‘’‘<img class=“mimg vi.src="(.?)”’
注:这个模式,有时候是比较随心的,就是看着匹配
2、检索bing如何,调控链接来实现翻页
在源码中查询,不同请求链接的差别 将不同请求粘贴到txt文本中对比,差异。 获取信息分析如下:
3、源码
思路:
- 在之前爬取百度图片的基础上,加入dicPattern字典,和dicUrl字典,分别保存从网页源码中搜索图片地址的模式,bing和百度的链接
import re
import time
import requests
from urllib import parse
import os
from fake_useragent import UserAgent
import urllib3
class ImgGenerate:
def __init__(self,engine,search,maxNum,outFile):
self.dicPattern={'bing':r'<img class="mimg vi.*src="(.*?)"','baidu':r'"middleURL":"(.*?)"','sogou':r'img.*src="(.*?)"','360':r'"img":"(.*?)"'}
self.dicUrl={'bing':'https://cn.bing.com/images/search?q={}&form=HDRSC2&first={}&tsc=ImageHoverTitle','baidu':'https://image.baidu.com/search/acjson?tn=resultjson_com&logid=7542812996841482750&ipn=rj&ct=201326592&is=&fp=result&fr=&word={}&queryWord={}&cl=2&lm=-1&ie=utf-8&oe=utf-8&adpicid=&st=-1&z=&ic=0&hd=&latest=©right=&s=&se=&tab=&width=&height=&face=0&istype=2&qc=&nc=1&expermode=&nojc=&isAsync=&pn={}&rn=30&gsm=1e&{}='}
self.engine = engine
self.search =search
self.Dowdnum=0
self.imgNum =maxNum
self.outFile=outFile
try:
os.chdir(self.outFile)
if not os.path.isdir("./{}_{}".format(search,engine)):
os.mkdir("./{}_{}".format(search,engine))
os.chdir("./{}_{}".format(search,engine))
except:
print("请输入正常的检索词")
'''
函数功能
输入一个地址和,网页源码,
将源码写入txt文本,便于浏览
'''
def writeHtml(self,outfile,html):
with open(outfile,'w',encoding='utf-8') as f:
f.write(str(html))
'''
函数功能
返回一个url页面里面全部图片超链接的列表
'''
def geturls(self,baseurl,enginPattern):
ImgUrlPattern = re.compile(enginPattern)
headers ={'User-Agent':UserAgent().random}
urllib3.disable_warnings()
response = requests.get(baseurl, headers=headers)
html = response.text
data=re.findall(ImgUrlPattern, html)
return data
'''
函数功能:
遍历输入的图像urls
并将其下载下来
'''
def DownloadImg(self,imgUrls):
headers={'User-Agent':UserAgent().random}
for ImgUrl in imgUrls:
if self.Dowdnum < self.imgNum:
try:
resp = requests.get(ImgUrl, headers=headers)
except requests.ConnectionError as e:
continue
byte = resp.content
with open("{:0>5d}.jpg".format(self.Dowdnum + 1), "wb") as f:
if resp.status_code==200 and len(str(byte)) > 1000 :
f.write(byte)
self.Dowdnum = self.Dowdnum + 1
time.sleep(0.5)
print("第{}张与{}有关的图片爬取成功!".format(self.Dowdnum, self.search))
else:
break
def run(self):
while(self.Dowdnum<self.imgNum):
for index in range(10000):
if self.engine=='baidu':
decteUrl=self.dicUrl[self.engine].format(parse.quote(self.search),parse.quote(self.search),index*30,str(int(time.time()*1000)))
elif self.engine=='bing':
decteUrl=self.dicUrl[self.engine].format(self.search,index*35)
imgUrls=self.geturls(decteUrl,self.dicPattern[self.engine])
self.DownloadImg(imgUrls)
if self.Dowdnum>=self.imgNum:
break
if(self.Dowdnum==self.imgNum):
print("已基于搜索引擎{}爬取了{}张与{}相关的图片,保存在文件夹{}".format(self.engine,self.imgNum,self.search,os.getcwd()))
engine='bing'
def ImgGenerate(search,imgNum,File):
pass
def setOutFile(self,outFile):
self.outFile=outFile
def main():
print('有效的引擎有:bing,baidu')
engine = input('请输入引擎:')
search = input('请输入检索词:')
imgNum = int(input('请输入爬取图片数量:'))
outFile=os.getcwd()
ImgG = ImgGenerate(engine,search,imgNum,outFile)
ImgG.run()
if __name__ == '__main__':
main()
四、完结撒花
1、运行截图
运行如上 还缺一个基于MD5码的图片自动去重。这个我在软件,以及随后的github中再添加了
2、自动爬取图片的软件
图片爬虫到这里就结束了 我准备开发一个爬虫软件,到时候会放在着,就不需要配环境了 等我两天好吧,效率 我先去学Qt
五、补充
1、下载原图设计过程
注:由于直接在搜索引擎上下载的图片,都经过了搜索引擎的压缩,模糊,每张大小10k左右,这样很明显不能很好的满足我们的需求。 为此我们需要加一步,进去然后再加载 大体步骤跟上面差不多。下载网页源码,进行分析,然后找出特性,进去再加载即可
a、如何在bing源码中直接下载原图
慢慢看网页源码可以找到如上,地址映射,我们要的是直接下载原图也就是murl后面的的地址,我找了30多分钟,有点忧伤,应该是不熟练的缘故:https://img.zcool.cn/community/016f405d2b3735a80120b5ab031177.jpg@1280w_1l_2o_100sh.jpg 这个就是我们要的。
获取信息分析如下:
- bing真正下载原图的正则表达式:
murl":"(.*?)& 将这个模式,替换掉原来的即可b、如何在baidu源码中直接下载原图
获取信息分析如下:
- baidu真正下载原图的正则表达式:
"thumbURL":"(.*?)" 将这个模式,替换掉原来的即可
2、源码
import re
import time
import requests
from urllib import parse
import os
from fake_useragent import UserAgent
class ImgGenerate:
def __init__(self,engine,search,maxNum,outFile):
self.dicPattern={'bing':r'<img class="mimg vi.*src="(.*?)"','baidu':r'"middleURL":"(.*?)"'}
self.dicPatternEr = {'bing': r'murl":"(.*?)&', 'baidu': r'"thumbURL":"(.*?)"'}
self.dicUrl={'bing':'https://cn.bing.com/images/search?q={}&form=HDRSC2&first={}&tsc=ImageHoverTitle','baidu':'https://image.baidu.com/search/acjson?tn=resultjson_com&logid=7542812996841482750&ipn=rj&ct=201326592&is=&fp=result&fr=&word={}&queryWord={}&cl=2&lm=-1&ie=utf-8&oe=utf-8&adpicid=&st=-1&z=&ic=0&hd=&latest=©right=&s=&se=&tab=&width=&height=&face=0&istype=2&qc=&nc=1&expermode=&nojc=&isAsync=&pn={}&rn=30&gsm=1e&{}='}
self.engine = engine
self.search =search
self.Dowdnum=0
self.imgNum =maxNum
self.outFile=outFile
try:
os.chdir(self.outFile)
if not os.path.isdir("./{}_{}".format(search,engine)):
os.mkdir("./{}_{}".format(search,engine))
os.chdir("./{}_{}".format(search,engine))
except:
print("请输入正常的检索词")
'''
函数功能
输入一个地址和,网页源码,
将源码写入txt文本,便于浏览
'''
def writeHtml(self,outfile,html):
with open(outfile,'w',encoding='utf-8') as f:
f.write(str(html))
'''
函数功能
返回一个url页面里面全部图片超链接的列表
'''
def geturls(self,baseurl,enginPattern):
ImgUrlPattern = re.compile(enginPattern)
headers ={'User-Agent':UserAgent().random}
response = requests.get(baseurl, headers=headers)
html = response.text
data=re.findall(ImgUrlPattern, html)
return data
'''
函数功能:
遍历输入的图像urls
并将其下载下来
'''
def DownloadImg(self,imgUrls):
headers={'User-Agent':UserAgent().random}
for ImgUrl in imgUrls:
if self.Dowdnum < self.imgNum:
try:
resp = requests.get(ImgUrl, headers=headers)
except requests.ConnectionError as e:
continue
byte = resp.content
with open("{:0>5d}.jpg".format(self.Dowdnum + 1), "wb") as f:
if resp.status_code==200 and len(str(byte)) > 1000 :
f.write(byte)
self.Dowdnum = self.Dowdnum + 1
time.sleep(0.5)
print("第{}张与{}有关的图片爬取成功!".format(self.Dowdnum, self.search))
else:
break
def run(self):
while(self.Dowdnum<self.imgNum):
for index in range(10000):
if self.engine=='baidu':
decteUrl=self.dicUrl[self.engine].format(parse.quote(self.search),parse.quote(self.search),index*30,str(int(time.time()*1000)))
elif self.engine=='bing':
decteUrl=self.dicUrl[self.engine].format(self.search,index*35)
imgUrls=self.geturls(decteUrl,self.dicPatternEr[self.engine])
self.DownloadImg(imgUrls)
if self.Dowdnum>=self.imgNum:
break
if(self.Dowdnum==self.imgNum):
print("已基于搜索引擎{}爬取了{}张与{}相关的图片,保存在文件夹{}".format(self.engine,self.imgNum,self.search,os.getcwd()))
engine='bing'
def ImgGenerate(search,imgNum,File):
pass
def setOutFile(self,outFile):
self.outFile=outFile
def Down_One_Img(url):
header={'User-Agent':UserAgent().random}
html=requests.get(url,headers=header).content
print(os.getcwd())
with open('../Images/10001.jpg','wb')as w:
w.write(html)
def main():
print('有效的引擎有:bing,baidu')
engine = input('请输入引擎:')
search = input('请输入检索词:')
imgNum = int(input('请输入爬取图片数量:'))
outFile=os.getcwd()
ImgG = ImgGenerate(engine,search,imgNum,outFile)
ImgG.run()
if __name__ == '__main__':
main()
六、图片爬虫软件exe下载与全部源码开源GitHub地址
在开发了最迟明天好伐
|