python:从零开始的百度图片爬虫

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=&copyright=&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=&copyright=&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=&copyright=&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=&copyright=&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的数量
所以我进行了一个测试
(当然也可能和网速有关)
sb
太傻逼了
总之我调到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)

大概就这样了
在这里插入图片描述
在这里插入图片描述

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值