2025-08-06如何批量下载pinterset官网高清原图作品集图片

334 阅读6分钟

image-20250806003428773

* 2025-08-06如何批量下载pinterset官网高清原图作品集图片*

亲测有效:程序更新时间:2025-08-03

pinterest图片下载器链接: pan.baidu.com/s/1O2kO3xDO… 提取码: uuib

使用过程有任何问题可以联系沟通。

第1步:

必须安装chorme谷歌浏览器,同时要自行解决科学上网,如果不能正常访问behance网站那么该程序也是无法正常下载图片

img

*第2步:双击 *Pinterest图片下载器 ****** .exe文件 ****** ****** 弹出一个黑色面板和图片下载面板。注意不要关闭黑色面板。

img

*第3步:打开 *www.pinterest.com/ ****** 网站

img

*第4步 * ****** 选择 ****** 下载方式

第1种下载方式是按输入关键词搜索下载

image-20250806004044902

image-20250806004101812

img

第2种下载方式是按相似图片url下载

image-20250806004138835

img

* *5 ****** 步:程序会自动打开chorme谷歌浏览器访问输入的作品地址 ****** ,请不要关闭新打开的 ****** chorme谷歌浏览器;

* *6 ****** 步:自动下载作品所有图片,根据作品标题自动创建图片文件夹;

img

* *7 ****** 步:检查下载的图片;都是高清的原图;

img

开发代码

``

import os
import time
import threading
import random
import json
import requests
import re
from datetime import datetime
from PyQt5.QtCore import Qt, pyqtSignal, QObject
from concurrent.futures import ThreadPoolExecutor, as_completed
from jsonpath import jsonpath
​
# 开发者信息
DEVELOPER_INFO = """
"""class LicenseManager:
    """许可证管理器,负责处理试用次数限制 """
    def __init__(self):
        self.ensure_license_file()
​
    def ensure_license_file(self):
        """ 确保许可证文件存在 """
        if not os.path.exists(self.license_file):
            try:
                with open(self.license_file, 'w') as f:
                    f.write("30")  # 默认写入30次试用次数
            except:
                # 如果无法创建文件,退出程序
                QMessageBox.critical(None, "错误", "无法创建试用次数文件,程序将退出")
                os._exit(1)
​
    def read_use_count(self):
        """ 读取剩余使用次数 """
        if not os.path.exists(self.license_file):
            return 0
            
        try:
            with open(self.license_file, 'r') as f:
                content = f.read().strip()
                return int(content) if content.isdigit() else 0
        except:
            return 0  # 如果读取失败,默认返回0次
​
    def write_use_count(self, count):
        """ 写入剩余使用次数 """
        try:
            with open(self.license_file, 'w') as f:
                f.write(str(count))
            return True
        except:
            return False
​
    def check_license(self):
        """ 检查license """
        remaining = self.read_use_count()
        if remaining <= 0:
            return False, "试用次数已用完"
        return True, f"剩余试用次数: {remaining}"#
​
    def update_license(self):
        """ 更新license计数 """
        remaining = self.read_use_count()
        if remaining > 0:
            self.write_use_count(remaining - 1)
​
class Communicate(QObject):
    """ 用于线程间通信的信号类 """
    update_log = pyqtSignal(str)
    progress_signal = pyqtSignal(int)
    status_signal = pyqtSignal(str)
​
class ImageDownloader(QMainWindow):
    """ 图片下载器主窗口 """
    def __init__(self):
        super().__init__()
        self.license = LicenseManager()
        self.comm = Communicate()
        # 连接信号与槽函数
        self.comm.update_log.connect(self.update_log)
        self.comm.progress_signal.connect(self.update_progress)
        self.comm.status_signal.connect(self.update_status)
        
        self.init_ui()
        self.check_license_status()
​
    def init_ui(self):
        """ 初始化用户界面 """
        self.setWindowTitle("Pinterest图片下载器(")
        self.setGeometry(100, 100, 900, 600)
        
        # 主部件和布局
        central_widget = QWidget()
        self.setCentralWidget(central_widget)
        main_layout = QVBoxLayout(central_widget)
        
        # 下载方式选择布局
        method_layout = QHBoxLayout()
        self.method_combo = QComboBox()
        self.method_combo.addItems(["按关键词下载", "按相似图片URL下载"])
        self.method_combo.currentIndexChanged.connect(self.on_method_changed)
        method_layout.addWidget(QLabel("下载方式:"))
        method_layout.addWidget(self.method_combo)
        main_layout.addLayout(method_layout)
        
        # 搜索布局
        search_layout = QHBoxLayout()
        
        # 输入框(关键词或URL)
        self.input_field = QLineEdit()
        self.input_field.setPlaceholderText("请输入搜索关键词,例如:卧室设计")
        search_layout.addWidget(self.input_field)
        
        # 页码范围选择
        search_layout.addWidget(QLabel("起始页:"))
        self.start_page_spin = QSpinBox()
        self.start_page_spin.setMinimum(1)
        self.start_page_spin.setMaximum(20)
        self.start_page_spin.setValue(1)
        search_layout.addWidget(self.start_page_spin)
        
        search_layout.addWidget(QLabel("结束页:"))
        self.end_page_spin = QSpinBox()
        self.end_page_spin.setMinimum(1)
        self.end_page_spin.setMaximum(20)
        self.end_page_spin.setValue(2)
        search_layout.addWidget(self.end_page_spin)
        
        # 下载按钮
        self.download_btn = QPushButton("开始下载")
        self.download_btn.clicked.connect(self.start_download)
        search_layout.addWidget(self.download_btn)
        
        main_layout.addLayout(search_layout)
        
        # 状态标签
        self.status_label = QLabel("状态:就绪")
        main_layout.addWidget(self.status_label)
        
        # 进度条
        self.progress_bar = QProgressBar()
        self.progress_bar.setValue(0)
        main_layout.addWidget(self.progress_bar)
        
        # 日志区域
        log_label = QLabel("下载日志:")
        main_layout.addWidget(log_label)
        
        self.log_text = QTextEdit()
        self.log_text.setReadOnly(True)
        self.log_text.setWordWrapMode(QTextOption.WrapAnywhere)
        main_layout.addWidget(self.log_text)
​
    def on_method_changed(self, index):
        """根据选择的下载方式更改输入框提示"""
        if index == 0:  # 按关键词下载
            self.input_field.setPlaceholderText("请输入搜索关键词,例如:卧室设计")
        else:  # 按相似图片URL下载
            self.input_field.setPlaceholderText("请输入Pinterest URL,")
​
    def check_license_status(self):
        """ 检查license状态并更新UI """
        valid, msg = self.license.check_license()
        self.status_label.setText(msg)
​
    def update_log(self, text):
        """ 更新日志显示 """
        timestamp = datetime.now().strftime("%H:%M:%S")
        self.log_text.append(f"[{timestamp}] {text}")
        # 自动滚动到底部
        self.log_text.verticalScrollBar().setValue(
            self.log_text.verticalScrollBar().maximum()
        )
​
    def update_progress(self, value):
        """ 更新进度条 """
        self.progress_bar.setValue(value)
​
    def update_status(self, text):
        """ 更新状态标签 """
        self.status_label.setText(text)
​
    def sanitize_filename(self, filename):
        """ 清理文件名中的非法字符 """
        # Windows中不允许的字符
        invalid_chars = '<>:"/\|?*'
        for char in invalid_chars:
            filename = filename.replace(char, '')
​
        # 去除首尾空格并限制长度
        filename = filename.strip()
        if len(filename) > 50:  # 限制长度避免过长,为页码和索引留出空间
            filename = filename[:50]
​
        return filename if filename else "untitled"
​
    def extract_pin_id(self, url):
        """从URL中提取pin ID(数字部分)"""
        # 正则表达式匹配Pinterest URL中的数字ID
        match = re.search(r'/pin/(\d+)/', url)
        if match:
            return match.group(1)
        return None
​
    def download_image(self, url, save_path):
        """ 下载单张图片 - 添加了随机延迟 """
        try:
            # 下载前添加随机延迟,模拟人类行为
            delay = random.uniform(0.5, 2.0)  # 随机等待0.5-2秒
            time.sleep(delay)
            
            headers = {
                "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36"
            }
            response = requests.get(url, headers=headers, timeout=15)
            if response.status_code == 200:
                with open(save_path, 'wb') as f:
                    f.write(response.content)
                return True, save_path
            else:
                return False, f"状态码错误: {response.status_code}"
        except Exception as e:
            return False, f"下载失败: {str(e)}"
​
    def download_thread(self, method, input_data, start_page, end_page):
        """ 下载线程函数 """
        try:
            # 根据下载方式初始化变量和URL
            if method == 0:  # 关键词下载
                keyword = input_data
                base_url = f'url'
                listen_url = 'resource/BaseSearchResource/get'
                # 创建保存图片的文件夹
                safe_keyword = self.sanitize_filename(keyword)
                save_dir = os.path.join("images", safe_keyword)
                folder_name = safe_keyword
            else:  # URL下载
                url = input_data
                pin_id = self.extract_pin_id(url)
                base_url = url
                listen_url = 'resource/RelatedModulesResource/get/?source_url'
                # 创建保存图片的文件夹(使用pin_id作为文件夹名)
                save_dir = os.path.join("images", pin_id)
                folder_name = pin_id
​
            os.makedirs(save_dir, exist_ok=True)
            self.comm.update_log.emit(f"图片将保存到: {os.path.abspath(save_dir)}")
            
            # 启动浏览器并打开目标网页
            self.comm.update_log.emit("正在启动浏览器...")
            cp = Chromium().latest_tab
            cp.listen.start(listen_url)
            time.sleep(2)
            cp.get(base_url)
            
            # 开始监听指定接口
            self.comm.update_log.emit("开始监听数据接口...")
            
            # 存储图片URL及其对应的页码
            pic_info = []  # 格式: [(url, page_num), ...]
            
            # 如果不是从第1页开始,需要先滚动到起始页
            if start_page > 1:
                self.comm.update_log.emit(f"正在跳转到第 {start_page} 页...")
                for page in range(1, start_page):
                    cp.scroll.to_bottom()
                    time.sleep(random.uniform(2, 3))
                    # 消耗掉这些页面的响应,避免影响后续数据获取
                    try:
                        cp.listen.wait(timeout=5)
                    except:
                        pass
         
            
            # 下载图片
            self.comm.update_log.emit("开始下载图片...")
            success_count = 0
            
            with ThreadPoolExecutor(max_workers=3) as executor:  # 减少线程数降低请求频率
                # 创建下载任务
                futures = []
                for idx, (pic_url, page_num) in enumerate(pic_info, start=1):
                    # 根据不同下载方式使用不同的命名逻辑
                    if method == 0:  # 关键词下载命名
                        filename = f"{folder_name}-page{page_num}-{idx}.jpg"
                    else:  # URL下载命名
                        filename = f"{folder_name}-page{page_num}-{idx}.jpg"
                        
                    save_path = os.path.join(save_dir, filename)
                    futures.append(executor.submit(self.download_image, pic_url, save_path))
                
                # 处理下载结果
                for i, future in enumerate(as_completed(futures), 1):
                    success, result = future.result()
                    if success:
                        success_count += 1
                        self.comm.update_log.emit(f"下载成功: {os.path.basename(result)}")
                    else:
                        self.comm.update_log.emit(f"下载失败: {result}")
                    
                    # 更新进度
                    progress = int((i / len(futures)) * 100)
                    self.comm.progress_signal.emit(progress)
            
            self.comm.update_log.emit(f"下载完成,成功 {success_count}/{len(pic_info)} 张图片")
            self.comm.status_signal.emit(f"下载完成:成功 {success_count}/{len(pic_info)} 张图片")
            
        except Exception as e:
            self.comm.update_log.emit(f"发生错误: {str(e)}")
            self.comm.status_signal.emit("下载失败")
        finally:
            self.comm.progress_signal.emit(100)
            self.download_btn.setEnabled(True)
​
    def start_download(self):
        """ 开始下载过程 """
        # 检查license
        valid, msg = self.license.check_license()
        if not valid:
            QMessageBox.critical(self, "授权限制", DEVELOPER_INFO + "\n" + msg)
            return
        else:
            self.status_label.setText(msg)
​
        
        # 验证输入
        if not input_data:
            if method == 0:
                QMessageBox.warning(self, "输入错误", "请输入搜索关键词")
            else:
                QMessageBox.warning(self, "输入错误", "请输入Pinterest URL")
            return
            
        # 对于URL下载方式,验证URL格式
        if method == 1:
            pin_id = self.extract_pin_id(input_data)
            if not pin_id:
                QMessageBox.warning(self, "输入错误", "无法从URL中提取有效ID,请检查URL格式")
                return
            
        if start_page > end_page:
            QMessageBox.warning(self, "输入错误", "起始页不能大于结束页")
            return
        
        # 更新license计数
        self.license.update_license()
        self.check_license_status()
        
        # 准备下载
        self.log_text.clear()
        self.progress_bar.setValue(0)
        self.download_btn.setEnabled(False)
        self.comm.status_signal.emit("正在准备下载...")
​
​
if __name__ == "__main__":
    import sys
    app = QApplication(sys.argv)
    window = ImageDownloader()
    window.show()
    sys.exit(app.exec_())