您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
To get the following list
// ==UserScript== // @name FollowingListOfBili // @namespace http://tampermonkey.net/ // @version 0.1 // @description To get the following list // @author Ouphi // @match https://space.bilibili.com/*/fans/follow* // @icon data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw== // @grant none // @license MPL // ==/UserScript== /** * 全局or常用的变量名 * 变量命名前缀: n--num, e--element, t--text * btn--button, patt--pattern * 特殊变量: * 顾名思义:uid, fuids, fuid, href * 临时变量:i, j, k * 一些函数内变量,定义与使用相隔不远,可直观查看,不再赘述 **/ var cnt = 0 // 页面固定信息 var href = "https://space.bilibili.com/208259/fans/follow" // 默认网址 var uid = "208259" // 默认uid var patt_uid = /.+\/([0-9]+)\/.*/ // 匹配uid的正则式 // 新增内容 var n_pages = -1 // 关注列表的页数 var fuids = new Array() // 关注人uid信息的列表 var btn_next = null // “下一页”按钮元素 var btn_down = null // 新增按钮,点击后可遍历内容 var e_father_down = null // 新增按钮的父元素,用于确定位置 init() // 设置初始页面,获取信息 function init(){ console.log('2 ---- 加载成功') // 获取页面信息 href = window.location.href uid = regGroup(patt_uid, href) console.log('2 ---- 当前用户:' + '\r' + uid) // 等待页面加载后,显示下载按钮 btn_down = document.createElement('button') console.log(btn_down) waitingSetButton(btn_down) } function run(flag, next_flag, element, method, text, page) { console.log('2 ---- flag, next_flag : ' + flag + "," + next_flag) console.log('2 ---- page : ' + page) // 每隔0.1s判断一次加载进度 if(flag == 0){ var tmp = checkElement(document, method, text) if(tmp == null || (next_flag == 2 && checkUpdatingPage(page) == 0)){ setTimeout(function(){run(0, next_flag, element, method, text, page)}, 100) } else run(next_flag, next_flag, element, method, text, page) } // 初始化,得到页数与next按钮 if(flag == 1){ if(run1GetAndResetPage() == 0) // 下一步 run(0, 2, document, 'class', 'cover', 1) else // 出现异常,等待加载 setTimeout(function(){run(0, 1, document, 'class', 'be-pager-total', 1)}, 100) } // 遍历每一页,得到最终关注列表 if(flag == 2){ if(run2GetFollowingUids() != 0) return if(page == n_pages) // 最后一页 run(4, 4, element, method, text, page) else // 继续加载下一页 run(3, 3, element, method, text, page) } // 加载下一页 if(flag == 3) { if(run3GoNextPage(page) != 0) return run(0, 2, document, 'class', 'cover', page + 1) } // 最后一页,保存数据 if(flag == 4) { run4SaveDataAndReset() } } /*** * 运行流程相关函数 ***/ // TODO:验证关注列表为0的状况 // 1.得到页面信息,并返回到第一页 function run1GetAndResetPage(){ var t_pages = document.getElementsByClassName("be-pager-total")[0].textContent n_pages = regGroup(/.+([0-9]+).+/, t_pages) console.log('2 ---- ' + '关注总页数:' + ' ' + n_pages) // 二次检测,因为出现了=0的状态 if(n_pages == 0) return 1 // 回到第一页,获取“下一页“按钮,以继续 backFirstPage() btn_next = document.getElementsByClassName("be-pager-next")[0].children[0] return 0 } // 2.得到当前页的uids function run2GetFollowingUids(){ var followings = document.getElementsByClassName("cover") for(var j = 0; j < followings.length; j++){ var fuid = regGroup(patt_uid, followings[j].attributes['href'].nodeValue) fuids[fuids.length] = fuid } return 0 } // 3.点击下一页 function run3GoNextPage(page){ btn_next.click() // 一个其实没必要的冗余判断 if(page + 1 > n_pages) return 1 return 0 } // 4.保存数据并解锁下载按钮 function run4SaveDataAndReset(){ // 结束,将得到的uids文件保存到本地 console.log('2 ----\n') console.log('fuids : ' + fuids.length + '\n' + fuids) // 得到uid文本内容,并表示为二进制数据 // 第一行是关注总数目 var t_fuid = fuids.length + '\n' + fuids.join('\n') // 由于bili的限制,不能用blob(blob的url简单),暂用data代替(url中包括完整文件) downloadFile(t_fuid) // 解锁下载按钮,可以重新下载 resetButton(btn_down) console.log('2 ---- ' + '结束下载') return 0 } /**** * 按钮相关函数 ****/ function waitingSetButton(btn){ console.log(btn) var elements = document.getElementsByClassName("follow-main") if(elements == null || elements == undefined || elements.length == 0){ setTimeout(function(){waitingSetButton(btn)}, 100) } else{ setButton(btn) } } function setButton(btn){ console.log(btn) // setTimeout不能嵌套 e_father_down = document.getElementsByClassName("follow-main")[0] btn.innerHTML = '下载列表' btn.style.width = '100px' btn.style.height = '30px' btn.style.fontSize = '16px' btn.style.color = '#FFFFFF' btn.style.background = '#99CCFF' btn.style.borderRadius = '7px' btn.style.borderWidth = '0px' btn.id = 'download-following-list-button' btn.onclick = function(){clickButton(btn)} e_father_down.insertBefore(btn, e_father_down.childNodes[1]) } function clickButton(btn){ btn.disabled = true btn.style.background = '#999999' // 此处不传btn参数,默认为btn_down;如果需要复用,需要改写 run(0, 1, document, 'class', 'be-pager-total', 1) } function resetButton(btn){ fuids.length = 0 btn.disabled = false btn.style.background = '#99CCFF' } /**** * 元素处理函数 *****/ // 保存信息 function downloadFile(text){ // var fuid_href = 'data:text/txt;charset=utf-8,\ufeff' + encodeURIComponent(fuid_text) // 如果想下载为文件,可以使用上面的代码(bilibili不支持blob下载),并将元素p改为元素a,最后加个click就好了 var p = checkElement(document, 'id', 'following-list-text') if(p != null) p.remove() // 利用a元素,为二进制数据设置临时url,实现下载 var p_father = document.body p = document.createElement('p') p.id = 'following-list-text' p.textContent = text // 如果需要直观查看,可以将这行注释掉,或改为block p.style.display = 'none' p_father.appendChild(p, p_father) } // 返回第一页 function backFirstPage(){ // 回车事件 var event = new Event('keyup') event = Object.assign(event, { ctrlKey: false, metaKey: false, altKey: false, which: 13, keyCode: 13, key: 'Enter', code: 'Enter' }) // 重新跳转到起始页 var e_banner = document.getElementsByClassName("be-pager-options-elevator")[0] var e_input = e_banner.getElementsByClassName("space_input")[0] e_input.value = '1' // e_input.focus() e_input.dispatchEvent(event) } /**** * 等待相关函数 ****/ // 检查所需元素是否已加载成功 function checkElement(element, method, text){ if(element == null) return null var result = null switch(method){ case 'class': result = element.getElementsByClassName(text) break case 'tag': result = element.getElementsByTagName(text) break case 'id': result = element.getElementById(text) break default: result = element.getElementsByClassName(text) break } if(result != null && result != undefined && result.length != 0){ return result }else{ return null } } // 检查页面转换(解决有时会出现链接变了,元素能获取,但还未来得及更新的状况) function checkUpdatingPage(page){ var e_page_num = document.getElementsByClassName('be-pager-item be-pager-item-active')[0] var following = document.getElementsByClassName("cover")[0] var fuid = regGroup(patt_uid, following.attributes['href'].nodeValue) if(page.toString() == e_page_num.textContent && fuids.indexOf(fuid) == -1){ return 1 } return 0 } /**** * 一些小函数 ****/ // 正则匹配 function regGroup(patt, text){ var matched_str = text.match(patt) var result = RegExp.$1 return result }