有些东西实现起来真的很简单,却可以带来蛮大的体验提升。
编程有什么用?能让自己感到开心吧。如果过去的我遇到现在的我,那么会是怎样崇拜的目光呢……虽然现在的自己依然不过是一只三脚猫(鼠)。
慢慢的记录一些有趣的东西,如果明白原理,都是很简单,很基础的,而且要写的代码也很少。
有些东西实现起来真的很简单,却可以带来蛮大的体验提升。
编程有什么用?能让自己感到开心吧。如果过去的我遇到现在的我,那么会是怎样崇拜的目光呢……虽然现在的自己依然不过是一只三脚猫(鼠)。
慢慢的记录一些有趣的东西,如果明白原理,都是很简单,很基础的,而且要写的代码也很少。
我把各个平台的通知汇聚在一起,显示在 Kindle 上,然后摆在桌面。
但这个东西不适合分享出来,这有很多原因,这里不解释了。但是自己书写一个也挺简单的,只不过两个知识点:
用 Node.js 引入 http(内置模块,无需额外安装),
const http = require('http');
http.createServer(function (request, response) {
response.writeHead(200, {'Content-Type': 'text/plain'});
response.write('要输出的内容')
response.end();
}).listen(8080);
console.log('Server running at http://127.0.0.1:8080/');
构造请求也用 http 这个模块,不过有些请求需要带上 cookie。也可以使用 superagent,格式上可能简单点。
const req = http.request({
method: 'GET',
host: 'https://website.com',
port: 80,
path: '/api',
headers: {
Cookie: ['a=111', 'b=222']
}
}, res => {
res.on('data', data => console.log(data.toString()) );
});
req.on('error', function (e) {
console.log('problem with request: ' + e.message);
});
req.end();
然后,然后就把两者缝合一下就行了,展示页面随便写写就好,反正服务器是自己的,展示页面疯狂轮询自己的后端没所谓啦,如果设备支持 websocket 的话可以不轮询(Kindle 似乎不支持)。
服务器这边请求别人的数据就克制点,五分钟十分钟的查询一次就好。
有时候自己絮絮叨叨的,尤其是写代码的时候,就是忍不住吐槽,冒出什么感想又想找地方说说。但是这些内容发在什么平台也不太合适,但是记录一下以后可能还有点什么用。或者说想到什么事情就想赶紧记录一下之类的场景吧。
就开个服务器,接受请求,把接收的数据写入文本就好了。上面让间的 http 服务里,request 里面有请求信息,拿到 query 里面的参数,然后对文档进行追加就行了。我是一个月一个文档,然后每条前面标记一下时间。
然后可以写一个小书签来提交数据,或者我用 utools 的 网页快开插件 做了个自定义。
当然这只是最基本的实现,不过确实可以满足我的需求。比如多行文本,空格啥的就没特别支持。
我做了个展示界面,每次请求都会显示出所有的已有内容,也就读取文件做个简单的查找替换后显示出来。
然后页面顶端加了个表单,get 请求嘛,学前端的但凡学个十来节课都会写。现在我碎嘴子的可开心了。
学一下 CSS 选择器,然后:
document.body.querySelector(选择器).click()
找到那个展开按钮,然后点击一下。然后的问题就是搜集所有展开按钮的选择器了。
但上面的方法有个缺陷,如果在点击事件上绑定了其他操作,也会被一同触发,虽然这种情况不多见。
那就把所有限制了高度的元素取消高度限制,反正就是把所有折叠样式逆向操作一下,主要还是折腾选择器和设置样式。
当然还有更复杂的情况,但这些已经可以覆盖百分之八九十了,自用问题不大。发布出来的话……就会有一些主要访问剩余百分之一二十网站的用户说根本不管用,2333
这不就是在讲么……(其实翻翻论坛,我写了好多乱七八糟的
网页中右键——检查,在代码里选中代码块元素,但凡认真看两眼都能选对,一般那个元素叫 code(谜底写在谜面上
切换到控制台(Console),输入 $0.innerText
,回车,好了,内容被输出,复制吧。
网页都是可以修改的,但是修改以后只是本地可见,刷新就没了,也不会影响到其他人。
上面这句大差不差,但你不真的理解最好别玩,真的有风险!!!
检查元素看代码里面,双击一下就可以修改代码里的文字,什么粉丝数,账户余额随便改(改了也没啥用,就是截图炫耀下。
别问我有啥用
var arr = []
document.body.querySelectorAll('a').forEach(el=>arr.push(el.href))
console.log(arr.join('\n'))
真的是所有链接,需要更精准的选择得学学选择器,虽然也不难,但显然这里就不会去展开了。
获取页面中其他东西的方法也类似,比如所有帖子的标题,所有图片地址……剩下自己发挥想象力。
第二行的方法可以嵌套,就是一层套一层的套娃,就可以玩出更精准的数据获取,比如获取并整理页面中 n 个表格的内容。
接 编程有意思 - #2,来自 dms 这里。获取数据以后根据情况再构造一个 get 请求,利用 Server酱 或者 pushplus 这类服务,就可以轻松的顺便给自己发条微信,提醒自己有数据更新。
就这么一两个方法反复倒腾就挺好玩的了。
不太确定是否相关,不过有的时候知道一些编程相关的小知识,还是很有用的。最近遇到了一个需求,需要把一些数据从一个闭源工具里导出来,然而这个工具本身只提供了自家的云同步,并没有任何导出到本地的功能。想着毕竟不是一个特别复杂的工具,数据存储大概率用的是 SQLite,于是试着在安装目录和用户目录下找了找 .db
文件,果不其然找到了。再用 DB Browser for SQLite 打开,很方便地就把数据迁移出来了。
我一直的观点是:不一定要一个多大的目标,学一句用一句,都是有价值的。而且就算啥都没学会,对思维方式带来的影响也是很有意义的。
就是找出所有链接,改一下 target
属性。
document.body.querySelectorAll('a').forEach(el=>el.setAttribute('target', '_blank'))
挺长的,不追求自己会写,但是按单词读也能理解大概意思:
document
文档,就是当前这个网页body
网页的身体querySelectorAll
查询所有选择器(选择器在小括号里)forEach
对他们每一个做后面小括号里的操作el
被用来代表其中的每一个元素el.setAttribute
对元素设置属性就这。
接 编程有意思 - #2,来自 dms 这里。
先找一个奖牌榜的网站,查看网络数据,随便翻翻大概就能找到个 json,里面是所有国家奖牌数据,然后就是 get 这个 json。
JSON 是种文件格式,反正读取这个文件内容,用 JSON.parse(文件内容)
处理一下就得到了一个对象或者数组,有了数据自己想办法展示出来就行了。
不过,冬奥会闭幕了,但是这个方法可以应用在很多场景上,比如疫情数据啥的
不是说这个论坛的,这个要更复杂。咱们说小众主站的,评论了没发,关了标签再打开,写的内容还在,这样万一遇到个崩溃啊,手残啊,不至于自己崩溃了。
先说原理,先是选准表单,然后对表单里的元素按 name
(没有 name
就按 id
,更出乎意料的情况不讨论)挨个取值,存一个对象,然后把这个对象转换为字符串,存到浏览器的存储里,每次打开页面就看一下有没有已经存好的数据,有就再读取回来。
// 数据存这里
const data = {}
// 假设就一个表单
const form = document.body.querySelector('form')
// 找出里面所有的输入元素
form.querySelectorAll('input, textarea').forEach(el=>{
// 有 name 属性才操作
if(el.name){
// 添加一个监听器,虽然道理上是发生改变
// 但是 onchange 反应迟钝,所以用按键事件
// 道理上再加一些判断性能更好,这里简化
el.addEventListener('keypress', ()=>{
// 把值赋给 data 里面对应的属性,就放在对应的位置嘛
data[el.name] = el.value
// 把 data 写入存储
window.localStorage.setItem('formData', JSON.stringify(data))
})
}
})
实际就几行代码啦,还差一个读取恢复功能:
// 读取存储的数据
const storeData = window.localStorage.getItem('formData')
// 有存储的数据就用存储的数据,否则新建一个对象
const data = storeData ? JSON.parse(storeData) : {}
// 找出里面所有的输入元素
form.querySelectorAll('input, textarea').forEach(el=>{
// 有 name 属性才操作
if(el.name){
// 恢复存储的内容,这里不是特别严谨,但基本可用
el.value = data[el.name]
}
})
好长的内容啊,可那是因为我写了好些注释吧,实际上也没几行。上下两段的循环逻辑完全一致。知识点只有三个:
localStorage
包装成油猴子应用在所有页面,就不怕填完的内容丢失了。(实际情况比理想中的复杂,上面只是最简单的实现,所以放在所有场景中应用不够严谨,可能遇到各种意外……但,这里不展开了
最重要的是基础,我曾尝试过自学python3,遇到一些问题无法解决不得不放弃
所以有人做适当的引导还是比较好的,能指明方向不走弯路也算一种捷径了。
问题来自: 求:保存【响应式网页】到本地文件的工具 和 小众论坛上用浏览器自带搜索只能搜到一部分内容 - #16,来自 Betty
先说明,是否有必要保存整个网页这件事情有待商榷,我个人以为这个需求应该是在(资料收集)方法上就出了问题。这个工作已经接近爬虫范畴了,责问网页就有点缘木求鱼吧。但这不妨碍我们技术层面讨论。
获取一个回帖的内容很简单,这里稍微放一张图片
每个 .topic-post
就是一个回帖,但这个元素没啥特征,article
这个元素比较好,包含所有回帖内容,并且它的 id 标记了“楼层”。于是就准备一个对象储存内容,然后遍历一下这个元素:
const data = {}
document.body.querySelectorAll('.topic-post > article').forEach(el=>{
data[el.id] = el.innerHTML
})
好了,但是数量不够,因为网页没加载出来所有帖子,所以我们要让页面往下滚动,然后再获取。先说往下滚动:
while(true){
const Y = window.scrollY
window.scrollTo(0,Y+1000)
// 工作代码放这里
if(Y === window.scrollY) break
}
获取当前滚动的位置,向下滚动 1000 像素,如果位置没变化,那就不滚了,否则无休止的进行下去。兄弟们,虽然这是代码,但它不吃人,你平心静气的思考一下会发现很简单的事情啦。
上下组合一下基本就可以用了,不过严谨点最好判断一下是不是已经保存过某个帖子了,如果是,那就别覆盖了,当然,可能也要判断一下保存的版本文字长度是不是太短之类,我就不详细演示了,简单示例如下:
const data = {}
while(true){
const Y = window.scrollY
window.scrollTo(0,Y+1000)
document.body.querySelectorAll('.topic-post > article').forEach(el=>{
if(data[el.id]) return
data[el.id] = el.innerHTML
})
if(Y === window.scrollY) break
}
核心方法很简单,不过实际使用中要考虑的问题比较多,不展开,就简单说一下:
至于合并数据,拼接字符串嘛,爆内存就是另外的问题了
从这开始聊 [自荐]Easy Links,追踪和分析你的 web链接
做个简易版很容易的,已知跳转到某个网址的代码是:
window.location.href = '新地址'
做个网页,加上上面的 JS 就可以实现跳转了,这样跳转速度很快的,基本可以认为无感。当然,没有任何统计功能。
我不会写统计功能,太麻烦了,找个第三方统计代码放进去好了,你喜欢什么用什么,我不管。
然后是一个时序问题,进页面就开始跳转的话,可能统计代码还没干活,所以把统计代码放在前面,先执行它。还不放心的话加一点延时跳转就行了。这些操作都十分基础。
可是,这样只能跳转到固定链接,那我们每次有一个新连接就需要弄一个新的页面,这很烦,所以我们可以利用网址中的 get 参数来传入目标网址,类似这样:
https://shortlink.com/redirect.html?target=https://meta.appinn.net/t/topic/30149/
但这样不行,因为后面网址中的一些符号会捣乱,所以我们得先对后面的网址进行编码,你可以在控制台运行:
encodeURIComponent('https://meta.appinn.net/t/topic/30149/')
获得这样的结果:
https%3A%2F%2Fmeta.appinn.net%2Ft%2Ftopic%2F30149%2F
然后组合出来的网址我不写了,现在我们网页里要获取这个 target 的值,你去搜索获取 get 值的方法,很多会定义出一个函数,用正则什么的搜索,但是,有一些的正则写的又不够严谨。
其实,如果不考虑兼容低版本浏览器,那么有现成的方法可用,也是非常的简单:
window.location.href = (new URLSearchParams(window.location.search)).get('target')
得,弄半天就写了一句代码,整的跟没干活似的……
你看这么简单,你学会了吧, 是不是觉得那个帖子里推荐的东东也不过尔尔 ……自己动手试试吧,你就知道了。
如果上面这些你也不太在乎,那么我们的网页放在哪里呢?弄一个国内可以方便访问的网站也比较麻烦吧,何况,好多时候网址是通过 QQ 和微信发送的,自己的小网站很可能在里面被标一个大大的不安全……
所以,所以我们这里只是很单纯的聊聊技术而已。
这是对这个回帖( 为Unified Remote添加任意自定义功能,把手机变成电脑的「真」万能遥控器(兼论如何实现一键盘是英文输入法,一键盘中文输入法) - #3,来自 dms )的进一步说明。
这里只是核心原理,因为需要调用外部程序,如果没有编程基础,那么可以实现的效果比较有限。
依然是起一个服务器用来接受请求,但是考虑到我们可能实现比较多的功能,那么有几种方案可以选择:
我们就假设选择最后一种,还是 编程有意思 - #2,来自 dms 这里这样弄,然后把收到的请求输出一下,大概是 request.query
这个对象里有请求中的所有 get 参数。
这就方便了,比如获得 get 参数是 ?app=notepad
就是想打开记事本,怎么打开呢?
exec('notepad', (err, stdout, stderr) => {
if(err) {
console.log(err);
return;
}
})
行数有一点多,不过其实后面的是错误处理啥的,可以不用管,反正前面 'notepad'
里面就是 cmd 命令,就这样。那如果会写 AHK,就可以调用 AHK 去实现各种操作了。
不过除此之外,在接受请求的时候还得做一件事情,就是返回用来展示的页面,比如上面很多按钮的网页,这个自己发挥,不展开了。
如果会 JS,可以把页面里的各种操作弄得流畅一点。不会就每个按钮用一个最基本的表单提交就行。
一直想弄个类似的东西玩,一方面我手头的旧设备不是很适合,另一方面我想要的功能更复杂一点,比如实时显示当前电脑电量音量啥的。
然后这个方法除了简单还有一个好处:网页可以全屏显示(设备浏览器不太差劲的话),屏幕利用率美滋滋,设备扛得住,自己又会写的话还能加各种特效。