Распространенное сканирование через Apache Spark - возможно ли это?

Интересный вопрос, заданный мне, когда я присутствовал на одном из интервью, посвященном веб-разработке. Вопрос в том, можно ли сканировать веб-сайты с помощью Apache Spark?

Я предположил, что это возможно, потому что он поддерживает распределенную вычислительную мощность Spark. После интервью я искал это, но не нашел никакого интересного ответа. Возможно ли это с помощью Spark?

Ответ 1

Как насчет этого способа:

Ваше приложение получит набор URL-адресов веб-сайтов для ввода искателя, если вы реализуете только обычное приложение, вы можете сделать это следующим образом:

  • разделить все веб-страницы, которые будут сканироваться в список отдельных сайтов, каждый сайт достаточно мал, чтобы вписаться в один поток: 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]
  • присваивать каждому базовому url (www.example.com/news/20150401) одному потоку, он находится в потоках, где происходит действительно выборка данных.
  • сохранить результат каждого потока в FileSystem.

Когда приложение становится искровым, такая же процедура происходит, но инкапсулируется в понятии Spark: мы можем настроить CrawlRDD на тот же персонал:

  • Разделенные сайты: def getPartitions: Array[Partition] - хорошее место для выполнения задачи разделения.
  • Потоки для сканирования каждого фрагмента: def compute(part: Partition, context: TaskContext): Iterator[X] будет распространяться на всех исполнителей вашего приложения, выполняться параллельно.
  • сохранить 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()
  }
}

Ответ 2

Искра не добавляет по существу никакой ценности для этой задачи.

Конечно, вы можете распространять сканирование, но хорошие инструменты сканирования уже поддерживают это из коробки. Datastructures, предоставляемые Spark, такие как RRD, здесь практически бесполезны, и просто для запуска работ по обходам вы можете просто использовать YARN, Mesos и т.д. Непосредственно при меньших затратах.

Конечно, вы можете сделать это на Spark. Точно так же, как вы можете сделать текстовый процессор на Spark, поскольку он завершен полным... но это не становится легче.

Ответ 3

ДА.

Посмотрите проект с открытым исходным кодом: Sparkler (искрогаситель) https://github.com/USCDataScience/sparkler

Оформить заказ Внутренние источники искры для диаграммы потока/трубопровода. (Извинения, это изображение SVG, которое я не мог опубликовать здесь)

Этот проект не был доступен, когда вопрос был опубликован, однако по состоянию на декабрь 2016 года это один из самых активных проектов!

Возможно ли сканирование веб-сайтов с помощью Apache Spark?

Следующие части могут помочь вам понять, почему кто-то задал такой вопрос, а также поможет вам ответить на него.

  • Создатели среды Spark в основной работе [1] писали, что RDD будут менее подходящими для приложений, которые делают асинхронные мелкомасштабные обновления для общего состояния, такие как система хранения для веб-приложения или инкрементного веб-искателя.
  • RDD являются ключевыми компонентами Spark. Тем не менее, вы можете создавать традиционные приложения для сокращения карты (с небольшим или вообще не злоупотребляющим 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 и Committer, PMC для Apache Nutch.


Когда я создал Sparkler, я создал RDD, который является прокси-сервером для индексированного хранилища на основе Solr/Lucene. Это позволило нашему RDD сканера-датба сделать асинхронные мелкомасштабные обновления для общего состояния, что в противном случае невозможно изначально.

Ответ 4

Существует проект под названием SpookyStuff, который является

Масштабируемая система запросов для веб-лома и/mashup/приемки QA, работающая от Apache Spark

Надеюсь, что это поможет!

Ответ 5

Я думаю, что принятый ответ неверен одним фундаментальным способом; реальное крупномасштабное извлечение сети - это процесс вытягивания.

Это связано с тем, что часто запрашивать HTTP-контент часто гораздо труднее, чем создавать ответ. Я создал небольшую программу, которая способна сканировать 16 миллионов страниц в день с четырьмя ядрами ЦП и 3 ГБ оперативной памяти, и это даже не было оптимизировано очень хорошо. Для подобного сервера такая загрузка (~ 200 запросов в секунду) не является тривиальной и обычно требует много уровней оптимизации.

Реальные веб-сайты могут, например, разбить свою систему кэширования, если вы сканируете их слишком быстро (вместо того, чтобы иметь самые популярные страницы в кеше, он может быть затоплен длинным хвостом содержимого обхода). Так что в этом смысле хороший веб-скребок всегда уважает robots.txt и т.д.

Реальная польза от распределенного искателя заключается не в разделении рабочей нагрузки одного домена, а в разбиении рабочей нагрузки многих доменов на один распределенный процесс, чтобы один процесс мог уверенно отслеживать, сколько запросов система ставит через.

Конечно, в некоторых случаях вы хотите быть плохим мальчиком и навязывать правила; однако, по моему опыту, такие продукты не остаются живыми долго, так как владельцы веб-сайтов любят защищать свои активы от вещей, которые выглядят как атаки DoS.

Golang очень хорош для создания веб-скреперов, поскольку у него есть каналы как собственный тип данных, и они очень хорошо поддерживают pull-queues. Поскольку протокол HTTP и соскабливание в целом происходит медленно, вы можете включить в него процесс извлечения данных, что уменьшит объем данных, которые будут храниться в системе хранилища данных. Вы можете сканировать один ТБ с затратами ресурсов менее 1 доллара и делать это быстро, используя Golang и Google Cloud (возможно, и с AWS и Azure).

Искра не дает дополнительного значения. Использование wget в качестве клиента является умным, так как оно автоматически уважает robots.txt правильно: параллельная очередь для очереди на перенос в wget - это способ, если вы работаете профессионально.