老师手上有一个项目,是某展馆的一个数据大屏。
这个项目之前是某大四学生开发的,现在他去实习了,系统还有一些东西要改,这个系统的开发和维护现在到我手上了 ¥ヾ(≧▽≦*)o¥
接手代码
这个数据大屏项目使用React写的,刚好之前把React学明白了,项目都能看明白。
整体看过去这个项目结构写的非常的好,代码非常整洁。
到此为止我以为开发它的人是个很厉害的人。
直到我看到某些地方的代码···
formatter: function (data) {
if (data.name == "黑龙江省") {
return (
"          " +
"黑龙江省" +
"<br>" +
" " +
data.data.value[0].name +
"----->" +
"丽水市" +
" " +
data.data.value[0].value +
"人 " +
"<br>" +
" " +
data.data.value[1].name +
"----->" +
" " +
"丽水市" +
" " +
data.data.value[1].value +
"人 "
);
}
if (data.name == "河北省") {
return (
"                    " +
"河北省" +
"<br>" +
" " +
data.data.value[0].name +
"----->" +
"丽水市" +
" " +
data.data.value[0].value +
"人 " +
"<br>" +
" " +
data.data.value[1].name +
"----->" +
" " +
"丽水市" +
" " +
data.data.value[1].value +
"人 "
);
}
if (data.name == "北京市") {
return (
"                    " +
"北京市" +
"<br>" +
" " +
data.data.value[0].name +
"----->" +
"丽水市" +
" " +
data.data.value[0].value +
"人 " +
"<br>" +
" " +
data.data.value[1].name +
"----->" +
" " +
"丽水市" +
" " +
data.data.value[1].value +
"人 "
);
}
// ································· //
if (data.name == "辽宁省") {
return (
"                    " +
"辽宁省" +
"<br>" +
" " +
data.data.value[0].name +
"----->" +
"丽水市" +
" " +
data.data.value[0].value +
"人 "
);
}
}
这代码写的和其他地方写的明显不是一个人写的。
问了一下老师,哦哦——套的模板···
上一个写这个代码的人是一个不会用循环的人o_o ....
完成需求
这个页面接手后是由很多问题的,为了我的身心健康,首先把前人写的东西重构了,接着是老师提需求···
- 让这个数据大屏能够响应式布局,能够支持Pad端查看
- 里面的一些新闻数据旧了,去爬新的
- 用知识图谱展示数据
- 点击新闻时要在页内浏览,不要打开新标签页
- ······
其中爬新闻这一块最麻烦也最有意思
爬新闻
之前爬的那些信息是用Python爬的(他直接用了python的标志http库o_o ....),相当一部分新闻的链接都是临时的搜索跳转链接,这一部分全部都失效了。
需要爬取的新闻的关键词是固定的,而很多网站里面都有搜索功能,于是我使用Golang写了个简单程序去逐页搜索爬取,但是这个方法在请求多了之后会被风控,而且也并不是每个网站的搜索接口都那么好调用,这一个方法在爬了一些网站之后,老师觉得爬的太少,于是要换新的方法···
于是我想到,可以利用baidu啦、bing啦、google啦这样的搜索引擎,这样不用针对每一个网站写爬虫,只要搜索引擎收录的就可以啦。
但实际编写程序才发现他们反爬虫做的更离谱 ( ̄▽ ̄)"
撇了一眼浏览器上的油猴插件···我明白了!
// ==UserScript==
// @name 必应爬取
// @namespace Violentmonkey Scripts
// @match https://cn.bing.com/search*
// @grant none
// @version 1.0
// @author -
// @description 2024/3/18 20:53:51
// ==/UserScript==
window.onload = ()=>{
function downloadFileData(data, fileName) {
blob = new Blob(data);
let blobUrl = window.URL.createObjectURL(blob);
let link = document.createElement('a');
link.download = fileName;
link.style.display = 'none';
link.href = blobUrl;
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
}
let rearr = []
document.querySelectorAll(".b_algo").forEach(e=>{
let d= {
url:e.querySelector(".tilk")?.href,
site:e.querySelector(".tptt")?.innerText,
title:e.querySelector("h2")?.innerText,
}
rearr.push(d)
})
downloadFileData([JSON.stringify(rearr)],document.title + document.querySelector(".sb_pagS ").innerHTML)
// 下一页
document.querySelector(".sb_pagS ").parentElement.nextSibling.childNodes[0].click()
}
这段脚本会在必应搜索时将当前页面的搜索结果整理、发起下载请求然后跳转下一页···
像学习强国、潮新闻这些不允许搜索引擎收录,我给他们单独写了类似于上面的脚本。
这些网站在其他地方做了反爬虫,所以他们似乎对浏览器很信任,无论开多少个标签页同时爬似乎也不会有什么问题。
部署
需求完成的差不多了,趁着没人,老师带我去部署大屏,第一次去,出了以下问题:
- 大屏里面的知识图谱似乎不支持Windows触摸屏
- 为了开机自启用electron套了层壳,这层壳完全无法响应触摸事件
- 全屏状态下需要一个关闭按钮
知识图谱使用echarts画的,echarts似乎默认Windows不会用触屏,所以不处理触摸事件,搜了一下,需要添加这样的代码:
// 强制触摸屏支持
import zRenderEnv from 'zrender/lib/core/env';
zRenderEnv.touchEventsSupported = true;
zRenderEnv.pointerEventsSupported = false;
这是一种办法,还有一种办法是改浏览器UA,让echarts以为是安卓端。
我呢,两个方法都采用了,页面内添加了代码,让echarts能够任何情况下支持Windows触摸屏,electron套壳改了浏览器UA,让echarts以外的东西也能正常使用。但似乎echarts以外就没有东西了
关闭按钮就在electron的preload脚本里面添加。
至于electron不响应触摸事件,搜了一下,似乎electron官方到现在还没解决,社区内有一些办法,这个问题我打算下次再去部署的时候修···
第二次去部署,一切都按预期进行,没有任何问题,唯独不响应触摸事件这个问题没复现出来···