一种更好的捕鼠器-将网页转换为Web API

2020-10-31 11:41:15

今天对我来说是个大日子,因为在经历了几个月(或几年,取决于你怎么看)之后,我终于为我的企业推出了第一款产品--BrandVantage。这篇帖子讲述了我是如何从一个想法开始,然后以另一个想法结束的。

我在当地的一家网络开发机构做了几年的网络开发人员,在那段时间里,我学到了很多关于各种不同的企业如何在网上运营的知识。

我在这些企业中发现了几个共同的关键问题:

在有营销部门的大中型公司里,大部分工作都可以由一名或多名专门负责这些工作的员工负责。在较小的公司里,这些任务通常由企业主负责,但他们已经戴上了许多不同的帽子。感觉就像这里有什么东西--如果我能以不同的方式自动完成其中的一些任务,我既可以帮助企业主,也可以在这个过程中为自己赚到一些钱。这就是说,如果我能以不同的方式自动完成其中的一些任务,我既可以帮助企业主,也可以在这个过程中为自己赚到一些钱。

任务自动化,尤其是在分析或搜索引擎优化领域的任务自动化,并不是一个新想法。事实上,自从启动以来,我在Product Hunt上看到了许多类似的太空发布,但这并没有阻止我。我正在建造一个更好的捕鼠器,希望以更低的价格推出它,而不是什么真正的创新,所以这将是一场艰苦的战斗。尽管如此,帮助在线小企业像一些大企业一样高效地完成任务,是我热衷于的事情,所以我还是继续前进。

早在2015/16/17年度,当我还在做全职工作的时候,我花了很多晚上和周末来构建和修补企业主面临的问题的解决方案。这是一个从Twitter、谷歌分析和Facebook等来源提取实时信息的黑客PHP解决方案。黑客方法似乎是一个好主意,因为这似乎是人们发起事情的方式,做你能做的最快、最黑客的事情来把它赶出家门。

在开发它的过程中,我遇到了几个感兴趣的人,尽管我建造的东西几乎不能被认为是一个原型。这件事很混乱。我可以做一些基本的查询,但它不是我认为可以销售的,肯定不是用户友好的,这是我认为这款产品的关键。我还遇到了规模方面的技术问题-任何足够复杂的查询都是实时执行的,这变得越来越复杂。实时处理必须停止。我需要预先计算并将其存储在数据库中。

我想更严肃地对待这件事,我并不觉得一种快速而老套的方法来制造产品对我来说是正确的。考虑到这一点,这似乎是一个将技术堆栈转变为长期更好的东西的好机会。

搬到.NET对我来说是明智之举,因为在我的工作中,我花在.NET上的时间比在PHP上花的时间多得多,而且我更喜欢.NET而不是PHP中的工具。也就是说,我到目前为止一直在处理的.NET代码肯定会被认为是遗留代码。

在我使用版本控制之前,我的第一个.NET版本(特别是.NET Framework)试图通过实体框架使用MySQL来保持较低的成本。在经历了很大的痛苦之后,在我决定使用MongoDB之前,我使用了一小段时间的MSSQL。

MongoDB可能看起来是个奇怪的选择--有些人对你应该使用哪种类型的数据库有非常强烈的意见。老实说,在摆弄过它之后,它似乎更符合我处理问题的方式,而不是关系数据库。虽然我非常喜欢实体框架的代码优先方法,所以我用一些自定义代码重新创建了MongoDB实体框架的感觉。这后来变成了我的一个开放源码项目,叫做MongoFramework。

我不想撒谎,进展是……。缓慢。虽然我在这上面投入了相当多的时间,但这仍然是一个非常雄心勃勃的项目。我对建造MVP有着强烈的感受,有些人过于专注于最低限度的MVP,而没有足够的注意力在可行的方面。说到底,人们会购买符合他们需求的产品,削减太多会满足不同人的需求。如果有人要使用它,在一个竞争对手众多、质量参差不齐的市场上,它必须做好自己的工作。但在这一天结束时,人们会购买符合他们需求的产品,而削减太多的产品将不会满足任何人的需求。如果有人要使用它,在一个有许多质量参差不齐的竞争对手的市场上,它必须做好它的工作。这里没有。如果我想让人们买它,我似乎不能合理地把它剪得更少。

我每天晚上都在不停地工作,从各种来源提取和存储数据。我从谷歌分析、谷歌网站管理员工具(现在称为谷歌搜索控制台)、Twitter、Facebook、IP地理位置、DNS信息和新闻文章中提取数据。我认为我能做的是,一旦我把不同的数据源放在一起,我就会编写自定义规则,从单个或组合的数据集推断洞察力。这些洞察力将构成数字品牌专家的基础。毕竟,这就是这个想法的目标,可以帮助小企业主。

在业余时间从事这项工作两年后,我觉得现在是离开工作进入这份全职工作的合适时机了。我觉得我离推出这份工作如此之近,我只是需要一些比日常工作更多的东西。所以我做到了-我在7年后离开了工作岗位。

刚走出大门,我就从.NET Framework转移到.NET Core,正在为应用程序改进UI/UX,并为其推出了网站。我与一名会计师和一名律师合作建立了业务,为产品名称购买了商标,我感觉很好,就像离推出只有几个月了一样。尽管这种感觉并没有持续太久……。

随着时间的推移,感觉就像我先前进了两步,然后又后退了一步--有些是技术上的,有些是业务上的。当然,这仍然是进步,但每天都有新的问题出现,真的会粉碎你的动力。

我最好/最快乐/最有效率的日子是我忽略或避免不同问题的日子。如果我的登录系统有问题,我会专注于菜单的用户体验是如何工作的。如果我在数据收集方面有问题,我会在代码库中增加更多的测试。虽然我没有完全忽视这个问题,但我会等上一两个星期再看它,有点希望它会自动解决-不幸的是,事情不是这样的。

然而,随着时间的推移,我到达了一个感觉可以发射的阶段,并一直在炒作自己,直到现实降临:我实际上并没有建造我开始建造的东西。

UI/UX很好,我有部署战略和下一步计划,但它不是数字品牌专家,而是人们可以通过现有工具更好地访问信息的美化数据存储。这是一个大问题!

当我意识到这一点时,我花了大量的时间来修复这个巨大的判断失误,但我做不到。无论我怎么努力,我就是想不出如何构建这个规则引擎。我的整个思维过程就像是一片乌云。我看不到问题的解决方案,就像我对大多数其他事情所能做的那样。

这很令人沮丧,结果我中断了一个月左右的工作。当我过去有一段时间感觉不喜欢或不能做编程时,我会试图通过看一些与技术(无论是虚构的还是非虚构的)有很强联系的节目或电影来刺激它。我去的地方通常有点像钢铁侠,但这一次我是在重看《停止与着火》(Start And Fire Fire),这一次我找到了一些灵感。

在这部剧的后面,很多焦点都围绕着网络,正是在这几集里,我对互联网和互联网上的数据的看法发生了变化。第三季结尾的一句主人公的话让我产生了共鸣:

当我们决定网络是什么的那一刻,我们就输了。当我们试图告诉人们该怎么做的时候,我们输了。我们所要做的就是造一扇门,让他们进来。

互联网是信息的宝库,它是可以搜索的,但一般都是无结构的。人们用HTML创建了各种各样的页面,但在制作网站的过程中,一切都是为人类用户设计的。原因很明显,我们毕竟是网页的消费者。不是吗?

在这些用户友好的网页背后通常有其他特定的标记,为特定情况提供一定级别的结构化数据。有时它是搜索引擎的描述元标记,其他时候可能是社交媒体链接的Open Graph元标记。我们构建这些东西是为了帮助计算机处理我们的网页。

2011年,Schema.org成立。这是谷歌、必应和雅虎(同年晚些时候,也是Yandex)合作的成果,其使命是为互联网、网页、电子邮件和其他地方的结构化数据创建、维护和推广模式。通过3种不同的编码(Microdata、RDFa和JSON-LD),网站可以表达详细的结构化数据。

虽然我非常喜欢计算机和编程,但它们也用来帮助我们实现其他目标。从我试图建立一个数字品牌专家的尝试中,我知道数据是帮助建立更先进的系统和提供新见解的基础。从世界各地的网页上更容易地访问其他形式的数据,可能会允许建立新的和不同的工具。

因此,我决定不去尝试解决困扰我的问题,而是将我的产品作为重心。它不会成为数字品牌专家(目前还没有),相反,它将成为一家独立的数据提供商。功能范围更小,发展道路似乎更清晰--我提供来自网页的结构化数据。

以这种方式成为一名数据提供商可以帮助我在以后的某个时间点实现最初的目标--我将拥有我的竞争对手实际上无法拥有或以比他们更低的成本拥有的独一无二的数据集。例如,当我将新闻文章整合到我的数字品牌专家中时,我使用的服务的月费很高,而且对查询的访问仍然相对有限。作为我自己的数据提供商,我可以免费访问像新闻文章这样的内容。

这样想,我基本上是让我的数字品牌专家概念中断一下,而我可以赚钱,为其他人提供数据来构建工具或整合到他们自己的工作流程中。因此,我在2019年末设计了一个工具,从网页中提取结构化数据。

我们的目标是标准化和互操作性,因此我需要支持现有的主要结构化数据类型,但也需要在缺少结构化数据的地方派生结构化数据。出于互操作性原因,我不想为结构化数据创建新的标准。相反,我决定Schema.org词汇表将非常适合我的用例。

Schema.org中有很多类型,我不想自己编写它们,所以我找到了一个名为Schema.Net的库。而且因为我关心开源,而且我会很大程度上依赖该库,所以我贡献了各种补丁和性能改进。我现在是该项目的联合合作者,该项目的创建者穆罕默德·雷汉·赛义德(Muhammad Rehan Saeed)。

我构建了一个初始原型,看看它是否可行,而且它是可行的-我能够将常见的已知数据格式提取为单一格式。在接下来的几周里,我继续改进它,并使用一些基本逻辑对其进行扩展,以便从没有任何基本逻辑的页面中派生出新的结构化数据。

现在我实现了我设定的目标,我需要把它放到一些可以卖的东西上。

到目前为止,我已经拿到了我的数字品牌专家的所有代码,其中很多实际上都是可用的,所以我只是去掉了我不需要的东西,开始把我的原型移植到里面。需要做一些工作才能把它们连接在一起,但总体来说,这一部分进行得相当顺利。

在我真正将订阅/支付集成到应用程序中之前,一切看起来都很好。我对数字品牌专家的想法在一些方面存在缺陷,最近我发现了国际销售税这个有趣的世界。

我尝试了几种不同的解决方案,并与我的会计联系,讨论哪些方案可行,但最终花费的时间比我希望的要长得多。这些不同的业务/集成问题中的每一个都会损害我的工作效率,就像我最初的想法遇到的问题一样-这很难。

我确实遇到了不同的生产率下滑(和一次崩溃),但最终,我缓慢而稳步地取得了进展,最终达到了推出某种产品的地步。

我喜欢知道事情是如何运作的,我相信外面的其他人也有类似的情况,所以这里是一些方面的技术分析:

核心是作为Azure App Service在Linux上运行的ASP.NET Core 3.1应用程序。数据库由MongoDB(在MongoDB Atlas上)提供支持,使用我的类似于实体框架的开源库MongoFramework.应用程序中的各个页面都是Razor页面,API本身使用的是MVC。

在API内部,我使用Schema.NET与Schema.org词汇表相互转换,API本身在转换页面时支持robots.txt文件,因此我构建了一个强大的开放源码解决方案来解析robots.txt文件。

此外,系统的不同方面在内部使用缓存,其中我使用了Cache Tower,这是我自己的支持多层缓存的缓存库。

为了处理后台任务,比如从数据库中删除旧数据,我使用Hangfire。对于错误记录,我使用Sentry,我已经编写了一个自定义层来挂钩Hangfire异常。对于性能监控,我使用MiniProfiler,我已经在其中添加了对MongoFramework的支持,这样我就可以看到我的查询花费了多长时间。

GitHub管理代码本身,Azure DevOps管理应用程序的构建、测试和部署。我实际上在本地运行我自己的Azure DevOps构建代理,这对构建和发布性能有很大帮助。

在我即将结束人生的一个篇章,开启另一个篇章之际,写这篇文章有一种宣泄的感觉。推出BrandVantage对我来说是一大步-我对此既兴奋又紧张,尽管我对这个行业的未来持乐观态度。

我确实计划再次考虑数字品牌专家的想法。我仍然认为有一些好的东西,但下次我想我会准备得更充分一些。