Python爬虫:爬取网页图片

2023-11-06

在这里插入图片描述

开始:

最近在自学爬虫,自己也做了一些实例,(自认为)写的比较好的就是对整个网站的爬取了。接下来我将会说一说我使用的工具及方法。

注意:为了尊重网站维护人员,我只爬取了网站首页的24个套图,其余的,需要的小伙伴可以自行添加翻页操作!!!

编译环境和所需库

IDE: PyCharm Community Edition 2020.1 x64
python版本: 3.8.2
所需库: requests , BeautifulSoup4,os,time,random


分析与步骤:

第一步

废话不多说,我们直接开始:
第一件事就是导库了,这个简单,就不用我多说了吧。直接上代码:

import os
import time
from random import random
import requests
from bs4 import BeautifulSoup
第二步

这第二件事当然是要去请求网站了,但是我们了解到该网站有反爬机制,所以我们必须先包装一下自己。

ref_url='https://www.mzitu.com'
header = {
    'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/81.0.4044.92 Safari/537.36 Edg/81.0.416.53',
    'accept-encoding': 'gzip, deflate, br',
    'accept-language': 'zh-CN,zh;q=0.9,en;q=0.8,en-GB;q=0.7,en-US;q=0.6',
    'cache-control': 'max-age=0',
    'Referer': ref_url
    }

:为什么 headers 字段中 Referer 的值要设为全局变量
:因为我在测试代码可行性的时候发现,当 Referer 的值为一个定值时,请求大量数据,就会触发反爬机制,导致出现下标越界(或者是找不到某个标签)的异常。从而导致爬取中断。另外根据网站的反爬机制,Referer 字段是必须要有的。

第三步

当我们打开主页就会发现,主页上有24个套图链接,每个套图链接就是一套写真。所以,我们首先爬取的应该是主页上这24个套图链接:
打开浏览器进入主页后查看源码,我们可以看到,首页中24个套图链接都在 ‘ li ’ 标签里面。
所以在代码中 ,我先用 BeautifulSoup 解析源码,将每套图的 ‘ li ’ 标签保存到 Temp_list 中。
再利用 for 提取出每个套图链接,再次进行解析。取出每个 ’ a ’ 标签属性中的 ’ href ’ 字段的值。
又将 ’ href ’ 字段的值作为关键字,保存每套图的名字(每个 ’ img ’ 标签属性中的 ’ alt ’ 字段的值),生成一个字典。
最后,提示当前页面的所有链接都保存成功。
代码如下:

def get_main_url(url):  # 获取每个主页的24个图片链接
    res = requests.get(url,headers=header)
    soup = BeautifulSoup(res.text, 'html.parser')
    Temp_list = soup.find_all('li')[8:]
    # [8:] 的目的是过滤掉多余的 li 标签
    for lab_list in Temp_list:
        div = BeautifulSoup(str(lab_list), 'html.parser')
        main_url.append(div.a.attrs['href'])  
        # 每个主页中套图详情列表链接
        name_dict[div.a.attrs['href']] = div.img.attrs['alt']
        # 每个主页中套图名字列表
    print("获取当前页面所有链接成功!")
第四步

来到这里,我首先用 for 挨个取出这24个套图链接。
然后取出每一个套图链接的名字,判断是否有同名文件夹,如果有,则跳过,如果没有,则创建。
接着对每个链接进行解析,找出该套图链接中的图片页数。
紧接着,利用 for 进行翻页操作。
for 每翻一页,就对当前页面进行解析。
通过 BeautifulSoup 解析后,取出 ’ div ’ 标签下, ’ img ’ 属性中的 ‘ arc ’ 字段的值,即为高清图片的地址。
通过 requests 库请求该图片链接(同样要带上 header ,不然仍然会触发反爬,导致图片出错)。
接下来利用 ‘ split ’ 对图片链接进行处理,取出当前图片名字作为图片名。
’ split ‘ 不会用?点击查看使用方法
最后,将转换为二进制的图片保存下来。
注意:当我们以一定频率或者速度(requests请求速度几乎是一定的)去大量的连续请求时,还是会触发反爬,所以在每爬完一张照片后开始随机休眠。(如果还是不够的话,可以写成 ’ time.sleep(random() * 5) ’ ,数字随便定,不过要注意:数字太大下载会很慢,太小会触发反爬,根据情况可以自行设置)
代码如下:

def get_image():
    global main_num,ref_url
    for now_url in main_url:
        main_num+=1   #第 main_num 套图
        ref_url=now_url  #修改当前的 Referer 
        
        if os.path.exists(path + '/' + name_dict[now_url]):
            pass
        else:
            os.mkdir(path + '/' + name_dict[now_url])
            
        response = requests.get(now_url, headers=header)
        soup = BeautifulSoup(response.text, 'html.parser')
        page_nums = soup.find('div', attrs={'class': "pagenavi"})
        page_num = BeautifulSoup(str(page_nums), 'html.parser').find_all('span')[-2].string
        
        for i in range(1, int(page_num) + 1):
            now_new_url = now_url + '/' + '{}'.format(i)
            new_response = requests.get(now_new_url, headers=header)
            Temp = BeautifulSoup(new_response.text, 'html.parser')
            image_url = Temp.find('div', attrs={'class': "main-image"}).img.attrs['src']
            image = requests.get(image_url,headers=header)
            name = str(image_url).split('/', 5)[-1]
            
            with open(path + '/' + name_dict[now_url] + '/' + name, 'wb') as f:
                f.write(image.content)
                print('正在爬取第'+str(main_num)+'个图库的第'+str(i)+'张图片,本页共'+page_num+'张照片。')
                time.sleep(random())

最后:

主要功能写完后,就可以开始用主函数调用了:

if __name__ == '__main__':
    start_time = time.time()
    get_main_url(url)
    get_image()
    end_time = time.time()
    print('耗时:' + str(end_time - start_time))

运行时展示:
在这里插入图片描述
最最最最最后:
附上我总结了三天经验后写出的源码:

import os
import time
from random import random
import requests
from bs4 import BeautifulSoup

path = './spider'
if os.path.exists(path):
    pass
else:
    os.mkdir(path)
url = 'https://www.mzitu.com'
main_url = []
name_dict = {}
main_num = 0

ref_url='https://www.mzitu.com'
header = {
    'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/81.0.4044.92 Safari/537.36 Edg/81.0.416.53',
    'accept-encoding': 'gzip, deflate, br',
    'accept-language': 'zh-CN,zh;q=0.9,en;q=0.8,en-GB;q=0.7,en-US;q=0.6',
    'cache-control': 'max-age=0',
    'Referer': ref_url
    }


def get_main_url(url):  # 获取每个主页的24个图片链接
    res = requests.get(url,headers=header)
    soup = BeautifulSoup(res.text, 'html.parser')
    Temp_list = soup.find_all('li')[8:]
    for lab_list in Temp_list:
        div = BeautifulSoup(str(lab_list), 'html.parser')
        main_url.append(div.a.attrs['href'])  # 每个主页中图片详情列表链接
        name_dict[div.a.attrs['href']] = div.img.attrs['alt']
    print("获取当前页面所有链接成功!")


# <div class="main-image">  图片标签
# <div class="pagenavi">    页码标签
def get_image():
    global main_num,ref_url
    for now_url in main_url:
        main_num+=1
        ref_url=now_url
        if os.path.exists(path + '/' + name_dict[now_url]):
            pass
        else:
            os.mkdir(path + '/' + name_dict[now_url])
        response = requests.get(now_url, headers=header)
        soup = BeautifulSoup(response.text, 'html.parser')
        page_nums = soup.find('div', attrs={'class': "pagenavi"})
        page_num = BeautifulSoup(str(page_nums), 'html.parser').find_all('span')[-2].string
        for i in range(1, int(page_num) + 1):
            now_new_url = now_url + '/' + '{}'.format(i)
            new_response = requests.get(now_new_url, headers=header)
            Temp = BeautifulSoup(new_response.text, 'html.parser')
            image_url = Temp.find('div', attrs={'class': "main-image"}).img.attrs['src']
            image = requests.get(image_url,headers=header)
            name = str(image_url).split('/', 5)[-1]
            with open(path + '/' + name_dict[now_url] + '/' + name, 'wb') as f:
                f.write(image.content)
                print('正在爬取第'+str(main_num)+'个图库的第'+str(i)+'张图片,本页共'+page_num+'张照片。')
                time.sleep(random())

if __name__ == '__main__':
    start_time = time.time()
    get_main_url(url)
    get_image()
    end_time = time.time()
    print('耗时:' + str(end_time - start_time))
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Python爬虫:爬取网页图片 的相关文章

  • 如何在刻度标签和轴之间添加空间

    我已成功增加刻度标签的字体 但现在它们距离轴太近了 我想在刻度标签和轴之间添加一点呼吸空间 如果您不想全局更改间距 通过编辑 rcParams 并且想要更简洁的方法 请尝试以下操作 ax tick params axis both whic
  • Python PAM 模块的安全问题?

    我有兴趣编写一个 PAM 模块 该模块将利用流行的 Unix 登录身份验证机制 我过去的大部分编程经验都是使用 Python 进行的 并且我正在交互的系统已经有一个 Python API 我用谷歌搜索发现pam python http pa
  • 使用 openCV 对图像中的子图像进行通用检测

    免责声明 我是计算机视觉菜鸟 我看过很多关于如何在较大图像中查找特定子图像的堆栈溢出帖子 我的用例有点不同 因为我不希望它是具体的 而且我不确定如何做到这一点 如果可能的话 但我感觉应该如此 我有大量图像数据集 有时 其中一些图像是数据集的
  • 如何生成给定范围内的回文数列表?

    假设范围是 1 X 120 这是我尝试过的 gt gt gt def isPalindrome s check if a number is a Palindrome s str s return s s 1 gt gt gt def ge
  • DreamPie 不适用于 Python 3.2

    我最喜欢的 Python shell 是DreamPie http dreampie sourceforge net 我想将它与 Python 3 2 一起使用 我使用了 添加解释器 DreamPie 应用程序并添加了 Python 3 2
  • 更改自动插入 tkinter 小部件的文本颜色

    我有一个文本框小部件 其中插入了三条消息 一条是开始消息 一条是结束消息 一条是在 单位 被摧毁时发出警报的消息 我希望开始和结束消息是黑色的 但被毁坏的消息 参见我在代码中评论的位置 插入小部件时颜色为红色 我不太确定如何去做这件事 我看
  • Python 多处理示例不起作用

    我正在尝试学习如何使用multiprocessing但我无法让它发挥作用 这是代码文档 http docs python org 2 library multiprocessing html from multiprocessing imp
  • 使用 Pycharm 在 Windows 下启动应用程序时出现 UnicodeDecodeError

    问题是当我尝试启动应用程序 app py 时 我收到以下错误 UnicodeDecodeError utf 8 编解码器无法解码位置 5 中的字节 0xb3 起始字节无效 整个文件app py coding utf 8 from flask
  • Python 中的二进制缓冲区

    在Python中你可以使用StringIO https docs python org library struct html用于字符数据的类似文件的缓冲区 内存映射文件 https docs python org library mmap
  • python 集合可以包含的值的数量是否有限制?

    我正在尝试使用 python 设置作为 mysql 表中 ids 的过滤器 python集存储了所有要过滤的id 现在大约有30000个 这个数字会随着时间的推移慢慢增长 我担心python集的最大容量 它可以包含的元素数量有限制吗 您最大
  • Python:字符串不会转换为浮点数[重复]

    这个问题在这里已经有答案了 我几个小时前写了这个程序 while True print What would you like me to double line raw input gt if line done break else f
  • Pandas Dataframe 中 bool 值的条件前向填充

    问题 如何转发 fill boolTruepandas 数据框中的值 如果是当天的第一个条目 True 到一天结束时 请参阅以下示例和所需的输出 Data import pandas as pd import numpy as np df
  • Geopandas 设置几何图形:MultiPolygon“等于 len 键和值”的 ValueError

    我有 2 个带有几何列的地理数据框 我将一些几何图形从 1 个复制到另一个 这对于多边形效果很好 但对于任何 有效 多多边形都会返回 ValueError 请指教如何解决这个问题 我不知道是否 如何 为什么应该更改 MultiPolygon
  • HTTPS 代理不适用于 Python 的 requests 模块

    我对 Python 还很陌生 我一直在使用他们的 requests 模块作为 PHP 的 cURL 库的替代品 我的代码如下 import requests import json import os import urllib impor
  • Python - 在窗口最小化或隐藏时使用 pywinauto 控制窗口

    我正在尝试做的事情 我正在尝试使用 pywinauto 在 python 中创建一个脚本 以在后台自动安装 notepad 隐藏或最小化 notepad 只是一个示例 因为我将编辑它以与其他软件一起使用 Problem 问题是我想在安装程序
  • Nuitka 未使用 nuitka --recurse-all hello.py [错误] 编译 exe

    我正在尝试通过 nuitka 创建一个简单的 exe 这样我就可以在我的笔记本电脑上运行它 而无需安装 Python 我在 Windows 10 上并使用 Anaconda Python 3 我输入 nuitka recurse all h
  • 为美国东部以外地区的 Cloudwatch 警报发送短信?

    AWS 似乎没有为美国东部以外的 SNS 主题订阅者提供 SMS 作为协议 我想连接我的 CloudWatch 警报并在发生故障时接收短信 但无法将其发送到 SMS YES 经过一番挖掘后 我能够让它发挥作用 它比仅仅选择一个主题或输入闹钟
  • 协方差矩阵的对角元素不是 1 pandas/numpy

    我有以下数据框 A B 0 1 5 1 2 6 2 3 7 3 4 8 我想计算协方差 a df iloc 0 values b df iloc 1 values 使用 numpy 作为 cov numpy cov a b I get ar
  • Spark.read 在 Databricks 中给出 KrbException

    我正在尝试从 databricks 笔记本连接到 SQL 数据库 以下是我的代码 jdbcDF spark read format com microsoft sqlserver jdbc spark option url jdbc sql
  • Pandas 与 Numpy 数据帧

    看这几行代码 df2 df copy df2 1 df 1 df 1 values 1 df2 ix 0 0 我们的教练说我们需要使用 values属性来访问底层的 numpy 数组 否则我们的代码将无法工作 我知道 pandas Data

随机推荐