使用Apache Spark进行分布式Web爬网 - 可能吗?

New*_*an 12 web-crawler web apache-spark

当我参加一个关于网络挖掘的访谈时,我问到了一个有趣的问题.问题是,是否可以使用Apache Spark抓取网站?

我猜这有可能,因为它支持Spark的分布式处理能力.在采访之后我搜索了这个,但找不到任何有趣的答案.这可能与Spark有关吗?

Ano*_*sse 11

Spark基本上没有为此任务增加任何价值.

当然,您可以进行分布式爬网,但良好的爬行工具已经开箱即用.Spark提供的数据结构(如RRD)在这里几乎没用,只是为了启动爬网作业,您可以直接以较少的开销使用YARN,Mesos等.

当然,你可以在Spark上做到这一点.就像你可以在Spark上做一个文字处理器,因为它是图灵完成......但它并没有变得更容易.


yjs*_*hen 6

怎么样这样:

您的应用程序将获取一组网站URL作为您的爬网程序的输入,如果您只实现一个普通的应用程序,您可以按如下方式执行:

  1. 将要抓取的所有网页拆分为单独的网站列表,每个网站都足够小,可以很好地适应单个线程: for example: you have to crawl www.example.com/news from 20150301 to 20150401, split results can be: [www.example.com/news/20150301, www.example.com/news/20150302, ..., www.example.com/news/20150401]
  2. 将每个基本url(www.example.com/news/20150401)分配给一个线程,它位于真正数据获取发生的线程中
  3. 将每个线程的结果保存到FileSystem中.

当应用程序成为一个火花时,同样的过程发生但封装在Spark概念中:我们可以自定义一个CrawlRDD做同样的工作人员:

  1. 拆分站点:def getPartitions: Array[Partition]是执行拆分任务的好地方.
  2. 用于抓取每个拆分的线程:def compute(part: Partition, context: TaskContext): Iterator[X]将传播到应用程序的所有执行程序,并行运行.
  3. 将rdd保存到HDFS中.

最终的计划如下:

class CrawlPartition(rddId: Int, idx: Int, val baseURL: String) extends Partition {}

class CrawlRDD(baseURL: String, sc: SparkContext) extends RDD[X](sc, Nil) {

  override protected def getPartitions: Array[CrawlPartition] = {
    val partitions = new ArrayBuffer[CrawlPartition]
    //split baseURL to subsets and populate the partitions
    partitions.toArray
  }

  override def compute(part: Partition, context: TaskContext): Iterator[X] = {
    val p = part.asInstanceOf[CrawlPartition]
    val baseUrl = p.baseURL

    new Iterator[X] {
       var nextURL = _
       override def hasNext: Boolean = {
         //logic to find next url if has one, fill in nextURL and return true
         // else false
       }          

       override def next(): X = {
         //logic to crawl the web page nextURL and return the content in X
       }
    } 
  }
}

object Crawl {
  def main(args: Array[String]) {
    val sparkConf = new SparkConf().setAppName("Crawler")
    val sc = new SparkContext(sparkConf)
    val crdd = new CrawlRDD("baseURL", sc)
    crdd.saveAsTextFile("hdfs://path_here")
    sc.stop()
  }
}
Run Code Online (Sandbox Code Playgroud)

  • @Yijie Shen,我已经从火花例子中给出的那个字数例子中启动了火花.我已经安装了Scala 2.10.4,Hadoop 2.7.0(http:// localhost:50070/dfshealth.html#tab-overview),spark 1.3.1(本地;主机:8080).如何将这些东西链接到支架中单独模式? (2认同)

Tha*_*wda 5

是的。

查看开源项目:Sparkler (spark - crawler) https://github.com/USCDataScience/sparkler

查看Sparkler Internals以获取流程/管道图。(抱歉,这是一张 SVG 图像,我无法在此处发布)

发布问题时该项目不可用,但截至 2016 年 12 月,它是非常活跃的项目之一!

是否可以使用 Apache Spark 抓取网站?

以下内容可以帮助您理解为什么有人会问这样的问题,也可以帮助您回答。

  • Spark 框架的创建者在开创性论文 [1] 中写道RDD 不太适合对共享状态进行异步细粒度更新的应用程序,例如 Web 应用程序的存储系统或增量 Web 爬虫
  • RDD 是 Spark 中的关键组件。但是,您可以创建传统的 map reduce 应用程序(很少或没有滥用 RDD)
  • 有一种广受欢迎的分布式网络爬虫,称为 Nutch [2]。Nutch 是使用 Hadoop Map-Reduce 构建的(实际上,Hadoop Map Reduce 是从 Nutch 代码库中提取出来的)
  • 如果你可以在 Hadoop Map Reduce 中完成一些任务,你也可以用 Apache Spark 来完成。

[1] http://dl.acm.org/citation.cfm?id=2228301
[2] http://nutch.apache.org/


PS:我是 Sparkler 的共同创建者和 Apache Nutch 的提交者、PMC。


当我设计 Sparkler 时,我创建了一个 RDD,它是基于 Solr/Lucene 的索引存储的代理。它使我们的 crawler-databse RDD 能够对共享 state 进行异步细粒度更新,否则这在本地是不可能的。