暗梦先生呀~ | 2022-6-17 | 最近更新于 2023-5-30 | 技术分享 | 1.6k 字 | 预计阅读时间 7 分钟 2022年上半年后,又迎来暑假的炎热,来讲讲如何搭建一个属于自己的TermBlog 其实它是利用获取feed/atom订阅的原理哈,不一定能获取所有的文章。 至于暗梦我为什么会这样想呢,因为在90年代那个时候互联网不发达的时候,某些高校会使用Telnet Term来作为在线BBS论坛,但是对于以前的Telnet属于明文传输,现在的SSH的加密传输方式也替代了Telnet,对于那些站点也被Web端所替代,作为经典的话也值得去怀念。 I. OpenSSH服务端配置首先你的ssh服务端由密码登录变更为密钥登录,然后呢 来参考下列的流程图 (建议关闭深色模式查看哈) graph TB A("使用ssh-keygen生成密钥tip:前提是先创建一个单独的用户作为TermBlog的登录用户") --> B("修改/etc/ssh/sshd_config 配置文件禁止密码登录[Ex:RSAAuthentication yesPubkeyAuthentication yesPermitRootLogin yesPasswordAuthentication no]") B --> |将指定用户和root的密钥下载到设备上之后重启ssh服务端| C("测试root用户和指定用户的密钥登录tip:root用户的密钥请妥善保管") C --> |无法登录ssh| D("登录Vnc/tty重新配置密钥/配置") D --> A C --> |成功使用密钥免密登录ssh| E("修改 /etc/passwd 或者使用 usermod 修改默认shell为你的shell批处理脚本[Ex:(I) /etc/passwd文件格式[用户名]:x:[uid]:[gid]::[根目录]:[默认shell/shell批处理脚本](II) usermod -s [默认shell/shell批处理脚本] [用户名](usermod仅能通过su或者tty登录到root用户才能使用,直接通过ssh登录到root用户会提示未找到命令)") E --> F("禁止指定用户对sudo的使用 (visudo)[Ex:(I) 禁止用户sudo到root [用户名] ALL=(ALL:ALL) ALL,!/bin/su]") F --> G("开始编写TermBlog脚本tip:如果想要调用Python脚本则也需要创建一个单独的shell批处理脚本作为默认shell[Ex:#!/bin/bashclearpython3 ~/termblog.py]") G --> H("测试SSH Term Blog") H --> |脚本报错则修改| G H --> I("搭建成功") II.基于Python3 Feed阅读/过滤html标签部分代码 ## -*- coding:utf-8 -*- # Feed Reader By DarkDream # site:https://darkace.pages.dev import feedparser ##过滤HTML中的标签 # 将HTML中标签等信息去掉 # @param htmlstr HTML字符串. def filter_tags(htmlstr): # 先过滤CDATA re_cdata = re.compile("//<!CDATA\[[>]∗//\]>", re.I) #匹配CDATA re_script = re.compile('<\s*script[^>]*>[^<]*<\s*/\s*script\s*>', re.I) # Script re_style = re.compile('<\s*style[^>]*>[^<]*<\s*/\s*style\s*>', re.I) # style re_br = re.compile('<br\s*?/?>') # 处理换行 re_h = re.compile('</?\w+[^>]*>') # HTML标签 re_comment = re.compile('<!--[^>]*-->') # HTML注释 s = re_cdata.sub('', htmlstr) # 去掉CDATA s = re_script.sub('', s) # 去掉SCRIPT s = re_style.sub('', s) # 去掉style s = re_br.sub('\n', s) # 将br转换为换行 s = re_h.sub('', s) # 去掉HTML 标签 s = re_comment.sub('', s) # 去掉HTML注释 # 去掉多余的空行 blank_line = re.compile('\n+') s = blank_line.sub('\n', s) s = replaceCharEntity(s) # 替换实体 return s ##替换常用HTML字符实体. # 使用正常的字符替换HTML中特殊的字符实体. # 你可以添加新的实体字符到CHAR_ENTITIES中,处理更多HTML字符实体. # @param htmlstr HTML字符串. def replaceCharEntity(htmlstr): CHAR_ENTITIES = {'nbsp': ' ', '160': ' ', 'lt': '<', '60': '<', 'gt': '>', '62': '>', 'amp': '&', '38': '&', 'quot': '"''"', '34': '"', } re_charEntity = re.compile(r'&#?(?P<name>\w+);') sz = re_charEntity.search(htmlstr) while sz: entity = sz.group() # entity全称,如> key = sz.group('name') # 去除&;后entity,如>为gt try: htmlstr = re_charEntity.sub(CHAR_ENTITIES[key], htmlstr, 1) sz = re_charEntity.search(htmlstr) except KeyError: # 以空串代替 htmlstr = re_charEntity.sub('', htmlstr, 1) sz = re_charEntity.search(htmlstr) return htmlstr def repalce(s, re_exp, repl_string): return re_exp.sub(repl_string, s) def feedview(feedurl): #支持rss/rss2/atom等feed feed=feedparser.parse(feed) feed["feed"]["title"] topic=0 while(True): i=os.system("clear") print(feed.feed.title) print(feed.feed.subtitle) print(PrintColor("red")+"本站共"+str(len(feed.entries))+"篇文章 | 您正在阅读第"+str(topic+1)+"篇文章"+PrintColor("white")) print("*-----------------------------------------------------------------------*") #print("标题:"+feed.entries[topic].title) #print("URL:"+feed.entries[topic].id) #print("发布时间:"+feed.entries[topic].published) #print("作者:"+feed.entries[topic].author) content=feed.entries[topic].content[0]['value'] content = filter_tags(content) # 获取文章内容并去掉html标签 #获取文章字数 num_regex = re.compile(r'[0-9]') zimu_regex = re.compile(r'[a-zA-z]') hanzi_regex = re.compile(r'[\u4E00-\u9FA5]') num_list = num_regex.findall(content) zimu_list = zimu_regex.findall(content) hanzi_list = hanzi_regex.findall(content) total_num = len(num_list) + len(zimu_list) + len(hanzi_list) # 输出文章信息 print(PrintColor("blue")+"["+feed.entries[topic].title+"] \n"+PrintColor("skyblue")+"[Writer In "+str(feed.entries[topic].published)+" By "+feed.entries[topic].author+"]"+PrintColor("pup")+" [总字数:"+str(total_num)+" 字]"+PrintColor("white")) print() dyh="'" syh='"' #content=str(content).replace(dyh,syh) print(content) print("*--------------------------------EOF------------------------------------*") # 显示版权信息 print(PrintColor("pup")+"*-----------------------------------------------------------------------*") print("# 商业转载请联系作者获得授权,非商业转载请注明出处。") print("# For commercial use, please contact the author for authorization. For non-commercial use, please indicate the source.") print("# 协议(License):署名-非商业性使用-相同方式共享 4.0 国际 (CC BY-NC-SA 4.0)") print("# 作者(Author):"+feed.entries[topic].author) print("# 链接(URL):"+feed.entries[topic].id) print("# 来源(Source):"+feed.feed.title) print("*-----------------------------------------------------------------------*"+PrintColor("white")) # 阅读器shell指令,不过你也可以像暗梦我那样用大写字母来表示,毕竟,有的时候也为了更方便简单。 print("*[请键入字母] P(上一篇) / N(下一篇) R/Q(退出SSHTerm)*") print(PrintColor("green")) shell=input("[TermBlog]$ ") shell=shell.lower() print(PrintColor("white")) if(shell == "p"): if(topic < 1): topic=0 print("提示:这已经是第一篇文章了!") Pause_PressAnyKey() i=os.system("clear") else: topic=topic-1 i=os.system("clear") elif(shell == "n"): if(topic >= len(feed.entries)-1): topic=len(feed.entries)-1 print("提示:这已经是最后一篇文章了!") Pause_PressAnyKey() i=os.system("clear") else: topic=topic+1 i=os.system("clear") elif(shell == "r" or shell == "q"): i=os.system("clear") break # 退出阅读器 else: print("提示:无效指令!") i=os.system("clear") …至于其他功能自由发挥,比如说IP记录功能,或者在终端上的小游戏都可以。毕竟,代码在于折腾,只要有点bug,就接着折腾,在折腾的路途上领悟在其中,最后也能折腾出属于自己的璀璨星空。 em…… 但如果您的代码以奇怪的方式,正常地运行了起来,就建议不要再动它了,好吗?毕竟你已经成功了。 然后保存好先调试一下,没有问题再开放即可,另外也可以使用echo在shell批处理文件加入一段提示语,能让指定用户无法通过sftp进行文件传输(会提示 Received message too long / Received too long packet length),建议和Web端同时开放,将密钥放在Web端提供下载。 LinuxPython