Python爬虫系列(二)——Python爬虫批量下载百度图片

2023-11-04

1. 前言

先贴代码

# -*- coding:utf8 -*-
import requests
import json
from urllib import parse
import os
import time


class BaiduImageSpider(object):
    def __init__(self):
        self.json_count = 0  # 请求到的json文件数量(一个json文件包含30个图像文件)
        self.url = 'https://image.baidu.com/search/acjson?tn=resultjson_com&logid=5179920884740494226&ipn=rj&ct' \
                   '=201326592&is=&fp=result&queryWord={' \
                   '}&cl=2&lm=-1&ie=utf-8&oe=utf-8&adpicid=&st=-1&z=&ic=0&hd=&latest=&copyright=&word={' \
                   '}&s=&se=&tab=&width=&height=&face=0&istype=2&qc=&nc=1&fr=&expermode=&nojc=&pn={' \
                   '}&rn=30&gsm=1e&1635054081427= '
        self.directory = r"C:\Users\cun\Pictures\download\{}"  # 存储目录  这里需要修改为自己希望保存的目录  {}不要丢
        self.header = {
            'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) '
                          'Chrome/95.0.4638.54 Safari/537.36 Edg/95.0.1020.30 '
        }

    # 创建存储文件夹
    def create_directory(self, name):
        self.directory = self.directory.format(name)
        # 如果目录不存在则创建
        if not os.path.exists(self.directory):
            os.makedirs(self.directory)
        self.directory += r'\{}'

    # 获取图像链接
    def get_image_link(self, url):
        list_image_link = []
        strhtml = requests.get(url, headers=self.header)  # Get方式获取网页数据
        jsonInfo = json.loads(strhtml.text)
        for index in range(30):
            list_image_link.append(jsonInfo['data'][index]['thumbURL'])
        return list_image_link

    # 下载图片
    def save_image(self, img_link, filename):
        res = requests.get(img_link, headers=self.header)
        if res.status_code == 404:
            print(f"图片{img_link}下载出错------->")
        with open(filename, "wb") as f:
            f.write(res.content)
            print("存储路径:" + filename)

    # 入口函数
    def run(self):
        searchName = input("查询内容:")
        searchName_parse = parse.quote(searchName)  # 编码

        self.create_directory(searchName)

        pic_number = 0  # 图像数量
        for index in range(self.json_count):
            pn = (index+1)*30
            request_url = self.url.format(searchName_parse, searchName_parse, str(pn))
            list_image_link = self.get_image_link(request_url)
            for link in list_image_link:
                pic_number += 1
                self.save_image(link, self.directory.format(str(pic_number)+'.jpg'))
                time.sleep(0.2)  # 休眠0.2秒,防止封ip
        print(searchName+"----图像下载完成--------->")


if __name__ == '__main__':
    spider = BaiduImageSpider()
    spider.json_count = 10   # 定义下载10组图像,也就是三百张
    spider.run()

如果要使用上述程序的话,需要修改两个地方

  • self.directory 这是本地存储地址,修改为自己电脑的地址,另外,**{}**不要删
  • spider.json_count = 10 这是下载的图像组数,一组有30张图像,10组就是三百张,根据需求下载

也可以去gitee仓库直接下载程序。

关于python爬虫入门,如何查看网页源码,可以参考我的另一篇文章 点击跳转

2. Python爬虫批量下载百度图片

流程:先分析页面,然后写爬虫程序。

打开“百度图片”,随便搜索一个词汇,例如玫瑰,可以查询到相关的图片

image-20211024132137388

  1. 分析页面

点击鼠标右键–>检查–元素,先找到第一层div

image-20211024132532939

然后往下找,可以找到一堆li,也就是以列表排列的元素,经研究发现,每个li代表一个模块,每个模块包含图像和下面的字,实际上,下面的字也带有相应链接,点击可以跳转到新页面。

image-20211024132811181

可以先数一下,包含前面的广告图片,总共也就二十多个li,也就是只包含了二十多张图像。

根据使用经验来看,鼠标滚轮下滚,会看到源源不断的图像,并不局限于二十多张图像,那么我们先下滚鼠标滚轮,看看会发生什么。(此时只有一个类名为“imgpage”的div

image-20211024134004366

鼠标滚轮下滚,类名为“imgpage”的div增加了很多,继续下滚,还会继续增加。

image-20211024134201075

由此可以得出一个结论,“百度图片”初始只会渲染部分图像到页面上,随着滚轮下滚,就会请求新的数据。而请求数据,就可以在“网络“中获取请求信息,

image-20211024134634136

打开”网络“,可以发现请求的数据非常非常多,而我们只想找刚刚请求的图像数据。

这里再了解一个新技术–XHR,关于XHR,推荐一篇文章XHR-点击跳转,简单来说,在XHR之前,网页要获取客户端和服务器的任何状态更新,都需要刷新一次,而XHR可以不用刷新就请求到新的数据。刚才的下滚鼠标滚轮并没有刷新界面信息。

打开”网络“中的【XHR】,这里的数据都是通过XHR请求到的,通过名称可以初步判断出,请求到的文件是json格式的。

image-20211024135256750

随便点开一个文件,查看请求的url,可以发现,url很长

image-20211024135458608

比对以下不同文件的请求url,可以发现两个【pn】和【gsm】不同(gsm可以不用管它,这是通信系统)

image-20211024135832630

对比多个文件,可以看到特点:

  • pn:30
  • pn:60
  • pn:90
  • ……

下滚鼠标滚轮,会添加一个新的json文件,实际上,pn表示一组数据,一组数据包含30个图像内容,也就是第一次请求会得到30个图像,再次请求会得到另外30个图像。

现在已经分析出查询同种类型图像的url特点,那么不同类型的请求url呢?

这里又查询了一下”向日葵“,,pn也是按30、60、90进行排列的。对比”玫瑰“和”向日葵“的请求url,不同的属性增加了【logid】、【queryWord】、【word】,而【queryWord】和【word】的信息是相同的,通过名称可以看出,【queryWord】和【word】代表的是查询信息。

queryWord=%E5%90%91%E6%97%A5%E8%91%B5

这后面的信息是编码后的查询数据,至于为什么编码,是因为URL只支持一部分ASCII编码,而中文内容需要进行编码,才能用于url

使用在线URL编码工具尝试编码”向日葵“,发现与url使用中的相同

image-20211024141921177

到这里,我们可以尝试一下这个url请求

import requests  # 导入requests包

url = 'https://image.baidu.com/search/acjson?tn=resultjson_com&logid=6991546938775238432&ipn=rj&ct=201326592&is=&fp=result&queryWord=%E5%90%91%E6%97%A5%E8%91%B5&cl=2&lm=-1&ie=utf-8&oe=utf-8&adpicid=&st=&z=&ic=&hd=&latest=&copyright=&word=%E5%90%91%E6%97%A5%E8%91%B5&s=&se=&tab=&width=&height=&face=&istype=&qc=&nc=1&fr=&expermode=&nojc=&pn=30&rn=30&gsm=1e&1635046467636='
headers = {'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/95.0.4638.54 Safari/537.36 Edg/95.0.1020.30'}

strhtml = requests.get(url, headers=headers)  # Get方式获取网页数据
print(strhtml.text)

请求到的数据如下图所示,可以看到返回结果是json格式的。

image-20211024142333934

既然是json格式的,我们也不用BeautifulSoup进行解码了,直接根据json格式获取信息。

import requests  # 导入requests包
import json

url = 'https://image.baidu.com/search/acjson?tn=resultjson_com&logid=6991546938775238432&ipn=rj&ct=201326592&is=&fp=result&queryWord=%E5%90%91%E6%97%A5%E8%91%B5&cl=2&lm=-1&ie=utf-8&oe=utf-8&adpicid=&st=&z=&ic=&hd=&latest=&copyright=&word=%E5%90%91%E6%97%A5%E8%91%B5&s=&se=&tab=&width=&height=&face=&istype=&qc=&nc=1&fr=&expermode=&nojc=&pn=30&rn=30&gsm=1e&1635046467636='
headers = {'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/95.0.4638.54 Safari/537.36 Edg/95.0.1020.30'}

strhtml = requests.get(url, headers=headers)  # Get方式获取网页数据
jsonInfo = json.loads(strhtml.text)
for index in range(30):
    print(jsonInfo['data'][index]['thumbURL'])

image-20211024143135677

点击相应的链接,可以查询出相应的图像。

image-20211024143249824

  1. 编写爬虫程序

经过上面分析,基本上有了编写程序的思路。

  • 获取请求url
  • 解析出图像对应的url
  • 根据图像url下载图像

根据设计思路,编写爬虫程序

# -*- coding:utf8 -*-
import requests
import json
from urllib import parse
import os
import time


class BaiduImageSpider(object):
    def __init__(self):
        self.json_count = 0  # 请求到的json文件数量(一个json文件包含30个图像文件)
        self.url = 'https://image.baidu.com/search/acjson?tn=resultjson_com&logid=5179920884740494226&ipn=rj&ct' \
                   '=201326592&is=&fp=result&queryWord={' \
                   '}&cl=2&lm=-1&ie=utf-8&oe=utf-8&adpicid=&st=-1&z=&ic=0&hd=&latest=&copyright=&word={' \
                   '}&s=&se=&tab=&width=&height=&face=0&istype=2&qc=&nc=1&fr=&expermode=&nojc=&pn={' \
                   '}&rn=30&gsm=1e&1635054081427= '
        self.directory = r"C:\Users\cun\Pictures\download\{}"  # 存储目录  这里需要修改为自己希望保存的目录  {}不要丢
        self.header = {
            'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) '
                          'Chrome/95.0.4638.54 Safari/537.36 Edg/95.0.1020.30 '
        }

    # 创建存储文件夹
    def create_directory(self, name):
        self.directory = self.directory.format(name)
        # 如果目录不存在则创建
        if not os.path.exists(self.directory):
            os.makedirs(self.directory)
        self.directory += r'\{}'

    # 获取图像链接
    def get_image_link(self, url):
        list_image_link = []
        strhtml = requests.get(url, headers=self.header)  # Get方式获取网页数据
        jsonInfo = json.loads(strhtml.text)
        for index in range(30):
            list_image_link.append(jsonInfo['data'][index]['thumbURL'])
        return list_image_link

    # 下载图片
    def save_image(self, img_link, filename):
        res = requests.get(img_link, headers=self.header)
        if res.status_code == 404:
            print(f"图片{img_link}下载出错------->")
        with open(filename, "wb") as f:
            f.write(res.content)
            print("存储路径:" + filename)

    # 入口函数
    def run(self):
        searchName = input("查询内容:")
        searchName_parse = parse.quote(searchName)  # 编码

        self.create_directory(searchName)

        pic_number = 0  # 图像数量
        for index in range(self.json_count):
            pn = (index+1)*30
            request_url = self.url.format(searchName_parse, searchName_parse, str(pn))
            list_image_link = self.get_image_link(request_url)
            for link in list_image_link:
                pic_number += 1
                self.save_image(link, self.directory.format(str(pic_number)+'.jpg'))
                time.sleep(0.2)  # 休眠0.2秒,防止封ip
        print(searchName+"----图像下载完成--------->")


if __name__ == '__main__':
    spider = BaiduImageSpider()
    spider.json_count = 10   # 定义下载10组图像,也就是三百张
    spider.run()

如果要使用上述程序的话,需要修改两个地方

  • self.directory 这是本地存储地址,修改为自己电脑的地址,另外,**{}**不要删
  • spider.json_count = 10 这是下载的图像组数,一组有30张图像,10组就是三百张,根据需求下载

测试下载3组玫瑰,程序运行情况:

image-20211024152530111

下载的玫瑰图像数据:

image-20211024152714420

10组向日葵图像:

image-20211024152653324

值得注意的是,下载过程中使用了休眠,这里设置了下载一张图像休眠0.2秒,是为了防止查询过快导致ip地址被封,更进阶的做法是添加【代理ip池】

3. 后言

爬虫还是比较好入门的,这得益于成熟的爬虫工具。

爬虫可以满足自己的个性化搜索需求,快动手试试吧。

如果觉得文章还不错的话,留个赞再走吧,非常感谢!!!

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Python爬虫系列(二)——Python爬虫批量下载百度图片 的相关文章

  • 如何计算 pandas datetime 对象的均值和方差?

    如何计算 YYYY MM DD 形式的 python 日期时间对象的汇总统计数据 均值和标准差 我想对具有不同 ID 的不同日期时间对象组执行此操作 数据如下 import datetime as dt df pd DataFrame Da
  • matplotlib 图中点的标签

    所以这是一个关于已发布的解决方案的问题 我试图在我拥有的 matplotlib 散点图中的点上放置一些数据标签 我试图在这里模仿解决方案 是否有与 MATLAB 的 datacursormode 等效的 matplotlib https s
  • 为什么 web2py 在启动时崩溃?

    我正在尝试让 web2py 在 Ubuntu 机器上运行 所有文档似乎都表明要在 nix 系统上运行它 您需要下载源代码并执行以下操作 蟒蛇 web2py py 我抓住了source http www web2py com examples
  • GUI(输入和输出矩阵)?

    我需要创建一个 GUI 将数据输入到矩阵或表格中并读取此表单数据 完美的解决方案是限制输入表单仅允许float 例如 A 1 02 0 25 0 30 0 515 0 41 1 13 0 15 1 555 0 25 0 14 1 21 2
  • 打印包含字符串和其他 2 个变量的变量

    var a 8 var b 3 var c hello my name is var a and var b bye print var c 当我运行程序时 var c 会像这样打印出来 hello my name is 8 and 3 b
  • 如何使用 Selenium 和 ChromeDriver 解决 TypeError: 'module' object is not callable 错误 [重复]

    这个问题在这里已经有答案了 代码试验 from selenium import webdriver from selenium webdriver chrome options import Options as Chromeoptions
  • 如何将特定范围内的标量添加到 numpy 数组?

    有没有一种更简单 更节省内存的方法可以单独在 numpy 中执行以下操作 import numpy as np ar np array a l r ar c a a 0 l ar tolist a r 它可能看起来很原始 但它涉及获取给定数
  • Python 3:将字符串转换为变量[重复]

    这个问题在这里已经有答案了 我正在从 txt 文件读取文本 并且需要使用我读取的数据之一作为类实例的变量 class Sports def init self players 0 location name self players pla
  • 如何将 ascii 值列表转换为 python 中的字符串?

    我在 Python 程序中有一个列表 其中包含一系列数字 这些数字本身就是 ASCII 值 如何将其转换为可以在屏幕上回显的 常规 字符串 您可能正在寻找 chr gt gt gt L 104 101 108 108 111 44 32 1
  • Python GTK+ 画布

    我目前正在通过 PyGobject 学习 GTK 需要画布之类的东西 我已经搜索了文档 发现两个小部件似乎可以完成这项工作 GtkDrawingArea 和 GtkLayout 我需要一些基本函数 如 fillrect 或 drawline
  • 找到一个数字所属的一组范围

    我有一个 200k 行的数字范围列表 例如开始位置 停止位置 该列表包括除了非重叠的重叠之外的所有类型的重叠 列表看起来像这样 3 5 10 30 15 25 5 15 25 35 我需要找到给定数字所属的范围 并对 100k 个数字重复该
  • 带有 LSTM 的 GridSearchCV/RandomizedSearchCV

    我一直在尝试通过 RandomizedSearchCV 调整 LSTM 的超参数 我的代码如下 X train X train reshape X train shape 0 1 X train shape 1 X test X test
  • Python:Goslate 翻译请求返回“503:服务不可用”[关闭]

    Closed 这个问题不符合堆栈溢出指南 help closed questions 目前不接受答案 我们不允许提出寻求书籍 工具 软件库等推荐的问题 您可以编辑问题 以便用事实和引文来回答 这个问题似乎不是关于主要由程序员使用的特定编程问
  • 如何以正确的方式为独立的Python应用程序制作setup.py?

    我读过几个类似的主题 但还没有成功 我觉得我错过或误解了一些基本的事情 这就是我失败的原因 我有一个用 python 编写的 应用程序 我想在标准 setup py 的帮助下进行部署 由于功能复杂 它由不同的 python 模块组成 但单独
  • 如果 PyPy 快 6.3 倍,为什么我不应该使用 PyPy 而不是 CPython?

    我已经听到很多关于PyPy http en wikipedia org wiki PyPy项目 他们声称它比现有技术快 6 3 倍CPython http en wikipedia org wiki CPython口译员开启他们的网站 ht
  • Firebase Firestore:获取文档的生成 ID (Python)

    我可以创建一个新文档 带有自动生成的 ID 并存储对其的引用 如下所示 my data key value doc ref db collection u campaigns add my data 我可以像这样访问数据本身 print d
  • 在virtualenv中下载sqlite3

    我正在尝试使用命令创建应用程序python3 manage py startapp webapp但我收到一条错误消息 django core exceptions ImproperlyConfigured 加载时出错 pysqlite2 或
  • pytest找不到模块[重复]

    这个问题在这里已经有答案了 我正在关注pytest 良好实践 https docs pytest org en latest explanation goodpractices html test discovery或者至少我认为我是 但是
  • 如何将Python3设置为Mac上的默认Python版本?

    有没有办法将 Python 3 8 3 设置为 macOS Catalina 版本 10 15 2 上的默认 Python 版本 我已经完成的步骤 看看它安装在哪里 ls l usr local bin python 我得到的输出是这样的
  • NLTK:查找单词大小为 2k 的上下文

    我有一个语料库 我有一个词 对于语料库中该单词的每次出现 我想获取一个包含该单词之前的 k 个单词和该单词之后的 k 个单词的列表 我在算法上做得很好 见下文 但我想知道 NLTK 是否提供了一些我错过的功能来满足我的需求 def size

随机推荐

  • Android versions (Android 版本)

    Android versions Android 版本 All Android releases https developer android com about versions Android 1 0 G1 Android 1 5 C
  • vue怎么在一个页面里写两个表格_vue项目中将element-ui table表格写成组件

    表格中我们经常需要动态加载数据 如果有多个页面都需要用到表格 那我希望可以有个组件 只传数据过去显示 不用每个页面都去写这么一段内容 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 查看 16 编辑 17 18 19
  • 《百面机器学习》学习笔试之模型评估(第2章)

    01 评估指标的局限性 准确率 Accuracy 的局限性 A c c u r a c y
  • 服务器输入nvidia-smi报错:

    发现服务器好像有挖矿程序再跑 我重启了一下 结果重启后nvidia smi报错了 NVIDIA SMI has failed because it couldn t communicate with the NVIDIA driver Ma
  • 运维36讲第10课:基于 Python+Ansible+Django 搭建 CMDB 平台

    本课时我们主要讲解如何基于 Python Django Ansible 开发一套具备 Devops 理念的自动化任务执行和资产管理 CMDB 系统 工程简介 这个可以实现自动化任务执行和资产管理的系统取名为 Imoocc 它是基于 Pyth
  • element ui 对话框设置固定宽度

    宽度设置width属性 默认是百分比 如 width 30 表示宽度为 其父元素宽的 30 想给固定宽度 使用v bind指令 加上px单位即可 width 300px 注意引号
  • 如何查看公众号文章的排版格式字体大小

    Q1 如何查看公众号文章的排版格式 字体 大小 颜色 行间距 页边距等 注意 如果是长图形式 图片中的文字 无法使用这个方法 总共三步 1 电脑端打开微信文章 复制链接地址 点击下方红框 2 在浏览器中粘贴 跳转显示该文章 3 鼠标选中字体
  • 对傅里叶变换的一些思考

    1 时域中的周期对应傅里叶变换的离散 2 时域的非周期对应傅里叶变换后的连续 3 将一个非周期信号傅里叶变换后 得到频谱图 其中横坐标是频率 纵坐标是幅值密度 而不是幅值 量纲是幅值的单位 Hz 所以这个频谱图里面各个频率对应的波的幅值应该
  • 简单博弈论(Nim游戏)

    891 Nim游戏 题目 提交记录 讨论 题解 视频讲解 给定 n 堆石子 两位玩家轮流操作 每次操作可以从任意一堆石子中拿走任意数量的石子 可以拿完 但不能不拿 最后无法进行操作的人视为失败 问如果两人都采用最优策略 先手是否必胜 输入格
  • 图像分类之PaddleClas网络预训练模型加载方法

    PaddlePaddle简介 PaddlePaddle是非常好用的深度学习库 尤其是2 0版本发布以来 高低层API可以自由结合使用 优点如下 可以像tensorflow里面的keras一样非常方便的用几行代码完成模型构建和训练 可以像py
  • 【图像处理】彩色图直方图统计

    首先要知道彩色图是没有直方图的 只能在rgb方向分别求直方图在合并一下 干脆不用这么麻烦 用rgb2gray转到灰度图 再在二维上进行直方图绘制 最后还提供了代码 找出直方图中横坐标 像素值 为50以下的纵坐标 以此为像素的个数 的和 cl
  • 代码精简10倍,责任链模式yyds

    目录 什么是责任链 使用场景 结语 前言最近 我让团队内一位成员写了一个导入功能 他使用了责任链模式 代码堆的非常多 bug 也多 没有达到我预期的效果 实际上 针对导入功能 我认为模版方法更合适 为此 隔壁团队也拿出我们的案例 进行了集体
  • K8S中安装kafka集群问题总结

    k8s下kafkacluster的安装 https github com banzaicloud kafka operator 问题一 镜像无法拉取 由于镜像源在国外被墙的原因 无法从源镜像下载 一般走镜像代理的形式 先从代理仓库docke
  • Ubuntu16.04 完全卸载opencv

    cd XXX opencv build 进入build目录 sudo make uninstall 卸载掉配置路径中的文件 sudo rm r build 删除build文件
  • Windows10家庭版 Windows defender 安全中心显示 页面不可用

    前言 今天使用电脑时出现了如下情况 倒没有发现电脑有什么实质的问题 只是不太理解又觉得好奇 于是就上网查了查 因为没有发现电脑有什么实质的问题 所以犯懒没有鼓捣自己的电脑 以下内容皆由网络所得 由本人整理汇总 希望有所帮助 可能的原因与解决
  • IOU(Intersection Over Union) 概念清晰图解 + python代码示例

    IOU Intersection Over Union 交并比 Intersection over Union IoU 目标检测中使用的一个概念 是产生的候选框 candidate bound 与原标记框 ground truth boun
  • C++ gstreamer函数使用总结

    目录 1 GSteamer的基本API的使用 这个播放mp4报错 这个创建play bin 返回0 不能运行 这个值得看 2 创建元件并且链接起来 3 添加衬垫 添加回调 手动链接衬垫 4 打印gstreamer的版本信息 5 gstrea
  • vim-指定区域查找替换

    vim中的区域查找替换 vim这么强大的工具当然是支持只替换一部分文本啦 那么怎么实现呢 最直接的方式 1 用v选中文本 2 然后 这样的话 命令默认形式是 lt gt s source source abc g 繁琐的方法 a bg fr
  • C/S与P2P的主要区别以及相同点

    C S方式所描述的是进程之间服务和被服务的关系 客户是服务的请求方 服务器是服务的提供方 服务的请求方和提供方都要使用网络核心部分所提供的服务 客户程序被用户调用后运行 在通信时主动向远地服务器发起通信 服务请求 因此 客户程序必须知道服务
  • Python爬虫系列(二)——Python爬虫批量下载百度图片

    1 前言 先贴代码 coding utf8 import requests import json from urllib import parse import os import time class BaiduImageSpider