Algorithm Scala中的web爬虫算法
我正在尝试创建一个算法,以递归的方式和功能性的方式进行web爬网。 我知道如何使用for循环、var变量和对其进行累加。 但我正努力递归地去做 关于我的代码的一些问题: 1.为什么Algorithm Scala中的web爬虫算法,algorithm,scala,recursion,Algorithm,Scala,Recursion,我正在尝试创建一个算法,以递归的方式和功能性的方式进行web爬网。 我知道如何使用for循环、var变量和对其进行累加。 但我正努力递归地去做 关于我的代码的一些问题: 1.为什么def循环返回Any? 2.表单中有一些URL,其中getLinksPage抛出异常,返回None并中断循环。我该怎么处理呢? 3.如何使用Scala框架测试来测试这段代码 def getLinksPage(urlToCrawl: String): Option[List[String]] = { try {
def循环
返回Any
?
2.表单中有一些URL,其中getLinksPage抛出异常,返回None并中断循环。我该怎么处理呢?
3.如何使用Scala框架测试来测试这段代码
def getLinksPage(urlToCrawl: String): Option[List[String]] = {
try {
val conn = Jsoup.connect(urlToCrawl)
val doc = conn.get()
val elements = doc.select("a[href]")
val elementsSc = elements.asScala
val links = elementsSc.map(_.attr("abs:href")).toSeq
val linksURL = links.map(new URL(_))
val tartgetURL = (new URL(urlToCrawl)).getHost
val linksLocalURL = linksURL.filter(_.getHost == tartgetURL).map(_.toString).toList
Some(linksLocalURL)
}
catch {
case e: Exception => None
}
}
def loop(l:Option[List[String]], acc: List[String]): Any = l match {
case Some(Nil) => acc
case Some(hd::tl) => if (!acc.contains(hd)) loop(getLinksPage(hd),hd::acc)
else loop(Option(tl), acc)
case None => acc
}
loop(getLinksPage(mainURL), List(mainURL))
List[String]
进行理解
应该有助于理解。另外,为了简单起见,只需返回<代码>列表>代码>而不是使用<代码>列表[String ] > <代码>选项[列表] <代码> >空< /COL> conn
实例混合在一起,该trait将允许您覆盖该值,或者更改您的函数以获取隐式conn
,然后您的单元测试可以模拟该隐式conn
ScalaTest
作为独立单元测试getLinksPage
和loop
函数。免责声明:语法可能不是100%;根据需要进行调整
case class Crawler() {
def getConnection(url: String) = Jsoup.connect(url)
def getLinksPage(urlToCrawl: String): Option[List[String]] = {
val conn = getConnection(urlToCrawl)
...
}
}
class CrawerSpec extends WordSpec with MockFactory {
trait LinksFixture {
val connection = mock[Connection]
val getConnection = mockFunction[String, Connection]
lazy val crawler = new Crawler() {
override def getConnection(url: String) = LinksFixture.this.getConnection(url)
}
}
trait LoopFixture {
val getLinksPage = mock[String, Option[List[String]]]
lazy val crawler = new Crawler() {
override def getLinksPage(url: String) = LoopFixture.this.getLinksPage(url)
}
}
"getLinksPage" should {
"return the links" in new LinksFixture {
val url = "http://bad-wolf"
getConnection expects(url) returning connection
// add other expects on connection
crawler.getLinksPage(url) shouldBe expected // define expected
}
}
"loop" should {
"loop over the links" in new LoopFixture {
getLinksPage expects(*) onCall {
_ match {
case "a" => Some(List("b","c"))
case "b" => Some(List("d"))
case _ => None
}
}
// add any other expects
crawler.loop(Some(List("a")), List.empty[String]) shouldBe // define expected
}
}
}
谢谢关于第3点,如何使用递归http链接在本地模拟web服务器来测试web爬虫?哪个框架(ScalaMock…)?更新了答案,并提供了示例单元测试。不保证语法正确。:)我不明白你为什么用这个。而且这对我不起作用。我在编辑2中用我的代码复制了你的代码,但它不起作用。如果你有什么错误呢?在测试时,我的首选是使用可以混合到每个单独测试中的夹具在测试中设置代码。这允许我在测试不同的输入/输出时重用相同的夹具。我已经发布了我的代码,复制了给我带来错误的特性。