关于油猴脚本
范例:使用油猴脚本及 Eagle API,开发 Pinterest 批量导入扩展
跨域访问 CORS 问题
如果你想要透过「油猴」等脚本扩展在网页中使用 Eagle API,请使用 GM_xmlhttpRequest 方法进行呼叫,即可避免跨域安全限制的问题。
GM_xmlhttpRequest({url: EAGLE_IMPORT_API_URL,method: "POST",data: JSON.stringify({ items: images, folderId: pageInfo.folderId }),onload: function(response) {}});
完整代码:
// ==UserScript==// @name Save Pinterest images to Eagle// @name:zh-CN 批量导入 Pinterest 图片到 Eagle// @name:zh-TW 批次導入 Pinterest 圖片到 Eagle// @name:ja-JP Pinterestの画像を Eagle に保存// @description Launch a script on Pinterest that automatically scrolls the page and converts all images on the page into large images (with links, names) to be added to the Eagle App.// @description:zh-CN 请确保你的网路环境可以正常访问 Pinterest,如果设备网路无法访问,此脚本将无法正常运作。在 Pinterest 画版页面启动脚本,此脚本会自动滚动页面,将页面中所有图片转换成大图(包含链接、名称),添加至 Eagle App。// @description:zh-TW 在 Pinterest 畫版頁面啓動腳本,此腳本會自動滾動頁面,將頁面中所有圖片轉換成大圖(包含鏈接、名稱),添加至 Eagle App。// @description:ja-JP Pinterestのボードページ上でスクリプトを起動すると、ページが自動的にスクロールし、ページ上のすべての画像を大きな画像(リンク、名前付き)に変換してEagleアプリに追加することができます。// @author Augus// @namespace https://eagle.cool/// @homepageURL https://eagle.cool/// @supportURL https://docs-cn.eagle.cool/// @icon https://cn.eagle.cool/favicon.png// @license MIT License// @match https://www.pinterest.com/*// @grant GM_xmlhttpRequest// @run-at context-menu// @date 06/16/2020// @modified 06/16/2020// @version 0.0.3// ==/UserScript==(function() {if (location.href.indexOf("pinterest.com") === -1) {alert("This script only works on pinterest.com.");return;}// Eagle API 服务器位置const EAGLE_SERVER_URL = "http://localhost:41595";const EAGLE_IMPORT_API_URL = `${EAGLE_SERVER_URL}/api/item/addFromURLs`;const EAGLE_CREATE_FOLDER_API_URL = `${EAGLE_SERVER_URL}/api/folder/create`;// Pinterest 当前图片、链接命名规则const SELECTOR_IMAGE = "[data-grid-item] a img[srcset]";const SELECTOR_LINK = "[data-grid-item] a";const SELECTOR_SPINNER = `[aria-label="Board Pins grid"]`;var startTime = Date.now(); // 开始滚动时间var scrollInterval; // 无限滚动,直到底部var lastScrollPos; // 上一次滚轴位置var retryCount = 0; // 目前重试次数var scrollDelay = 500; // 滚动页面延迟var retryThreshold = 4; // 无法滚动页面重试次数,当超过次数,表示到底部了var pageInfo = {imageCount: 0,imageSet: {},folderId: ""};// 创建文件夹var createFolder = function(folderName, callback) {GM_xmlhttpRequest({url: EAGLE_CREATE_FOLDER_API_URL,method: "POST",data: JSON.stringify({ folderName: folderName }),onload: function(response) {try {var result = JSON.parse(response.response);if (result.status === "success" && result.data && result.data.id) {callback(undefined, result.data);} else {callback(true);}} catch (err) {callback(true);}}});};// 滚动至页面顶端var scarollToTop = function() {window.scrollTo(0, 0);lastScrollPos = window.scrollY;};// 滚动至页面底端var scarollToBottom = function() {window.scrollTo(0, document.body.scrollHeight);// window.scrollTo(0, window.innerHeight);lastScrollPos = window.scrollY;};// 取得当前画面所有图片链接var getImgs = function() {var imgs = [];var imgElements = Array.from(document.querySelectorAll(SELECTOR_IMAGE));// 避免重复添加imgElements = imgElements.filter(function(elem) {var src = elem.src;if (!pageInfo.imageSet[src]) {pageInfo.imageSet[src] = true;return true;}return false;});var getLink = function(img) {var links = Array.from(document.querySelectorAll(SELECTOR_LINK));for (var i = 0; i < links.length; i++) {if (links[i].contains(img)) {return absolutePath(links[i].href);}}return "";};imgs = imgElements.map(function(elem, index) {pageInfo.imageCount++;return {name: elem.alt || "",url: getHighestResImg(elem) || elem.src, // 取得最大分辨率website: getLink(elem), // 取得图片链接modificationTime: startTime - pageInfo.imageCount // 强制设置时间,确保在 Eagle 顺序与 Pinterest 相同}});return imgs;};// 滚动页面并取得图片信息,发送至 Eagle Appvar fetchImages = function() {var currentScrollPos = window.scrollY;scarollToBottom();// 到底了if (lastScrollPos === currentScrollPos) {// 画面如果出现 Spinner 表示后面还有内容尚未载入完成if (!document.querySelector(SELECTOR_SPINNER)) {retryCount++;if (retryCount >= retryThreshold) {clearInterval(scrollInterval);alert(`Scan completed, a total of ${pageInfo.imageCount} images have been added to Eagle App.`);}}}// 还有内容else {retryCount = 0;var images = getImgs();addImagesToEagle(images);}}// 将图片添加至 Eaglevar addImagesToEagle = function(images) {GM_xmlhttpRequest({url: EAGLE_IMPORT_API_URL,method: "POST",data: JSON.stringify({ items: images, folderId: pageInfo.folderId }),onload: function(response) {}});}function absolutePath(href) {if (href && href.indexOf(" ") > -1) {href = href.trim().split(" ")[0];}var link = document.createElement("a");link.href = href;return link.href;}function getHighestResImg(element) {if (element.getAttribute('srcset')) {let highResImgUrl = '';let maxRes = 0;let imgWidth, urlWidthArr;element.getAttribute('srcset').split(',').forEach((item) => {urlWidthArr = item.trim().split(' ');imgWidth = parseInt(urlWidthArr[1]);if (imgWidth > maxRes) {maxRes = imgWidth;highResImgUrl = urlWidthArr[0];}});return highResImgUrl;} else {return element.getAttribute('src');}}// 脚本开始scarollToTop();// 创建本次保存使用文件夹var folderName = document.querySelector("h1") && document.querySelector("h1").innerText || "Pinterest";createFolder(folderName, function(err, folder) {if (folder) {// 持续滚动列表,直到列表没有更多内容pageInfo.folderId = folder.id;scrollInterval = setInterval(fetchImages, 1000);} else {alert("An error has occurred or the Eagle app is not open.");}});})();
