python百度图片爬虫
最近打算尝试接触人工智障,于是发现需要先搞到数据集,制作数据集又需要带量数据
我打算先搞个图片判断的,类似于看有没有猫这种
所以我需要数据集,需要图片,需要很多很多图片
所以我想搞个百度图片的爬虫,比较方便的那种
首先,我去看了网页的源码,直接用百度图片的网站搜索“东京”
https://image.baidu.com/search/index?tn=baiduimage&ipn=r&ct=201326592&cl=2&lm=-1&st=-1&fm=result&fr=&sf=1&fmq=1595357021616_R&pv=&ic=&nc=1&z=&hd=&latest=©right=&se=1&showtab=0&fb=0&width=&height=&face=0&istype=2&ie=utf-8&sid=&word=%E4%B8%9C%E4%BA%AC
然后发现搜索不同的词,变化的只是最后一个的word后面的一串东西
当然那一串是“东京”的url编码,用urllib.parse
里面的parse.quote(word)
可以搞定
于是用requests
模块的
data_all = requests.get(rooturl)
data_all.encoding = 'utf8'
print(str(data_all.content))
看了看,并弄了个简单的正则表达式获取其中url
还蛮顺利,不用搞headers那些
结果得了个空集。。。
于是我发现我get到的代码和浏览器上显示的源码不一样🤮🤮
查了百度,好像是因为我get的是服务器发过来的源码,和浏览器解析过的不一样
而且这个方法好像也get不到多少图片
百度图片是瀑布式的,往下拉它的url还不会改变
是时候查看网络了,就是f12后里边有个网络选项,点进去,刷新页面,再往下拉,的确最先有一个index的url,然后都是图片的url,然后在一堆图片url中,发现了一个不一样的url
https://image.baidu.com/search/acjson?tn=resultjson_com&ipn=rj&ct=201326592&is=&fp=result&queryWord=%E4%B8%9C%E4%BA%AC&cl=2&lm=-1&ie=utf-8&oe=utf-8&adpicid=&st=-1&z=&ic=&hd=&latest=©right=&word=%E4%B8%9C%E4%BA%AC&s=&se=&tab=&width=&height=&face=0&istype=2&qc=&nc=1&fr=&expermode=&force=&pn=0&rn=0&gsm=78&1595357380029=
而且每次图片新加载,这条都会出现
可以确定图片的url就在这里面了
于是可以获得包含图片连接的url了
needurl = "https://image.baidu.com/search/acjson?tn=resultjson_com&ipn=rj&ct=201326592&is=&fp=result&queryWord="+uriword+"&cl=2&lm=-1&ie=utf-8&oe=utf-8&adpicid=&st=-1&z=&ic=&hd=&latest=©right=&word="+uriword+"&s=&se=&tab=&width=&height=&face=0&istype=2&qc=&nc=1&fr=&expermode=&force=&pn="+str(page)+"&rn=30&gsm=78&1595357380029="
pn是搞翻页的,(rn好像是步长(每一页 的图片数)?改动之后对速度影响不大,还是按原来的好一点),uriword是经过url编码的要搜索的词汇
好像同样的代码,每次爬到的图片都多少有点出入
总之,开始编码
import requests
from urllib import parse
import re
import os
import time
from concurrent.futures import ThreadPoolExecutor, as_completed
从包含图片连接的url中提取图片连接
'''可以选择需要图片的数量'''
def getImagesLinks(word, num):
images_links = []
page = 30
uriword = parse.quote(word)
rec_num = 0
while True:
needurl = "https://image.baidu.com/search/acjson?tn=resultjson_com&ipn=rj&ct=201326592&is=&fp=result&queryWord="+uriword+"&cl=2&lm=-1&ie=utf-8&oe=utf-8&adpicid=&st=-1&z=&ic=&hd=&latest=©right=&word="+uriword+"&s=&se=&tab=&width=&height=&face=0&istype=2&qc=&nc=1&fr=&expermode=&force=&pn="+str(page)+"&rn=30&gsm=78&1595357380029="
page += 30
print(needurl)
data_all = requests.get(needurl)
data_all.encoding = 'utf8'
pat01 = '"thumbURL":"([\\s\\S]*?)"'
res0 = re.compile(pat01).findall(str(data_all.content))
for item in res0:
print(item)
images_links.append(item)
rec_num += 1
print(rec_num)
if rec_num == num:
return images_links
下载所有图片:
当然,这里用了线程池,如果不用,爬1000张图要80-100+秒,用了整个程序就20秒左右
我们需要一个比较好的max_worker的数量
所以我进行了一个测试
(当然也可能和网速有关)
太傻逼了
总之我调到100个
def downLoadImages(links, name, path=None, speedup=False):
''' 检查文件夹是否建立,并建立文件夹 '''
if path == None:
tar = os.path.exists(os.getcwd()+"\\"+name)
if not tar:
os.mkdir(os.getcwd()+"\\"+name)
im_path = os.getcwd()+"\\"+name+"\\"
else:
tar = os.path.exists(path+"\\"+name)
if not tar:
os.mkdir(path+"\\"+name)
im_path = path+"\\"+name+"\\"
def get_pic(pic_path, pic_link):
'''本来想防止重复爬的,但每次爬到的都有点不同,所以好像没什么用'''
tar = os.path.exists(pic_path)
if not tar:
res = requests.get(pic_link).content
with open(pic_path, "wb") as pic_object:
pic_object.write(res)
executor = ThreadPoolExecutor(max_workers=90)
all_tasks = []
for i in range(1, len(links)+1):
task = executor.submit(get_pic, im_path + str(i) + ".jpg", links[i-1])
all_tasks.append(task)
for future in as_completed(all_tasks):
data = future.result()
print("get {} page".format(data))
程序入口
if __name__ == "__main__":
links = getImagesLinks("东京", 1000)
start_time = time.time()
downLoadImages(links, "tokyo10")
print(time.time()-start_time)
大概就这样了