搜索引擎已经成为广告和AI生成内容的荒地。
Google曾是互联网的冠军,其搜索结果的质量和速度无人能及。在现代社会中,Google变得臃肿且缓慢。和所有事物一样,Google也屈服于疲软的经济中,搜索质量下降。
作为一名软件工程师,搜索是一个极其重要的工具。文档往往非常密集,在某些情况下甚至不存在。没有一个强大的搜索引擎,找到解决方案或具体的代码示例几乎变得不可能。
为了改变这一现状,我决定自己开发一个个人搜索引擎。虽然这看起来是一项艰巨的任务,但许多曾经新颖的技术(如向量化数据库)如今已成为常见技术。尽管网页爬虫仍然不完全成熟,但在人工智能从互联网各个角落抓取训练数据的今天,它们已变得更加普遍。
要求
免费: 必须免费运营并且使用也是免费的。Kagi是一个很好的付费搜索引擎选项,但我相信我可以通过免费的方式构建一个“足够好”的搜索引擎。这也意味着我不打算使用像Google的API之类的服务,因为这些服务每次查询都要收费。
快速: 它必须像其他替代产品一样迅速。现在是2024年,没有人愿意等待数分钟才能得到结果。为此,我需要一种支持异步处理的语言,以便让单一服务器上的有限线程可以为尽可能多的用户服务。由于我希望成本低廉,所以服务器不仅不会很快,也不会拥有大量内存,这意味着我更倾向于使用编译语言。此外我还需要进行一些网页抓取工作,这使得语言需要具备高性能。
安全: 我希望这个系统是合法的……我不希望通过法律诉讼或违反服务条款。我也相信开放的互联网不应该跟踪用户。因此,我决定不引入账户系统或记录搜索信息。我也希望我的代码尽可能安全,这意味着不会选择C或C++。
基于这些原因并考虑到我对学习该语言的浓厚兴趣,我选择用Rust编写。
我仍处于职业生涯早期阶段,并且对Rust生态系统更是新手。在直接构建搜索引擎之前,我可以采用几个小技巧来获得较快的结果。
搜索引擎提供商Kagi以其高质量结果而闻名,并且主动使用来自Google、DuckDuckGo和Bing的数据作为其数据源之一以实现这一点。我每天大部分时间都在使用DuckDuckGo搜索,相比于现代的Google,我更偏爱它。然而,Google的图像搜索非常出色。由于Google规模庞大,它可以记录用户在搜索特定术语时点击了哪些图片,下次有人搜索该内容时会优先显示该图片,从而形成一种自我强化循环。最终,这将导致高质量的数据来源,使这些图片与相应搜索相关联。当然这只是Google在寻找相关图片时采取的众多方法之一,但这确实是Google图像搜索始终出类拔萃的主要原因之一。
按照第一步计划,我的引擎将提供DuckDuckGo的搜索结果和Google的图像。
DuckDuckGo的主要网站相当复杂,提供了大量的数据。为了限制这一点,我决定使用DuckDuckGo lite。DuckDuckGo lite有明显较少的样式,并且承诺不含JavaScript,这使得它成为更容易抓取的对象。
使用DuckDuckGo搜索提供了一个通过GET请求的简单接口。
https://lite.duckduckgo.com/lite?q=TERM
其中TERM替换为用户想要搜索的内容。
这种方法确实很好,会返回一个HTML页面,可以进一步解析,但是如果想要超过最初的30个结果又会怎样?
这之后就会变成带以下参数的POST请求。乍一看,这种形式似乎很容易添加,参数"s"和"dc"显然操纵了结果数量和分页功能。
尽管模仿了这些参数,HTML页面却似乎没有返回下一页的结果。调整参数"s"和"dc"会改变HTML页面中的数字,但并没有实际的链接变化。我还需要进一步调查是否与此有关于某种会话机制。第一次测试中我只会利用前30条结果。
代码开始比较简单。这个站点已经运行在一个axum服务器上,所以我们只需构造一个JSON API。为此,我使用了reqwest 进行非阻塞API调用,scraper 高效地解析DOM,以及[