分类
网站

Python真香:尝试开发数据爬取与后端接口

高考结束,回到开往项目组。大学录取了计算机方向的专业,之前做项目的经历告诉我开发这件事情不能靠别人,自己不太好意思再给别人提需求了,也对同龄人已经熟练使用 Node.js 感到焦虑,所以这几个月自己尝试打开电脑为项目写点东西。

此前用 PHP 和原生 JavaScript 写过一点点东西,但都不算作一个项目——要么就是从网上搜随机数来实现随机动漫图片,要么就是搜索关于数组的处理方法用函数实现了一下并集、补集之类的东西。

这并不算是一个技术笔记,只是我的碎碎念。

编写 Python 数据爬取脚本

开往此前有一个“成员文章同步”的 ToDo,但是一直没有人实现。所以,我来折腾了(实则为捣乱)。

成员文章同步计划用 FreshRSS 实现,现在只需要用一个脚本爬取开往成员的订阅地址,生成一个 OPML 文件就好了。

开往成员的订阅地址从哪里整呢?组里原先有一些想法:弄个平台让站长自行提交;内置订阅地址的一些常见 uri 去测测哪个可以访问……最后,我想到了自己此前维护过的项目——中文博客列表导航。自己之前收集的那些订阅地址不就派上用场了?我可真是一个天才(猪)。

第一次,我的想法是这样的:

用 OneNote 画的超级丑的图

但是,当我真的去按照这个思路写代码的时候,电脑报错了。检查之后发现是中文博客列表导航有频率限制。我尝试 sleep 了一下,发现效果不好。这样会给中文博客列表导航发一千多次请求,对项目不友好。

所以,我对思路进行了改进(其实并不是):首先请求中文博客列表导航和开往的全量数据(相当于复刻了两个项目的数据库),再在中文博客列表导航的数据里查开往的成员网站,找到订阅地址信息。代码碎片如下:

travellingsData = requests.get('https://api.travellings.cn/all', headers = headers)
travellingsData = list(json.loads(travellingsData.text)["data"])

regex = r"^(?:https?:\/\/)?(?:[^@\/\n]+@)?(?:www\.)?([^\/:\?\n]+)"

zhblogsRequestUrl = 'https://www.zhblogs.net/api/blog/list?page=1&pageSize=7000'
zhblogsData = requests.get(zhblogsRequestUrl)
zhblogsData = json.loads(zhblogsData.text)["data"]["data"]

def searchZhblogs(targetDomain, zhblogsAllData):
    for j in zhblogsAllData:
        if targetDomain in j["url"]:
            return j
    return 0

这里有一个细节,中文博客列表导航并没有获取全量数据的接口,怎么办呢?我发现项目的博客列表请求接口时会带一个 Size 参数。我试着把这个 Size 调成一个很大很大的值,这样数据就可以覆盖项目收录的全部博客。我试了一下,果不其然,成功了。我真是一个小机灵鬼

接下来是如何生成 OPML。我找组里的 Kegongteng 要了一份文件,看了一下文件的结构,感觉还挺简单的,就是这个 xml 不知道要用什么东西搞定。字符串拼接?我之前想过这个东西,但是肉眼可见的麻烦。懒惰的我上网搜了一下 Python 生成 xml 文件的方法,发现了一个东西,让我眼前一亮。

import xml.etree.ElementTree as ET

# 创建根元素
root = ET.Element("RootElement")

# 创建子元素
child1 = ET.SubElement(root, "ChildElement")

# 添加属性
child1.attrib["attribute"] = "value"

# 创建子元素的文本内容
child1.text = "Hello, World!"

# 创建XML文件
tree = ET.ElementTree(root)
tree.write("example.xml")

当时看到这个东西就喜欢上了。这才是适合我这种小菜鸡使用的库。Python 真香!我不知道该怎么形容我喜欢它的原因,可能是“高度的语义化”?不懂。

有了这个库,我就可以不用尝试痛苦的字符串拼接了,直接写成以下代码:

root = Element('opml')
root.attrib["xmlns:frss"] = "https://freshrss.org/opml"
root.attrib["version"] = "2.0"

# head元素
head = SubElement(root, 'head')

# head里套title元素
title = SubElement(head, 'title')
title.text = "开往成员文章订阅"

# body元素
body = SubElement(root, 'body')

outline1 = SubElement(body, 'outline')
outline1.attrib["text"] = "技术博客"

for j in travellingsTechBlogData:
    searchResult = searchZhblogs(re.match(regex, j["url"]).group(1), zhblogsData)
    if searchResult != 0 and searchResult["feed"] != None:
        outline = SubElement(outline1, 'outline')
        outline.attrib["text"] = j["name"]
        outline.attrib["type"] = "rss"
        outline.attrib["xmlUrl"] = searchResult["feed"][0]["url"]
        outline.attrib["htmlUrl"] = j["url"]
        outline.attrib["description"] = searchResult["sign"]

tree = ElementTree(root)

# write out xml data
tree.write('result-tech.xml', encoding = 'utf-8', xml_declaration = True)

最后,拖了一年多的 ToDo 就被我这么折腾完了。

整完成员文章订阅的东西之后,我还弄了一个标签同步的东西,这里不再赘述。

用 Python 写巡查工具后端

一句玩笑话

开往的巡查工具又是一个拖了很久的东西,之前大蛋糕写的前端代码还在。我来折腾(捣乱)一下。

最开始是跟组里的同学确定一下需求,是这样的:

用飞书画的模式图,比较漂亮

然后,因为我喜欢折腾,所以这个东西前端和后端分成两个人完成——前端由组里的 Lee 同学负责,后端就由我来糟蹋了。

首先是看看用 Python 的什么开发。Django?太重了,还会把前端的活给刨了。FastAPI?文档看不懂(太真实了)。为什么不用 Node.js 开发呢?因为我看不懂教程。所以,我用 Python Flask 来做后端,因为它够轻,够简单,够友好。

接着,我对要用到的接口进行了整理,大致如下:

这是我第一次做项目。虽然最后没有严格按照这样开发,但我仍然认为这样做是必要的,因为这样做我不再是无头苍蝇了。

然后,我用 PHPStudy 配了一下 MySQL 数据库环境,开始“查文档-写代码-调试”的循环。这个过程超级花时间,我还容易忘记时间。几次下午坐在电脑面前一坐就坐到夜晚。几次我爸我妈教我下楼吃饭,我都还在忙着改 SQL 查询语句,最后我爸把饭端到房间让我边写边吃。

开发过程琐碎。这里列出一些问题,以及我的解决方法(或者是组里的 Lee 和 Xuanzhi 同学告诉我的)

问题解决方法
路由挤在一个文件里面不利于维护使用 Flask 的 Blueprint
要防止 SQL 注入攻击使用参数化查询
CORS 跨域使用 flask_cors 拓展库
配置参数硬写在代码里不好使用 .env 以及 Python 相应的库

Xuanzhi 还提了一些关于接口设计的问题,比如不宜用 ifSuccess 作布尔值的名称,而应为 Success 或 isSuccess。我发现我把 is 记成 if 了。

各位大佬可以在 GitHub 上看到本小菜鸡的代码。如果有改进建议,还请批评指出。

分类
生活

社交媒体向我贩售焦虑和脆弱

我在社交媒体上把好友看得太重,发消息过去没回复就想我们的关系是不是淡了。我在社交媒体上把好友看得太重,最近常常为了网上的一点争执面红耳赤。
有约不来过夜半,闲敲棋子落灯花。我大概是没有赵师秀那样的闲趣。在轻敲桌子震落灯花时,我在担心我在别人眼里是不是根本不重要。好像我的朋友比我有更多的朋友,我对我的朋友来说并不重要。
我想过成为谁生命中重要的人吗?也许是我的父母,他们有时为我感到骄傲,有时替我感到担心,我是他们生命中重要的人。也许是我的同学和老师?哦哦,我称不上在他们生命里重要的人。我在网上的那些朋友呢?说实话,我感觉我在网上就像一次性塑料瓶,别人喝了尝过滋味了,便把我丢弃了。
社交媒体放大了我对自己的能力和人际关系的焦虑。跟我同年龄的人在参加腾讯的训练营。我焦虑,在他眼里我什么都不是,我是个彻头彻尾的废物。之前我在网上的一个朋友在他频道里发「有史以来第一次觉得自己真的是个彻头彻尾的废物」,我原想安慰他,但其实我也困在其中。

分类
生活

高考之后,出分之前(已经录取版)

618买了一个笔记本,现在对着笔记本的屏幕写这篇博文。今天中午,我就可以在省考试院上查到自己的高考成绩。
我原先想说高中三年一晃就过了,但,真的吗?高中三年,我收获的不仅仅是荣誉和一个又一个成绩,还有谦逊。我不再勤去年段老师的办公室给老师整理桌面,除非别人安排我不再参与集体活动的组织,我不再向往学校社团的活动。我知道我没有力排众难的决心,我害怕自己因为组织失败而变成小丑。我在高中没有什么可以说得上要好的朋友,或许初中也是这样。中学的朋友不像小学,交个朋友还要明面确认。我不知道班级里

我刚才对着空白的文章编辑栏发呆,想了一些跟高考有关的事情,但没有写成文章的冲动。我想,要不看看我高中三年写的文章吧。这个博客是我上高一的时候重新建立的,这个博客上的文章都是我在高中时候写的。

当广播响起“考生可以进入考场”后,我们穿过警戒线,慢慢地上楼。我边走着楼梯,广播边播着考试的注意事项,初中三年几乎所有的情景就在上楼的那一瞬间闪过我的眼前。啊!要说时间过得很快嘛,九月份才到高中,这一转眼就期中考了。要说时间过得很慢嘛……初中三年也没有多慢,看,这一眨眼就过去了。

不愧是我,文章还没写,成绩就出来了。当时还在睡觉,我妈把我挖起来查分。我把个人信息填好。在点查询键之前,我拿一张纸挡着屏幕。点完查询键后,我妈说:“我先看看。”她看了一眼,尖叫了起来,然后把纸挪开。成绩贴在这边:
我的高考成绩

录取结果出来了
录取西安电子科技大学

分类
生活

我弟

今年春节,我妈郑重地对我弟说他已经八岁了。“今年几岁了?”“七岁。”“不对,你已经八岁了。记住,你已经八岁了。”她当时讲他八岁还是九岁我已经记不清了,这约莫十年的时间里我们经历了好多好多。

当我妈怀孕时,我还在上小学。那时我也说我“怀孕”了。我妈笑了笑,问:“几个月了?”我当时估计是从医院等候室电视上知道,一个月肚子是不会大的,便回答一个月。过了几周她又问,还是一个月。她的肚子渐渐大了起来,我的肚子还是那样。(最近缺乏运动,肚子胖了起来,可以说五个月了吧。)不知是哪位老师跟我们说的,要体验母亲十月怀胎的辛苦,可以把篮球塞进自己的衣服里。我曾经这样试过,细节已经忘得一干二净了。过了一段时间,我弟就开始在里面闹腾了。在我们吃饭的时候,在我们半躺在床上看书玩手机的时候,我妈突然间叫了一声,用手捂着她的肚子,估计是我弟又开始踢了。到夏天,我们吃西瓜,我妈边吃边对我说,她怀我的时候很喜欢吃西瓜,所以我也跟着爱吃西瓜了。

有次看《宝贝老板》,还是其他什么电影,我妈对我说,有了我弟之后他们对我们的爱不会少,不要担心一份爱被分成两份,他们会给出两份爱,我和我弟一人一份。我弟也会因为我更幸福,因为有三个人在爱着他。此后,我爸和我妈又在不同场合对我说了很多次,当时的我还不理解为什么这么简单的问题要重复如此多遍,写完这段话我的心酸了。

我妈生我弟,我到医院的时候,我弟已经出生了。没过多久,我妈那家人就从百公里外的老家赶了过来。不知道我弟当时怎么了,动不动就在蓝光箱里睡觉。有时他没戴眼罩,我靠着蓝光箱盯着他看,呆萌呆萌的,很可爱。先前刷到过一个视频,新生儿视力是逐渐发育的。刚开始看到人围着他时只能看见一个圈里面的模糊画面,估计是几个月后成黑白的,再过段时间才能看见彩色的世界。视频底下有条评论说,他看着看着眼眶不知不觉就湿了。我也差不多,在看那个视频的时候想起我曾经也有那么一个时候被几乎所有人温柔地爱着。我弟的出生,对于小学的我来说是一种震撼。生命原来就是这么诞生的吗?我就是这么来到这个世界了吗?

我也许在那个时候意识到,我已经成为一名哥哥了。可能因为我无情,每次打完弟弟后我都觉得自己很正确,写下这句话,提醒我这个哥哥的身份,对之前的挥出去的手十分后悔。有人说,打完孩子之后自己的心比孩子还疼。每次我妈打完我或者我弟之后,她都会说她非常后悔。

我弟大一些,我家购置了一辆婴儿车。我们带弟弟出门玩,他躺在婴儿车里。婴儿车里有挂着星星吗?不知道。弟弟多少次在婴儿车里睡着了呢?也不知道。我有时会像我妈那样把我弟抱在怀里。他头顶貌似有个东西一跳一跳的,妈妈说那是什么东西,我忘记了,她叫我千万不要去碰。有时候摇着摇着,我弟就在我怀里睡着了。“宗林学会哄弟弟睡觉了。”我爸,又或者是我妈在旁边轻声地对我说。

可能当时我还小,我弟给我们家带来的唯一的意外就是我们叫他几乎没有反应。他有个绰号叫“淘淘”,因为他在我妈肚子里时特别淘气调皮。我们一直叫他“淘淘”,他好像没有听见。这当时让我爸妈担心坏了,还带他去做核磁共振,这才放心。他不爱听别人的话,这似乎成了习惯。现在我们叫他放下手机,或者放下橡皮泥过来吃饭时,他也是爱理不理的。

可能是因为我不太喜欢说话,或者手机比我们彼此交流更加有趣,又或者说我们玩手机的内容截然不同,连手机都交流不来,我们家近年来都比较安静。我从学校回到家,再从家回到学校时,我妈都会抱怨几句:“你在家说的字用手指头就能数得过来。”我弟的出现给我们家带来了一些变化。我妈出门买菜,安排我弟做数学作业,也就是些算术题。写完,我弟估计就写了一点,便不知学谁那样说:“我累了,要休息了。”然后他就在客厅的垫子上玩,有时坐着,有时趴着。等我妈回来,便会发现整个客厅被我弟弄得一团糟。

我弟学说话比较晚。一方面在难过的时候没有办法表达出来。他很喜欢哭,特别是在吃饭的时候对着我妈哭。那种哭对我们来说是突然的。可能他提的问题我们听不懂,我们没有办法回答他,他就把眼睛眯上,嘴巴张开,哭了起来。有时,他会扑在我妈的怀里,要抱。

学英语和生物时,做题不时会看到令我感慨万千的研究。什么“低母性行为会导致心理创伤”啦,什么“吸烟会使基因甲基化程度升高影响后代发育”啦,什么“智能手机会对早期教育中各项关键能力的形成产生负面影响”啦……我很怕看到这些东西,不是因为研究报告和情境推理题难,而是因为会联想到伤人的现实。我家貌似有“怪罪”的基因,凡做错什么事出个什么岔子都要把别人数落一遍。路上但凡堵个车就怪别人瞎安排,自己事情没交代清楚就责备别人没有主动问明白,等等等等。我明白,我是懦弱的。

说话比较晚,另一方面是他会在与别的小朋友玩耍时占据劣势。他想荡秋千,不会跟别人说“我可以玩一下吗”之类的,而是直接将正在荡秋千的小朋友拉下来。他在家里很敏感,在外面又很愚钝。在这方面,我妈比我担心得多。有一次,我妈、我弟弟和我在小区里的游乐场玩。实际上,我弟弟在玩,我妈看着我弟,然后我不知道在哪里自己听自己的歌。估计是我妈看见三四个小孩都围着我弟,还就急忙上去拉开,把那伙人骂了一顿。我闻声过来,跟我妈说那叫假想防卫,人都还没动手她就先防卫上了。她不听,一直说:“那群小孩把他围住了,一定要欺负他了。三四个人围着他。”我觉得她太敏感了,她觉得我没有尽到做哥哥的责任。我弟上小学,也被人欺负。我周末回家有时会听到母亲在电话里跟别人抱怨班上有哪个孩子特别坏。我没想到小学会给家长这么多事情。
不知道是在什么时候,可能是幼儿园,还是在幼儿园以前,我弟就开始被人不看好。有一天晚上,我妈哭着跟我说:“原本生我弟是为了将来我有个帮衬,没想到会这么不争气。”一段时间后,我爸在餐桌上跟我弟说,把他卖掉好不好。我弟听不懂,也不知道大人们为什么要对他有所苛求。我妈随即叫我爸不要这么说。“他们会给出两份爱,我和我弟一人一份,我弟也会更幸福,因为有三人在爱着他。”这段大概是九年前说的话,像回旋镖一样刺中我的心。

原先过来陪护的外公已经失望了,原先跟他玩的已经不太理他了。我问自己,我有像当初说的那样爱着他吗?

这篇文章原本写在作业纸上,足足写了四张。周末又用Deepseek图片转文字,再花了点心力校对了一遍。

分类
生活

一些过往的平常的回忆

这是很早以前计划发的文章,可能是图片转文字太麻烦,或者打字一个个打太费劲,拖到今天才发。这段原先写在学校的作业纸上,今晚用Deepseek图片转文字,发现对我原先的语句做了修改,校对了一遍,有些改了回去。

周末,母亲就重疾险续保的事情与我交谈。“要是我那天被挂在墙上了……”

母亲算是第一次跟我谈起她的身后事。我起初感到意外,一个年纪还没到五十的妇女已经开始讲“如果有一天被挂在墙上”了吗?后又觉得有些惘然,自己已经十八岁了。母亲也从过去的照片里变得满头白发、满脸皱纹。不得不说:她貌似经历了这个年龄的其他女性所没有经历的东西。

父亲,从来没跟我们提他年轻时的经历。虽说母亲曾主动问过,但他只字不提。他年纪已过半百,头一回觉得他老,是在那回签房贷合同的时候。他和母亲还在担心他那年纪还能不能贷到款。父母两人向来互相诟病:母亲嫌父亲心里没家,一点责任感都没有;父亲嫌母亲把家里的事安排得一团糟。他曾经吸过烟,也曾经戒过烟,但现在估计又吸上了。虽说父亲常为了赚钱而不着家,但当我需要他的时候,比如需要送药的时候,他又常能出现。

在我小的时候,周末爸妈常要上班,走的时候不叫醒我。等我醒来,打开房间门就发现门前留了张字条,字条上大抵是“宗林宝贝,爸爸妈妈今天上午要上班,锅里留了稀饭,配肉松,爸爸妈妈中午回来”之类的话。字条通常用一罐热好了的花生牛奶压着。字条有时候是父亲写的,父亲的字有骨头,有时候像是母亲写的,她的字是软的。

有些不经意间拍下的照片,往后回过头来觉得饶有趣味,而郑重拍下的照片却无法引起心中的波澜。有些回忆,当时只道是平常,回过头来已成过往。