我正在写这个程序,就像在线论坛的网络爬虫一样。对于我爬网的每个论坛,我都需要做同样的事情:

  • 登录
  • 找到木板
  • 找到帖子
  • 找到文章
  • 的永久链接
  • 查找发布该帖子的人的用户名

  • 现在,虽然每个论坛都需要执行相同的逻辑,但是每个论坛的实现都不同。例如,每个论坛的每个登录表单的输入都是不同的。一个论坛可能有一个名为“用户名”的字段,另一个论坛可能有一个名为“用户”的字段。其中一些步骤可能具有默认实现。例如,login的默认实现是不执行任何操作(因为您不必登录某些论坛即可对其进行爬网)。

    我所做的是创建了一个包含所有这些步骤的函数crawl-forum,但是实现是抽象的,并在其他地方实现。我的问题是,是使crawl-forum使用这些实现的最佳方法是什么?

    我尝试过的

    1)配置图

    到目前为止,这是我尝试过的。我在crawl-forum函数中添加了一个名为configs的新参数。这是一个 map 数据结构,如下所示:
    { :login login-function
      :find-boards find-boards-function
      ...
    }
    

    调用crawl-forum的代码负责填充该 map 。我不喜欢的是configs需要在整个crawl-forum代码中传递。它随处添加新参数。此外,我还有一些la脚的临时代码用于处理默认实现。

    2)多方法

    我在irc上谈论了这个问题,有人给我一个想法,我应该为此使用多方法,因为它确实是多态行为。他们看起来像这样:
    (defn get-site-key [& args] (first args))
    (defmulti login get-site-key)
    (defmethod login :default [site-key cookie-store] nil)
    

    然后,客户端代码必须在外部定义自己的多重方法:
    (defmethod login :forum-1 [site-key cookie-store] (do-something cookie-store))
    

    我对此不满意的是,就像config一样,我必须将site-key传递给crawl-forum函数,而且site-key仍必须在内部各处传递。同样,每个defmethod必须作为参数传递回自己的site-key,但是没有人会使用它。这只是进行分派(dispatch)的必要参数。但是,对于我来说,很难找到详尽的多方法教程,因此,如果有更聪明的方法可以做到这一点,请告诉我。

    有没有第三种更好的选择?有没有更好的方法来使用多方法?让我知道,谢谢。

    最佳答案

    我会选择选项1。如果使 map 困扰,您始终可以使用动态var。对于默认值,我建议使用合并:

    (def defaults { ... })
    (def site-specific (merge defaults { ...}))
    

    10-04 21:10