selenium进行xhs图片爬虫:04selenium实现获取一篇文章图片

📚博客主页:knighthood2001
公众号:认知up吧 (目前正在带领大家一起提升认知,感兴趣可以来围观一下)
🎃知识星球:【认知up吧|成长|副业】介绍
❤️感谢大家点赞👍🏻收藏⭐评论✍🏻,您的三连就是我持续更新的动力❤️
🙏笔者水平有限,欢迎各位大佬指点,相互学习进步!

上文我说了,我本来是用今天这个方法进行爬虫的,selenium远程调试的思路,这样的好处就是不需要你进行登录。

比如下面的的小红书链接
100篇阅读理解刷爆大纲5500词|2001年Text3 - 小红书

我需要将其中的图片下载下来,并且还是无水印的。

前言

右键检查,可以发现图片一般有专门的网址,并且点击进去后是无水印的。
在这里插入图片描述

你可以自己多研究一下

然后右键,查看网页源代码,可以发现图片链接都在这个地方出现。
在这里插入图片描述

因此你可以通过正则表达式进行图片链接的提取。

下面这张图片中的代码就是将图片链接保存为本地图片。这也是我之前讲过的内容,相对于这些都是可以即插即用的模板。
在这里插入图片描述

因此实现爬取小红书指定文章的图片的一般步骤就是:

获取网页源代码->使用正则表达式筛选出图片链接->将图片链接的内容保存为本地图片

项目准备

针对xhs的反爬

由于小红书反爬比较恶心,我这里采用的是selenium操作已经打开的浏览器。该原理是selenium进行远程调控,这个好处就是不需要登录(没有很好措施的话,很容易扫码登录也失败,再加上笔者好久没有深入研究cookie这方面内容了,很多东西忘了)

如果这方面不太会的,可以看看我下面这篇文章,或者你们使用保存cookie的方法进行登录。

最新:Selenium操作已经打开的Chrome(免登录)

简单例子

比如你已经打开了一个链接
在这里插入图片描述

from selenium import webdriver
from selenium.webdriver.chrome.options import Options

# TODO 实现免登录爬虫
options = Options()
options.add_experimental_option("debuggerAddress", "127.0.0.1:9527")
driver = webdriver.Chrome(options=options)
# 打印网页title
print(driver.current_url)
print(driver.title)

使用上面的方法,你用selenium,就不需要弹出登录让你登录(有时候爬虫最难的就是登录问题)

运行结果如下,是不是比较轻松。
在这里插入图片描述

编写其他代码

解决了登录问题,后面的就比较好解决了。

但是这次代码,相对于我上面那个即插即用的模板来说,不太一样。因为我上面的那个模板,每次保存图片,由于时间戳一样,就会导致即使有多个图片链接,但是最后都是以一个时间戳命名,最后就保存为1张照片(被反复覆盖了)。

因此我需要进行代码的重构,我的想法是把for循环遍历放到保存图片中,原先保存图片是传入的一个链接,我这时候传入的是一个列表,然后通过for循环进行图片的保存。

并且图片的上一级目录还有一个时间戳,可以帮助你排序,分辨下载先后顺序。

在这里插入图片描述

这一部分的代码,和之前版本来说,还是有较大区别的。

#TODO 实现输入一个图片url列表,将其中的图片保存到目录中,并按照1-nums排序,这样可以保证下载下来的图片顺序不乱。
#TODO 比如输入[图片链接1,图片链接2,图片链接3]和"image",最后就会生成image/时间戳的目录,然后在里面保存1.png,2.png,3.png
def image_save_batch(image_urls, save_dir):
    time_path = get_time()
    path = os.path.join(save_dir, str(time_path))
    if not os.path.exists(path):
        os.makedirs(path)

    for i, url in enumerate(image_urls):
        # 发送 GET 请求获取图片数据
        response = requests.get(url)
        # 确保请求成功
        if response.status_code == 200:
            # 生成图片文件名
            image_name = f"{time_path}/{i}.png"
            # 拼接图片保存路径
            save_path = os.path.join(save_dir, image_name)
            # 将图片数据写入文件
            with open(save_path, 'wb') as f:
                f.write(response.content)
            print(f'图片{i+1}已保存为: {save_path}')
        else:
            print(f'下载图片{i+1}失败,状态码: {response.status_code}')


def get_img_url_list(content):
    # 使用正则表达式提取网址
    url_pattern = re.compile(r'<meta name="og:image" content="(.*?)">')
    matches = url_pattern.findall(content)
    if matches:
        # 去重+顺序
        # unique_matches = list(set(matches)) # 会乱序
        unique_matches = list(Counter(matches))
        nums = len(unique_matches)
        print(f"图片数量:{nums}, 图片去重数量:{len(matches)-nums}")
        print(unique_matches)
        # # 打印每个网址
        # for i in range(nums):
        #     print(unique_matches[i])
        #     image_save(unique_matches[i], "images")
        image_save_batch(unique_matches, "images")
    else:
        print("No URL found.")

需要注意的一点是,matches中的图片链接有时候会有重复,因此需要去重操作,但是set函数的去重操作是无序的,会导致最终图片保存顺序为乱序。
因此我这里采用调用collections的Counter,解决去重+乱序的问题。

全部代码

from selenium import webdriver
from selenium.webdriver.chrome.options import Options
from collections import Counter  # 解决去重+乱序问题
import re
import os
import requests

# TODO 实现免登录爬虫
options = Options()
options.add_experimental_option("debuggerAddress", "127.0.0.1:9527")
driver = webdriver.Chrome(options=options)
# 打印网页title
print(driver.current_url)
print(driver.title)

# 获取当前时间戳
def get_time():
    import time
    timestamp = int(time.time())
    return timestamp

#TODO 实现输入一个图片url列表,将其中的图片保存到目录中,并按照1-nums排序,这样可以保证下载下来的图片顺序不乱。
#TODO 比如输入[图片链接1,图片链接2,图片链接3]和"image",最后就会生成image/时间戳的目录,然后在里面保存1.png,2.png,3.png
def image_save_batch(image_urls, save_dir):
    time_path = get_time()
    path = os.path.join(save_dir, str(time_path))
    if not os.path.exists(path):
        os.makedirs(path)

    for i, url in enumerate(image_urls):
        # 发送 GET 请求获取图片数据
        response = requests.get(url)
        # 确保请求成功
        if response.status_code == 200:
            # 生成图片文件名
            image_name = f"{time_path}/{i}.png"
            # 拼接图片保存路径
            save_path = os.path.join(save_dir, image_name)
            # 将图片数据写入文件
            with open(save_path, 'wb') as f:
                f.write(response.content)
            print(f'图片{i+1}已保存为: {save_path}')
        else:
            print(f'下载图片{i+1}失败,状态码: {response.status_code}')


def get_img_url_list(content):
    # 使用正则表达式提取网址
    url_pattern = re.compile(r'<meta name="og:image" content="(.*?)">')
    matches = url_pattern.findall(content)
    if matches:
        # 去重+顺序
        # unique_matches = list(set(matches)) # 会乱序
        unique_matches = list(Counter(matches))
        nums = len(unique_matches)
        print(f"图片数量:{nums}, 图片去重数量:{len(matches)-nums}")
        print(unique_matches)
        # # 打印每个网址
        # for i in range(nums):
        #     print(unique_matches[i])
        #     image_save(unique_matches[i], "images")
        image_save_batch(unique_matches, "images")
    else:
        print("No URL found.")

if __name__ == '__main__':
    page_source = driver.page_source
    get_img_url_list(page_source)

最后

这个项目也算是搭积木吧,但是我觉得应该挺多人需要。因为有时候一张一张手动保存有水印的小红书图片,慢且有水印。

当然,代码中有一些细节,我并没有讲到,因为我发现,写文档真的太折磨人了

  • 39
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

knighthood2001

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值