可爱女生图片到期了,怎么办?当前是把Python爬虫升级到可爱头像站

Posted 梦想橡皮擦

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了可爱女生图片到期了,怎么办?当前是把Python爬虫升级到可爱头像站相关的知识,希望对你有一定的参考价值。

最近收到 C 友反馈,说 《对 Python 爬虫编写者充满诱惑的网站,《可爱图片》》 这篇博客的目标图片站,已经不能使用了,橡皮擦查阅之后,发现是对方的图片源出了问题,可跟咱一点点关系都没有。

🍀 但是对我们专栏的订阅者可以有影响的,毕竟我们要学习的知识缺少了这么一块,有点不完美了。🍀

正因如此,我们做一下本案例的升级,(如果你在订阅之后,发现其它站点出现类似情况,一定第一时间联系橡皮擦,每个爬虫都质保 5 年)

版权声明:本案例涉及所有内容仅供学习使用,请勿用于商业目的,如有侵权,请及时联系。

学习注意事项:

  1. 文章会自动省略 http 和 https 协议,学习时请自行在地址中进行补充。
  2. 目标站点域名为 imeitou,在下文统一用 橡皮擦 代替,学习时请自行拼接。

文章目录

⛳️ 女生头像图片

本次目标站点时【美头】,一个小众站点,是一个专注如提供高清好看头像的小站。


经过简单测试,目标站点翻页规则如下所示。

www.橡皮擦.com/nvsheng/index.html
www.橡皮擦.com/nvsheng/index_2.html

www.橡皮擦.com/nvsheng/index_10.html

注意不要直接访问地址,看前文说明,【橡皮擦】属于密文。

在原案例中,我们使用了三个 Python 模块,分别是 requestsrethreading,其中提及了线程并行模块 threading,这也是本篇博客的重点内容。

学习的时候你可以两篇博客对比学习,所以橡皮擦在本文中增加一些补充逻辑进入。

本次的目标站点翻页规则属于 URL 数字跳转,难度系数比较低,很容易发现规律,并且点击详细地址链接,得到的详情页面数据无需翻页,所以代码编写逻辑也变简单,整理需求如下所示。

需求整理

  1. 目标站点的数据量大小是: 1790 页 28628 条数据,比较大,所以学习的时候,我们仅采集前 10 页,此时可以固定最大页,起始页在前文已经固定。
  2. 原博客中用到了多线程采集详情地址,这里保留该逻辑。
  3. 下载图片也是采用多线程处理,依旧保留逻辑。

下面进入到编码环节。

⛳️ 实战场景

获取详情页地址
编码的第一个环节,就是将详情页地址采集到一个全局变量中,这里会用到互斥锁,也是使用多线程模块访问全局变量的必备知识点。
在编码环节,重要步骤会在注释中添加,请仔细阅读。

import requests
import re
import threading
import time

headers = 
    "User-Agent": "Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.93 Safari/537.36"

# 详情页图片地址 URL
detail_urls = []

mutex = threading.Lock()


# 循环获取URL
def get_detail_urls(url):
    res = requests.get(url=url, headers=headers)
    res.encoding = 'gb2312'
    if res is not None:

        html = res.text  # 读取页面源码
        # 对目标源码页数据进行裁剪
        # 获取 ul class = "g-gxlist-imgbox" 的数据
        # 该数据在标签 <ul class="g-gxlist-imgbox"> 和 <div class="pagelist"> 之间
        html = html[html.find('<ul class="g-gxlist-imgbox">'):html.find('<div class="pagelist">')]
        # 裁剪之后的数据,可以使用正则提取
        # 设置正则表达式对象
        pattern = re.compile('<a href="(.*?)" target="_blank" title=".*?">')
        # 提取详情页地址
        find_urls = pattern.findall(html)

        if find_urls:
            # 上锁
            mutex.acquire()
            # 添加到全局变量中
            detail_urls.extend(find_urls)
            # 释放锁
            mutex.release()


if __name__ == '__main__':
    # 生成分页地址
    origin_url = ['http://www.imeitou.com/nvsheng/']
    for i in range(2, 11):
        origin_url.append(f'http://www.imeitou.com/nvsheng/index_i.html')

    # 获取图片详情页地址
    for d_url in origin_url:
        get_detail_urls(d_url)

    # 测试得到的详情页地址列表
    # 测试得到 160 条地址,数据量是正确的
    print(len(detail_urls))

通过运行上述代码,你已经将地址提取到了全量变量 detail_urls 中,注意在使用的时候进行锁设置,这里的锁是为了后续获取图片地址做的准备。

图片下载线程

import requests
import re
import threading
import time

headers = 
    "User-Agent": "Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.93 Safari/537.36"

# 详情页图片地址 URL
detail_urls = []

mutex = threading.Lock()


# 循环获取URL
def get_detail_urls(url):
    res = requests.get(url=url, headers=headers)
    res.encoding = 'gb2312'
    if res is not None:

        html = res.text  # 读取页面源码
        # 对目标源码页数据进行裁剪
        # 获取 ul class = "g-gxlist-imgbox" 的数据
        # 该数据在标签 <ul class="g-gxlist-imgbox"> 和 <div class="pagelist"> 之间
        html = html[html.find('<ul class="g-gxlist-imgbox">'):html.find('<div class="pagelist">')]
        # 裁剪之后的数据,可以使用正则提取
        # 设置正则表达式对象
        pattern = re.compile('<a href="(.*?)" target="_blank" title=".*?">')
        # 提取详情页地址
        find_urls = pattern.findall(html)

        if find_urls:
            # 上锁
            mutex.acquire()
            # 添加到全局变量中
            detail_urls.extend(find_urls)
            # 释放锁
            mutex.release()


# 保存图片线程
def save_image():
    global detail_urls

    while True:
        # 上锁
        mutex.acquire()
        if len(detail_urls) > 0:
            # 获取列表第1项
            img_url = detail_urls[0]
            # 删除列表第1项
            del detail_urls[0]
            # 释放锁
            mutex.release()
            res = requests.get(url=img_url, headers=headers)

            if res is not None:
                html = res.text

                # 裁切目标源码,便于后续整体提取
                html = html[html.find('<div class="img-list3">'):html.find('<div class="m_ssxx">')]
                pattern = re.compile('<img alt=".*?" src="(.*?)" />')

                img_list = pattern.findall(html)

                if img_list:
                    for img in img_list:
                        print(f"线程threading.currentThread().name", "抓取图片中:", img)

                        try:
                            res = requests.get(img)
                            with open(f"images/time.time().png", "wb+") as f:
                                f.write(res.content)
                        except Exception as e:
                            print(e)
        else:
            print("等待中,长时间等待,可以直接关闭")


if __name__ == '__main__':
    # 生成分页地址
    origin_url = ['http://www.imeitou.com/nvsheng/']
    for i in range(2, 11):
        origin_url.append(f'http://www.imeitou.com/nvsheng/index_i.html')

    # 获取图片详情页地址
    for d_url in origin_url:
        get_detail_urls(d_url)

    # 测试得到的详情页地址列表
    # 测试得到 160 条地址,数据量是正确的
    print(len(detail_urls))

    # 保存图片线程配置+启动
    # 这里我们开启2个线程
    save1 = threading.Thread(target=save_image)
    save1.start()

    # save2 = threading.Thread(target=save_image)
    # save2.start()

上述仅使用了 2 个线程,实战中根据电脑配置提高即可。代码运行效果如下所示。


注意提前在项目根目录建立 images 文件夹,然后你就能得到大量头像图片了。

📢📢📢📢📢📢
💗 你正在阅读 【梦想橡皮擦】 的博客
👍 阅读完毕,可以点点小手赞一下
🌻 发现错误,直接评论区中指正吧
📆 橡皮擦的第 786 篇原创博客

从订购之日起,案例 5 年内保证更新

以上是关于可爱女生图片到期了,怎么办?当前是把Python爬虫升级到可爱头像站的主要内容,如果未能解决你的问题,请参考以下文章

Python批量检测图片中的人脸并制作数据集(Dlib)

如何用python实现爬取微博相册所有图片?

python爬取MM图片

爬取动态图片—以百度图片为例

怎么判断一个女生有没有对象呢?

利用Python多线程爬虫——爬图片