pinterest images scrape(selenium实现)

本文介绍了如何使用Python的Selenium库动态爬取Pinterest网站上的图片链接,针对动态渲染的页面,通过模拟滑动加载更多图片。在获取图片链接后,文章还展示了如何将链接保存至文件并使用requests下载图片,同时提供了错误处理机制以确保下载过程的稳定性。整个过程涉及网页元素定位、动态加载处理及文件下载等技术。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

今天记录海外图片素材网站Pinterest的图片爬取
初步分析:网站是动态渲染网站,每往下滑动,刷新出来新的页面;通过观察刷新后的网页,初步定位每页的请求url是https://www.pinterest.com/resource/BaseSearchResource/get/,可以看到这是一个POST请求,
在这里插入图片描述之后分析Preview和Response可以确定该url里面的确有我们要的数据:
在这里插入图片描述但是该POST请求有两个加密参数:source_url和data;经对比后,发现每页数据的source_url是相同的,data的属性里面,除了bookmarks不同,其他属性也全部相同。

在这里插入图片描述初步思路是通过js逆向解析出bookmarks,然后得到每一页直接的规律;但是!!!该属性逆向分析起来实在很难,对于不会JS的人,断点打着打着就不知道自己的目标变量跑哪里去了。最后放弃逆向解析的方法,改用selenium实现。

确定思路:决定用selenium之后,思路如下:先通过selenium打开网页,网页链接为:‘https://www.pinterest.com/search/pins/?q=关键词’,然后通过元素定位到图片链接;最重要的,调用driver.execute_script()方法来实现页面滑动(这里需要提前调试获取每次滑动高度的最佳值),然后再次定位新页面的元素,找到图片链接;对于重复的进行去重;直到滑到底部之后停止滑动,将定位的所有图片链接保存至.txt文档,以便后续下载图片。
完整代码和注释如下:
以下是获取图片链接并保存到本地:

from selenium import webdriver
from selenium.webdriver import Chrome
from selenium.webdriver import ChromeOptions
from selenium.webdriver.common.action_chains import ActionChains
from selenium.webdriver.common.by import By
import json
import time

cr_options = ChromeOptions()
cr_options.add_argument("--start-maximized")  #将浏览器最大化

#  Input keywords
queries = [           # 想要搜索分类的关键词
    # '頭貼 卡通',
    '动物 头像',
    # '可愛頭貼',
    # '文字 头像',
    # '人物 头像',
    # 'ins风 头像',
    # '油画 头像',
    # '摄影 风景',

]
driver = Chrome('chromedriver.exe', options=cr_options)
print('Size: ' + str(driver.get_window_size()))   
# 这里输出浏览器尺寸是为了后面调试每次滑动的最佳高度
original_urls = set()   # 将图片的原始链接存储在集合内,自动去重
lasts = []
for query in queries:
    base_url = f'https://www.pinterest.com/search/pins/?q={query}'
    driver.get(base_url)
    time.sleep(2)
    for i in range(30):     # 这里为了保证滑到底部,所以循环次数写到了30,但其实可能不需要30次
        print('i----------',i)  # 输出i来记录滑动了几次(翻了几页)
        if i < 4:
            all_elements = driver.find_elements(By.XPATH, '//div[@data-test-id="pin-visual-wrapper"]/div[1]/div[1]/img')   # 查找全部的图片元素
            print(len(all_elements))
            print('-------------------------------------------------------------------')
            # print(all_elements)
            for element in all_elements:
                img_url = element.get_attribute('src')   # 获取图片链接
                original_url = img_url.replace('236x', 'originals')   #缩略图的尺寸只有236x,替换为originals才是原图尺寸高清
                original_urls.add(original_url)
                last = img_url
                # print(img_url)
                # print(original_url)
                # break
            # print('*****************************************')
            print(last)
            lasts.append(last)
            driver.execute_script(f'window.scrollTo({i * 2000},{(i + 1) * 2000})')
            # 设置每次滑动的高度,我这里经调试后即使每次滑动2000,每页数据也还是会有重复,所以必须去重
            time.sleep(3)
        else:
            all_elements = driver.find_elements(By.XPATH, '//div[@data-test-id="pin-visual-wrapper"]/div[1]/div[1]/img')
            print(len(all_elements))
            print('------------------------------------------------------------')
            for element in all_elements:
                img_url = element.get_attribute('src')
                original_url = img_url.replace('236x', 'originals')
                original_urls.add(original_url)
                last = img_url
            print(last)
            lasts.append(last)
            if lasts[-1] == lasts[-2] and lasts[-1] == lasts[-3]:
            # 这一步操作是为了判断滑到了底部,以last来记录每一页的最后一个数据,如果连续3页数据的最后一个数据都相同,则代表滑到了底部,则停止循环
                break
            else:
                driver.execute_script(f'window.scrollTo({i * 2000},{(i + 1) * 2000})')
                # 如果没有滑到底部则继续循环
                time.sleep(3)
print('lasts: ',lasts)
print('*****************************************')
# print(original_urls)
print(len(original_urls))
for item in original_urls:
    with open('ddd.txt','a+') as f:  # 最后将爬取的链接写入ddd.txt,注意要是a+追加方式,因为该代码可能要跑几遍(毕竟科学上网不稳定,可能有图片第一遍没有获取成功)
        f.writelines(item + "\n")

以下是读取保存的图片链接,然后将图片下载下来(该操作和上面操作分开来主要是本人有几个分类要爬取,不同分类图片的链接也放在不同文件下,所以分开进行;只需要爬取一个分类的同学可以一起进行):

import requests
import time

#     '插画头像',
#     '风景头像',
#     '可爱头像',
#     '文字头像',
#     '人物头像',
#     '油画头像',
#     '设计头像',
#     '动物头像',

def downfile(file, url):      # 下载图片方法
    print("开始下载:", url)
    try:
        r = requests.get(url, stream=True,timeout=30)
        # 默认情况下是stream=False,会立即开始下载文件并存放到内存当中,倘若文件过大就会导致内存不足的情况.
        # 当把stream参数设置成True时,不会立即开始下载,当使用iter_content或iter_lines遍历内容或访问内容属性时才开始下载。
        with open(file, 'wb') as fd:
            for chunk in r.iter_content():    # iter_content:一块一块的遍历要下载的内容
                fd.write(chunk)
    except Exception as e:    #提前做好错误检查,出错时可以跳过该条继续后面的;然后多跑几次就好了
        print("下载失败了", e)

urls = []
with open("D:/python/code/Test//bak0/油画头像.txt", "r+") as f:
    for line in f.readlines():
        urls.append(line.rstrip())

for url in urls:
    headers = {'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.54 Safari/537.36'}
    PWD = 'D:/python/code/TestScrapy/img/Pinterest/油画头像/'
    name = url.split('/')[-1]
    # 将图片以最后的数字+后缀命名,方便检查文件是否存在
    filename = PWD + name
    if os.path.isfile(filename):  # 如果文件已爬取,则不再重复爬取
        print("文件存在:", filename)
        continue
    try:
        r = requests.get(url, headers=headers, stream=True,timeout=30)
    except Exception as e:   # 同样提前做好错误检查,出错时可以跳过该条继续后面的;然后多跑几次就好了
        print("请求失败了", e)
        continue
    # url = url.replace('.jpg','.png')  
    #这里的坑在于,有一些图片缩略图是.jpg格式,原图又是.png格式;
    #所以加这一行的作用是为了在爬完所有.jpg之后,如果发现有.jpg图片打不开,则是因为该图片格式错误;
    #需要手动将文件夹内打不开的图片删除,然后将这行代码取消注释,再跑几遍,直到文件夹内所有图片都可以打开。
    downfile(filename, url)
print('--------------------------------')
print('over!')

转载链接:https://juejin.cn/post/7100736788448149512

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值