您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
抓取豆瓣电影信息,基于Notion搭建私人电影管理系统
// ==UserScript== // @name 豆瓣电影同步到Notion // @namespace https://greasyfork.org/zh-CN/scripts/464467-%E8%B1%86%E7%93%A3%E8%AF%BB%E4%B9%A6%E5%90%8C%E6%AD%A5%E5%88%B0notion // @version 1.6 // @description 抓取豆瓣电影信息,基于Notion搭建私人电影管理系统 // @author @Yanwudong https://twitter.com/yanwudong // @match https://movie.douban.com/* // @icon https://www.google.com/s2/favicons?sz=64&domain=douban.com // @require https://code.jquery.com/jquery-3.6.0.min.js // @grant GM_xmlhttpRequest // @grant GM_getValue // @grant GM_setValue // @grant GM_addStyle // @license GNU GPLv3 // ==/UserScript== (function() { 'use strict'; // 添加CSS样式 GM_addStyle(` .toast { position: fixed; top: 150px; right: 50%; z-index: 9999; opacity: 0; transition: opacity 0.2s ease-in-out; } .toast.show { opacity: 1; } .toast-body { background-color: #f2f8f2; //border: 1px solid #ccc; //border-radius: 3px; color:#4f946e; padding: 2px; padding-left:10px; padding-right:10px box-shadow: 0 0 10px rgba(0, 0, 0, 0.2); } #nlog { top: 130px; right: 50%; z-index: 9999; opacity: 0; transition: opacity 0.2s ease-in-out; box-shadow: 0 0 10px rgba(0, 0, 0, 0.2); background: #fff; overflow: hiadden; padding: 40px 30px 30px; position: fixed; display : none; } #nlog.show { opacity: 1; } .form-group{ margin-bottom: 10px; } .form-control{ border: 1px solid #e4e6e5; border-radius: 3px; box-sizing: border-box; font-size: 13px; padding: 10px; width: 280px; } #exampleModalLabel{ cursor: pointer; font-size: 18px; line-height: 2; text-align: center; border-bottom: 2px solid #494949; color: #333; font-weight: 600; margin-bottom:20px; } #twitter{ margin-left:30px; } #saveBtn{ background-color: #41ac52; border: 1px solid #b9dcd0; color: #fff; cursor: default; font-size: 15px; font-weight: 600; padding: 0; width:79%; } .modal-footer button{ height:36px; width:19%; margin-bottom:20px; } #syncbt { display: inline-block; margin-left: 10px; font-size: 13px; color:#4f946e; background-color: #f2f8f2; padding: 2px; padding-left: 8px; padding-right: 8px; border: 1px solid #b9dcd0; border-radius:3px } #syncbt:hover { cursor: pointer; } #setbt { display: inline-block; margin-left: 5px; font-size: 13px; color:#4f946e; background-color: #f2f8f2; padding: 2px; border: 1px solid #b9dcd0; border-radius:3px } `); // 创建一个 Modal const modalHtml = ` <div class="modal fade" id="myModal" tabindex="-1" role="dialog" aria-labelledby="exampleModalLabel" aria-hidden="true"> <div class="modal-dialog" role="document"> <div class="modal-content"> <div class="modal-header"> <h5 class="modal-title" id="exampleModalLabel">Notion Api 设置</h5> </div> <div class="modal-body"> <form> <div class="form-group"> <input type="text" class="form-control" id="apiInput" placeholder="token"> </div> <div class="form-group"> <input type="text" class="form-control" id="pageIdInput" placeholder="页面 ID"> </div> </form> </div> <div class="modal-footer"> <button type="button" class="btn btn-primary" id="saveBtn">保存设置</button> <button type="button" class="btn btn-secondary" id="closeBtn" data-dismiss="modal">关闭</button> </div> <div class="modal-bottom"> <a href="https://seemly-pear-9fc.notion.site/Notion-e0ae1a1d391143abb9ff383730649149" id="refBtn" target="_blank";>操作说明</a> <a href="https://twitter.com/yanwudong" id="twitter" target="_blank";>推特</a> </div> </div> </div> </div> `; //GM_setValue('nToken', nToken); //GM_setValue('MdatabaseId', MdatabaseId); //GM_setValue('databaseId', databaseId); //初始化用户信息 var nToken = GM_getValue('nToken'); var pageId = GM_getValue('pageId'); //电影数据库Id var MdatabaseId = GM_getValue('MdatabaseId'); const notionVersion = '2022-06-28'; // 创建一个轻提示框元素 const toast = document.createElement('div'); toast.id = 'toast'; toast.className = 'toast'; toast.innerHTML =` <div class="toast-body"> 🎉 同步成功! </div> `; // 将轻提示框添加到页面中 document.body.appendChild(toast); //创建一个授权框,让用户输入ApiKey和PageId const nlog = document.createElement('div'); nlog.id = 'nlog'; nlog.innerHTML = modalHtml; document.body.appendChild(nlog); nlog.classList.add('show'); // 等待页面加载完成后执行 $(document).ready(function() { // 给按钮添加点击事件 $('#saveBtn').click(function() { nToken = $('#apiInput').val(); pageId = $('#pageIdInput').val(); GM_setValue('nToken', nToken); GM_setValue('pageId', pageId); //用户第一次使用先创建数据库 createDatabase(); nlog.style.display = 'none'; }); $('#closeBtn').click(function(){ nlog.style.display = 'none'; }); }); //检查用户是否登录 const checkUserInfo = () =>{ // 如果用户没有输入过信息,弹出输入框让其输入 if (!nToken || !pageId || !MdatabaseId ) { nlog.style.display = 'block'; }else{ syncToNotion(); } } //添加同步按钮到页面 function addButton(){ const button = document.createElement('button'); button.innerText = '同步到Notion'; button.onclick = checkUserInfo; const actions = document.querySelector('#content > h1 > .year ');//在电影名称后面加按钮 //debugger actions.insertAdjacentElement('afterend',button); button.id = 'syncbt'; }; //获取电影信息 function getMovieInfo(){ const infos = document.querySelectorAll('#info .pl'); let movie = {}; // 创建类型数组 let type = ''; let typeList = []; debugger movie['电影名'] = document.querySelector('#content > h1 > span').innerText; movie['封面'] = document.querySelector('#mainpic > a > img').src; const grade = document.querySelector('.rating_num'); if(grade != null){ movie['评分'] = document.querySelector('.rating_num').innerText; } movie['豆瓣链接']=window.location.href; movie['简介']=document.querySelector('#link-report-intra').innerText; debugger //循环遍历infos,并把每个元素赋值给info for(const info of infos){ if(info.innerText === '导演'){ movie['导演'] = info.nextSibling.nextSibling.innerText }else if(info.innerText === '编剧'){ movie['编剧'] = info.nextSibling.nextSibling.innerText }else if(info.innerText === '主演'){ movie['主演'] = info.nextSibling.nextSibling.innerText }else if(info.innerText === '上映日期:'){ movie['上映日期'] = info.nextSibling.nextSibling.innerText }else if(info.innerText === '片长:'){ movie['片长'] = info.nextSibling.nextSibling.innerText }else if(info.innerText === '类型:'){ // 找到所有具有属性 "property" 且属性值为 "v:genre" 的元素 const genreElements = document.querySelectorAll('span[property="v:genre"]'); // 遍历每个元素,将其内容添加到数组中 genreElements.forEach(function(element) { typeList.push(element.textContent.trim()); }); movie['类型'] = typeList }else{ let prop = info.innerText.substr(0,info.innerText.length-1) movie[prop] = info.nextSibling.data } } return movie } // 同步电影信息到Notion function syncToNotion(){ const movie = getMovieInfo(); createMovieItem(movie); } //创建页面电影子数据库database async function createDatabase() { const body = { 'parent': { 'type': 'page_id', 'page_id': pageId }, 'title': [ { 'type': 'text', 'text': { 'content': 'MovieList', 'link': null } } ], 'icon':{ 'type':'emoji', 'emoji':'🍿' }, 'properties': { '电影名': { 'title': {} }, '类型':{ 'multi_select':{ 'options':[ { 'name':'其他', 'color':'default' } ] } }, '地区':{ 'select':{ 'options':[ { 'name':'其他', 'color':'default' } ] } }, '状态':{ 'select':{ 'options':[ { 'name':'🌑想看', 'color':'purple' }, { 'name':'🌒在看', 'color':'orange' }, { 'name':'🌕看过', 'color':'green' } ] } }, '个人打分':{ 'select':{ 'options':[ { 'name':'⭐️⭐️⭐️⭐️⭐️' }, { 'name':'⭐️⭐️⭐️⭐️' }, { 'name':'⭐️⭐️⭐️' }, { 'name':'⭐️⭐️' }, { 'name':'⭐️' } ] } }, '导演': { 'rich_text': {} }, "创建时间": { "type": "created_time", "created_time": {} }, '主演': { 'rich_text': {} }, '简介': { 'rich_text': {} }, '上映日期': { 'rich_text': {} }, '片长': { 'number': { 'format': 'number' } }, '豆瓣评分': { 'number': { 'format': 'number' } }, 'IMDb': { 'rich_text': {} }, '封面': { 'files': {} }, '豆瓣链接': { 'url': {} }, '简介': { 'rich_text': {} }, } }; const options = { headers: { Authorization: 'Bearer ' + nToken, 'Notion-Version': notionVersion, 'Content-Type': 'application/json' }, body: JSON.stringify(body) } GM_xmlhttpRequest({ method: 'POST', url: 'https://api.notion.com/v1/databases', headers: options.headers, data: options.body, onload: function(response) { const res = JSON.parse(response.responseText); if (res.object === 'error') { alert(res.message); } else { GM_setValue('MdatabaseId',res.id); MdatabaseId = res.id; toast.innerHTML =` <div class="toast-body"> 🎉 配置成功! </div> `; // 显示轻提示框 toast.classList.add('show'); // 3秒后隐藏轻提示框 setTimeout(() => { toast.classList.remove('show'); }, 3000); } } }); } //同步电影 function createMovieItem(movie) { // 构建用于传递给 Notion 数据库的标签数据 const tagsProperties = movie['类型'].map(tag => { return { name: tag }; }); const body = { 'parent': { 'type': 'database_id', 'database_id': MdatabaseId }, 'icon':{ 'type':'emoji', 'emoji':'🎞️' }, 'properties': { '电影名': { 'type': 'title', 'title': [{ 'type': 'text', 'text': { 'content': movie['电影名'] } }] }, '封面': { 'files': [ { 'type': 'external', 'name': 'cover', 'external': { 'url': movie['封面']} }, ] }, 'IMDb': { 'type': 'rich_text', 'rich_text': [{ 'type': 'text', 'text': { 'content': movie['IMDb'] ? movie['IMDb']:'' } }] }, '片长': { 'number': parseInt(movie['片长'] ? movie['片长']:'' ) }, '状态':{ select:{ 'name':'🌑想看' } }, '上映日期': { 'type':'rich_text', 'rich_text': [{ 'type': 'text', 'text': { 'content': movie['上映日期'] ? movie['上映日期']:'' } }] } , '豆瓣评分': { 'number': parseFloat(movie['评分']) }, '导演': { 'type': 'rich_text', 'rich_text': [{ 'type': 'text', 'text': { 'content': movie['导演'] ? movie['导演']:''} }] }, '主演': { 'type': 'rich_text', 'rich_text': [{ 'type': 'text', 'text': { 'content': movie['主演'] ? movie['主演']:''} }] }, '简介': { 'type': 'rich_text', 'rich_text': [{ 'type': 'text', 'text': { 'content': movie['简介'] ? movie['简介']:''} }] }, '地区':{ select:{ 'name':movie['制片国家/地区'] ? movie['制片国家/地区']:'' } }, '类型': { "multi_select":tagsProperties }, '封面': { 'files': [ { 'type': 'external', 'name': 'cover', 'external': { 'url': movie['封面']} }, ] }, '豆瓣链接':{ 'type':'url', 'url':movie['豆瓣链接'] } }, }; //传参数 const options = { headers: { Authorization: 'Bearer ' + nToken, 'Notion-Version': notionVersion, 'Content-Type': 'application/json' }, body: JSON.stringify(body) } GM_xmlhttpRequest({ method: 'POST', url: 'https://api.notion.com/v1/pages', headers: options.headers, data: options.body, onload: function(response) { debugger const res = JSON.parse(response.responseText); if (res.object === 'error') { alert(res.message); } else { toast.innerHTML =` <div class="toast-body"> 🎉 同步成功! </div> `; // 显示轻提示框 toast.classList.add('show'); // 3秒后隐藏轻提示框 setTimeout(() => { toast.classList.remove('show'); }, 3000); } } }); } addButton(); })();