编程有意思

有些东西实现起来真的很简单,却可以带来蛮大的体验提升。

编程有什么用?能让自己感到开心吧。如果过去的我遇到现在的我,那么会是怎样崇拜的目光呢……虽然现在的自己依然不过是一只三脚猫(鼠)。

慢慢的记录一些有趣的东西,如果明白原理,都是很简单,很基础的,而且要写的代码也很少。

1 Like

通知聚合服务

我把各个平台的通知汇聚在一起,显示在 Kindle 上,然后摆在桌面。

但这个东西不适合分享出来,这有很多原因,这里不解释了。但是自己书写一个也挺简单的,只不过两个知识点:

  • 前端 JS 不方便跨域获取数据,所以我们需要一个服务器来请求数据
  • 服务器就是构造一个 get 方法(多数时候都是 get)而已

用 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,回车,好了,内容被输出,复制吧。

1 Like

I’m Rich

网页都是可以修改的,但是修改以后只是本地可见,刷新就没了,也不会影响到其他人。

上面这句大差不差,但你不真的理解最好别玩,真的有风险!!!

检查元素看代码里面,双击一下就可以修改代码里的文字,什么粉丝数,账户余额随便改(改了也没啥用,就是截图炫耀下。

所有链接地址

别问我有啥用

var arr = []
document.body.querySelectorAll('a').forEach(el=>arr.push(el.href))
console.log(arr.join('\n'))

真的是所有链接,需要更精准的选择得学学选择器,虽然也不难,但显然这里就不会去展开了。

获取页面中其他东西的方法也类似,比如所有帖子的标题,所有图片地址……剩下自己发挥想象力。

第二行的方法可以嵌套,就是一层套一层的套娃,就可以玩出更精准的数据获取,比如获取并整理页面中 n 个表格的内容。

1 Like

有事儿您叫我

编程有意思 - #2,来自 dms 这里。获取数据以后根据情况再构造一个 get 请求,利用 Server酱 或者 pushplus 这类服务,就可以轻松的顺便给自己发条微信,提醒自己有数据更新。

就这么一两个方法反复倒腾就挺好玩的了。

不太确定是否相关,不过有的时候知道一些编程相关的小知识,还是很有用的。最近遇到了一个需求,需要把一些数据从一个闭源工具里导出来,然而这个工具本身只提供了自家的云同步,并没有任何导出到本地的功能。想着毕竟不是一个特别复杂的工具,数据存储大概率用的是 SQLite,于是试着在安装目录和用户目录下找了找 .db 文件,果不其然找到了。再用 DB Browser for SQLite 打开,很方便地就把数据迁移出来了。

1 Like

我一直的观点是:不一定要一个多大的目标,学一句用一句,都是有价值的。而且就算啥都没学会,对思维方式带来的影响也是很有意义的。

3 Likes

所有链接在新窗口打开

就是找出所有链接,改一下 target 属性。

document.body.querySelectorAll('a').forEach(el=>el.setAttribute('target', '_blank'))

挺长的,不追求自己会写,但是按单词读也能理解大概意思:

  • document 文档,就是当前这个网页
  • body 网页的身体
  • querySelectorAll 查询所有选择器(选择器在小括号里)
  • forEach 对他们每一个做后面小括号里的操作
  • el 被用来代表其中的每一个元素
  • el.setAttribute 对元素设置属性

就这。

1 Like

奥运金牌榜

编程有意思 - #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
  • JSON 的两个方法
  • 事件监听器

包装成油猴子应用在所有页面,就不怕填完的内容丢失了。(实际情况比理想中的复杂,上面只是最简单的实现,所以放在所有场景中应用不够严谨,可能遇到各种意外……但,这里不展开了

最重要的是基础,我曾尝试过自学python3,遇到一些问题无法解决不得不放弃

所以有人做适当的引导还是比较好的,能指明方向不走弯路也算一种捷径了。

获取瀑布流王网页全部内容

问题来自: 求:保存【响应式网页】到本地文件的工具小众论坛上用浏览器自带搜索只能搜到一部分内容 - #16,来自 Betty

先说明,是否有必要保存整个网页这件事情有待商榷,我个人以为这个需求应该是在(资料收集)方法上就出了问题。这个工作已经接近爬虫范畴了,责问网页就有点缘木求鱼吧。但这不妨碍我们技术层面讨论。

获取一个回帖的内容很简单,这里稍微放一张图片

image

每个 .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
}

核心方法很简单,不过实际使用中要考虑的问题比较多,不展开,就简单说一下:

  • 滚动后应该给网页留出加载时间,做一个延时
  • 数据量的问题,各种意义上的可能爆内存,遍历太快还可能爆 cpu

至于合并数据,拼接字符串嘛,爆内存就是另外的问题了

链接访问统计

从这开始聊 [自荐]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 )的进一步说明。

这里只是核心原理,因为需要调用外部程序,如果没有编程基础,那么可以实现的效果比较有限。

依然是起一个服务器用来接受请求,但是考虑到我们可能实现比较多的功能,那么有几种方案可以选择:

  • 引入 Express,然后利用它的路由功能,这很方便;
  • 对请求地址用正则进行判断,算是自己完成路由功能了;
  • 就用 get 参数,这会非常简单

我们就假设选择最后一种,还是 编程有意思 - #2,来自 dms 这里这样弄,然后把收到的请求输出一下,大概是 request.query 这个对象里有请求中的所有 get 参数。

这就方便了,比如获得 get 参数是 ?app=notepad 就是想打开记事本,怎么打开呢?

  exec('notepad', (err, stdout, stderr) => {
    if(err) {
      console.log(err);
      return;
    }
  })

行数有一点多,不过其实后面的是错误处理啥的,可以不用管,反正前面 'notepad' 里面就是 cmd 命令,就这样。那如果会写 AHK,就可以调用 AHK 去实现各种操作了。

不过除此之外,在接受请求的时候还得做一件事情,就是返回用来展示的页面,比如上面很多按钮的网页,这个自己发挥,不展开了。

如果会 JS,可以把页面里的各种操作弄得流畅一点。不会就每个按钮用一个最基本的表单提交就行。


一直想弄个类似的东西玩,一方面我手头的旧设备不是很适合,另一方面我想要的功能更复杂一点,比如实时显示当前电脑电量音量啥的。

然后这个方法除了简单还有一个好处:网页可以全屏显示(设备浏览器不太差劲的话),屏幕利用率美滋滋,设备扛得住,自己又会写的话还能加各种特效。