通过关键字从百度中爬取相匹配图片,可以爬取多种也可以爬取一种图片

通过re、requests、urlib、BeautifulSoup、os模块实现从百度下载指定类别图片。包含代码逐行解析。

import re
# 进行http请求的第三方库
import requests
from urllib import error
# 解析HTML和XML文档的库
from bs4 import BeautifulSoup
import os
 
num = 0
numPi = 0
file = ''
List = []
 
def makefile(word):
    file = word + '文件'
    file_na = os.path.exists(file)
    if file_na == 1:
        print('该文件已存在,请重新输入')
        file = input('请建立一个存储图片的文件夹,输入文件夹名称即可: ')
        os.mkdir(file)
    else:
        os.mkdir(file)
    return file

 
# 根据地址去查找 对应的图片的信息
# 获取网页中图片URL函数
# url是目标网页的URL,A是用来发送http请求的类,通常是Request对象
def Find(url, A):
    global List  # 保存信息的列表,保存获取图片的URL
    t = 0           # 请求时间
    i = 1           # 请求次数
    s = 0           # 当前获取到的图片总数
    while t < 60000:
        # 时间戳 不间断刷新访问网址
        # 目标网页的URL与当前时间戳t拼接,形成一个新的url
        Url = url + str(t)
        try:
            # get获取数据,访问拼接后的url
            Result = A.get(Url, timeout=7, allow_redirects=False)
        # 捕获所有请求超时、URL错误等异常
        except BaseException:
            # 每一页有60张图片所以
            t = t + 60
            continue
        else:
            # 拿到网站的数据,捕获到的网页内容给result变量
            result = Result.text
            # 找到图片url,使用正则表达式从网页内容中提取图片url,并将结果赋值给pic_url变量
            pic_url = re.findall('"objURL":"(.*?)",', result, re.S)
            # 图片总数
            # 提取到的图片url数量加到s变量上
            s += len(pic_url)
            # 如果提取到的图片URL数量为 0,表示网页中没有图片,跳出循环
            if len(pic_url) == 0:
                break
            else:
                # 将提取到的图片 URL 添加到 List 列表中。
                List.append(pic_url)
                #  将时间戳 t 增加 60 秒,然后继续循环
                t = t + 60
    return s
 
 
# 记录相关数据
def recommend(url):
    Re = []
    try:
        # 向网页发送一个请求并返回响应
        html = requests.get(url, allow_redirects=False)
    except error.HTTPError as e:
        return
    else:
        html.encoding = 'utf-8'
        # html文件解析,解析响应的文件内容,html.text 是 HTML 文档的源代码,
        # 'html.parser' 是解析器,用于指定如何解析 HTML 文档
        bsObj = BeautifulSoup(html.text, 'html.parser')
        # 找到页面中id为topsRS的div元素
        div = bsObj.find('div', id='topRS')
        # 从该div元素中找到所有a的标签,并提取其中文本内容
        if div is not None:
            listA = div.findAll('a')
            for i in listA:
                if i is not None:
                    Re.append(i.get_text())
        return Re
 
 
# 下载图片
def dowmloadPicture(html, keyword):
    # 记录已经下载的图片数量
    global num
    # 找到图片url
    # 正则表达式从 HTML 中提取所有包含图片 URL 的字符串。re.S 参数表示使正则表达式对大小写不敏感。
    # (.*?):这是一个捕获组,用于匹配括号内的内容。点号(.)表示匹配任意字符,*? 表示匹配任意数量的字符,匹配一个引号、匹配一个逗号
    # 查找 html 中所有以 "objURL" 开头,并且以双引号和逗号结尾的字符串,并将这些字符串作为匹配结果返回
    pic_url = re.findall('"objURL":"(.*?)",', html, re.S)
    print('找到:' + keyword + '的图片,开始下载....')
    # 遍历图片的url
    for each in pic_url:
        print('正在下载第' + str(num + 1) + '张图片,图片地址:' + str(each))
        # 处理异常,主要处理图片下载失败的情况
        try:
            if each is not None:
                # 请问时间不能超过7s
                pic = requests.get(each, timeout=7)
            else:
                continue
        except BaseException:
            print('错误,当前图片无法下载')
            continue
        else:
            # 构建图片保存路径
            string = file + r'\\' + str(num) + '.jpg'
            # 以二进制写入模式打开新建文件
            fp = open(string, 'wb')
            # 将下载的图片内容写入文件
            fp.write(pic.content)
            # 关闭文件
            fp.close()
            # 已经下载一张图片加1
            num += 1
        # 检查是否已经下载所有需要下载的图片
        if num >= numPi:
            return
 
 
if __name__ == '__main__':  # 主函数入口
    # 模拟浏览器 请求数据 伪装成浏览器向网页提取服务,有的网站识别出你是python就会拒绝
    # 请求头是在发送http请求时,由客户端向服务器发送一些元数据,描述请求的特性和客户端的能力
    # 请求头通常由浏览器自动设置,也可由程序(python)脚本手动设置
    # 返回的文档语言,客户端和服务端建立一个持久的连接,客户端的身份,客户端是否愿意升级不安全的请求
    headers = {
        'Accept-Language': 'zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2',
        'Connection': 'keep-alive',
        'User-Agent': 'Mozilla/5.0 (X11; Linux x86_64; rv:60.0) Gecko/20100101 Firefox/60.0',
        'Upgrade-Insecure-Requests': '1'
    }
 
    # 创建一个请求的会话
    A = requests.Session()
    # 设置头部信息
    A.headers = headers
    choice = int(input("请问需要搜索多类图片还是单类图片?如果是单类请输入0,如果是多类请输入1:"))
    if choice == int(0):
        word = input("输入要搜索的关键词:")
        numPi = int(input('输入要下载的数量:'))
        # 拼接路径
        url = 'https://image.baidu.com/search/flip?ct=201326592&cl=2&st=-1&lm=-1&nc=1&ie=utf-8&tn=baiduimage&ipn=r&rps=1&pv=&fm=rs1&word=' + word
 
        # 根据路径去查找
        total = Find(url, A)
        # 记录相关推荐图片
        Recommend = recommend(url)
        print('经过检测%s类图片共有%d张' % (word, total))
        file = makefile(word)

        t = 0
        tmp = url
    
        while t < numPi:
            try:
                url = tmp + str(t)
                result = requests.get(url, timeout=10)
                print(url)
            except error.HTTPError as e:
                print('网络错误,请调整网络后重试')
                t = t + 60
            else:
                dowmloadPicture(result.text, word)
                t = t + 60

    else: 
        tm = int(input('请输入每类图片的下载数量 '))
        numPi = tm
        line_list = []
        with open('./name.txt', encoding='utf-8') as file:
            line_list = [k.strip() for k in file.readlines()]  # 用 strip()移除末尾的空格
        for word in line_list:
            #url = 'https://image.baidu.com/search/flip?ct=201326592&cl=2&st=-1&lm=-1&nc=1&ie=utf-8&tn=baiduimage&ipn=r&rps=1&pv=&fm=rs1&word=' + word
            url = 'https://image.baidu.com/search/flip?tn=baiduimage&ie=utf-8&word=' + word + '&pn='
            tot = Find(url,A)
            Recommend = recommend(url)  # 记录相关推荐
            print('经过检测%s类图片共有%d张' % (word, tot))
            file = makefile(word)
            
            t = 0
            tmp = url
            while t < numPi:
                try:
                    url = tmp + str(t)
                    result = A.get(url, timeout=10, allow_redirects=False)
                    print(url)
                except error.HTTPError as e:
                    print('网络错误,请调整网络后重试')
                    t = t + 60
                else:
                    dowmloadPicture(result.text, word)
                    t = t + 60

            numPi = numPi + tm
        

你可能感兴趣的:(爬虫,python,beautifulsoup)