抓取特定页面和数据并使其可搜索

时间:2014-10-31 13:12:13

标签: php mysql search web-scraping web-crawler

重要提示:以下问题并不意味着打破任何数据版权。所有已爬网和已保存的数据都直接链接到源。


大家好!

对于客户我收集有关构建搜索引擎/网络蜘蛛组合的信息。我确实有索引网页的经验'具有特定深度的内部链接。我也有从网页上抓取数据的经验。但是,在这种情况下,音量大于我的经验,所以我希望在最佳实践中获得一些知识和见解。

首先,我需要明确的是,客户端将提供将要编入索引的网站列表。所以,实际上是一个垂直搜索引擎。结果只需要有链接,标题和说明(就像Google显示结果的方式)。此搜索引擎的主要目的是使访问者更容易搜索大量网站和结果,以找到他们需要的内容。 So:网站A包含大量链接 - >将所有链接与元数据一起保存。

其次,有一个更具体的搜索引擎。也可以将所有链接编入索引(让他们称之为)文章,这些文章分布在许多较小的网站上,与最终在垂直搜索引擎中的网站相比,文章数量较少。原因很简单:在这些页面上找到的文章必须尽可能详细地删除。这是第一个问题所在:为每个网站编写一个刮刀需要花费大量时间,需要收集的数据例如是:城市名称,文章日期,文章标题。 So:网站B包含比网站A更详细的文章,我们将索引这些文章并抓取有用的数据。

我确实有一种可能有效的方法,但这涉及为每个网站编写一个刮刀,实际上它是我现在能想到的唯一解决方案。由于每个页面的DOM完全不同,我认为没有选择构建一个可以搜索DOM的傻瓜式算法并且知道'页面的哪个部分是一个位置(但是,如果您可以将文本与完整的城市列表进行匹配,则可能会出现这种情况。)

我想到了一些事情:

垂直搜索引擎

  • 对于垂直搜索引擎,它非常简单,我们有一个需要编制索引的网页列表,抓取与正则表达式匹配的所有网页并存储这些网页的完整列表应该相当简单数据库中的URL。
  • 我可能希望将保存页面数据(元描述,标题等)拆分为单独的流程以加快索引编制。
  • 由于具有匹配结果/文章的网站,此搜索引擎中可能存在重复数据。我还没有考虑如何过滤这些重复项,可能是文章标题,但是在数据来自那里的业务部门中,重复标题发生了巨大变化,但文章不同

页面抓取

  • 只要我们知道与网址匹配的正则表达式,就可以以类似的方式为“待删除的”页面编制索引。我们可以在数据库中保存URL列表
  • 使用运行所有单个页面的单独进程,根据URL,scraper现在应该使用什么正则表达式来匹配页面上所需的详细信息并将这些写入数据库
  • 有足够的网站可以对结果进行索引,所以我的猜测是应该有一种方法来创建一个知道如何读取页面而不必完全匹配正则表达式的抓取算法。正如我之前所说:如果我有完整的城市名称列表,必须有一个选项来使用搜索算法来获取城市名称,而不必说the city name lies in "#content .about .city"

数据冗余

蜘蛛/爬虫的一个重要部分是防止它索引重复数据。我希望做的是跟踪爬虫开始索引网站的时间以及何时结束,然后我还会跟踪上次更新时间'一篇文章(基于文章的URL)并删除所有早于爬网开始时间的文章。因为据我所知,这些文章不再存在。

使用页面抓取工具可以更轻松地恢复数据,因为我的客户列出了一些好消息来源" (阅读:带有独特文章的页面)。垂直搜索引擎的数据冗余更难,因为被索引的网站已经从“好的来源”中选择了自己的艺术品。因此,多个网站可能会从相同的来源中进行选择。


如何使搜索结果

除了如何抓取和抓取页面之外,这是一个问题,因为一旦所有数据都存储在数据库中,就需要高速搜索。与某些竞争相比,将要保存的数据量仍然未知,我的客户有大约10,000个较小记录(垂直搜索)的记录,可能还有4,000个记录更详细的记录。

据我所知,与您可能正在处理的某些数据库相比,这仍然很少。但最终可能有多达10-20个搜索字段,用户可以使用查找他们正在寻找的内容。由于流量很大且搜索量很多,我可以想象使用常规MySQL查询进行搜索并不是一个聪明的主意。

到目前为止,我已经找到了SphinxSearch和ElasticSearch。我还没有和他们中的任何人合作过,并且我们并没有真正研究过这两者的可能性,只有我知道的是,两者都应该在数据量大和搜索查询中表现良好。


总结一下

总结一下,这里有一个问题的候选名单:

  • 是否有一种简单的方法可以创建一个能够匹配DOM数据的搜索算法,而无需指定内容所在的确切div?
  • 抓取网页的最佳做法是什么(链接,标题和说明)
  • 我应该拆分抓取的网址并保存网页标题/说明以提高速度吗?
  • PHP是否有开箱即用的解决方案可以在数据库中找到(可能的)重复数据(即使存在细微差别,例如:如果80%匹配 - >标记为重复)
  • 为数据创建面向未来的搜索引擎的最佳方法是什么(请记住,数据量可能会随着网站流量和搜索请求的增加而增加)

我希望我把所有事情都清楚了,对不起,我很抱歉。我想这确实表明我已经花了一些时间试图弄清楚自己。

7 个答案:

答案 0 :(得分:9)

我有建立大型网络抓取工具的经验,并且可以证明在执行此任务时总会遇到很大的挑战。 Web scraper遇到了从CPU问题到存储到网络问题的各种问题,并且需要构建足够模块化的任何自定义scraper,以防止一个部分的更改破坏整个应用程序。在我的项目中,我采取了以下方法:

  

找出你的应用程序在逻辑上可以分割的位置

对我而言,这意味着建立3个不同的部分:

  1. 网页刮板管理器

  2. 网页刮板

  3. HTML处理器

  4. 然后可以将工作划分为:

      

    1)Web Scraper Manager

    Web Scraper Manager将URL被删除并生成Web Scrapers。 Web Scraper Manager需要标记已发送给Web scraper的所有URL,因为它们正在被“刮掉”#34;并且知道在他们处于那种状态时不要再把他们拉下来。收到来自刮刀的消息后,经理将删除该行或将其留在"主动刮取"如果没有发生错误,则说明状态,否则会将其重置为"不活动"

      

    2)Web Scraper

    网页Scraper会收到一个要抓取的网址,然后进行CURLing并下载HTML。然后,所有这些HTML都可以存储在具有以下结构的关系数据库中

      

    ID |网址| HTML(BLOB)|加工

    Processing是一个整数标志,指示当前是否正在处理数据。这使得其他解析器知道如果已经在查看数据,则不会提取数据。

      

    3)HTML处理器

    HTML处理器将不断从HTML表中读取,每次拉出新条目时都将行标记为活动状态。只要需要解析任何数据,HTML处理器就可以自由地对HTML进行操作。这可以链接到站点中的其他页面,这些页面可以放回到URL表中以再次启动该过程,任何相关数据(元标记等),图像等。

    解析完所有相关数据后,HTML处理器会将所有这些数据发送到ElasticSearch集群。 ElasticSearch提供闪电般快速的全文搜索,通过将数据分成不同的密钥可以更快地进行搜索:

    { 
       "url" : "http://example.com",
       "meta" : {
           "title" : "The meta title from the page",
           "description" : "The meta description from the page",
           "keywords" : "the,keywords,for,this,page"
       },
       "body" : "The body content in it's entirety",
       "images" : [
           "image1.png",
           "image2.png"
       ]
    }
    

    现在,您的网站/服务可以实时访问最新数据。解析器需要足够详细以处理任何错误,因此如果它不能将数据拉出来,它可以将处理标志设置为false,或者至少将其记录在某处以便可以对其进行检查。

      

    有什么好处?

    这种方法的优点在于,如果您想要更改数据,处理数据或存储数据的方式,您可以随时更改该部分,而无需重新构建整个应用程序。此外,如果刮刀/应用程序的一部分打破其余部分可以继续运行而不会丢失任何数据并且不会停止其他进程

      

    有哪些缺点?

    这是一个复杂的大系统。任何时候你有一个庞大的复杂系统,你要求大的复杂错误。不幸的是,网络抓取和数据处理是一项复杂的工作,根据我的经验,没有办法解决这个特别复杂的问题。

答案 1 :(得分:3)

抓取和索引操作可能需要一段时间,但您不会每2分钟抓取同一个网站,因此您可以考虑一种算法,您可以在其中花费更多精力来抓取和索引数据,另一个算法可以帮助您更快地搜索。

您可以随时抓取数据并在后台更新其余表格(每X分钟/小时),这样您的搜索结果就会一直保持新鲜,但您不必等待为了爬行结束。

<强>爬行

只需获取所有可用的数据(可能是所有HTML代码)并将其存储在一个简单的表中。您需要此数据进行索引分析。这张表可能很大,但是在使用它时你不需要良好的性能,因为它将成为后台使用的一部分而且它不会暴露给用户使用搜索。

ALL_DATA
____________________________________________
| Url | Title | Description | HTML_Content |
‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾

表格和索引

创建一个包含网址和关键字的大表

KEYWORDS
_________________
| URL | Keyword |
‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾

此表格将包含每个网址内容中的大部分字词(我会删除&#34;&#34;,&#34; on&#34;,&#34;&#34;,&# 34; a&#34;等...

创建一个包含关键字的表格。对于每次出现,将1添加到出现列

KEYWORDS
_______________________________
| URL | Keyword | Occurrences |
‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾

使用&#34; hot&#34;创建另一个表关键字会小很多

HOT_KEYWORDS
_________________
| URL | Keyword | 
‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾

此表格内容将根据搜索查询稍后加载。 最常见的搜索词将存储在HOT_KEYWORDS表中。

另一个表将保存缓存的搜索结果

CACHED_RESULTS
_________________
| Keyword | Url |
‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾

搜索算法

首先,您将搜索缓存的结果表。如果您有足够的结果,请选择它们。如果您没有,请搜索较大的KEYWORDS表。您的数据不是那么大,因此根据关键字索引进行搜索不会花费太长时间。如果您发现更多相关结果,请将它们添加到缓存中以供日后使用。

注意:您必须选择一种算法才能使CACHED_RESULTS表保持较小(可能是为了保存记录的最后一次使用,如果缓存已满,则删除最旧的记录)。

这样,缓存表将帮助您减少关键字表的负担,并为常见搜索提供超快的结果。

答案 2 :(得分:3)

  • 只需查看Solrsolr-wiki即可。它是lucene项目的开源搜索平台(类似于Elasticsearch)。
  • 对于网络抓取工具,您可以使用ApertureNutch。两者都是用java编写的。光圈是一种轻型履带。但是使用Nutch,我们可以抓取1000个更多网站。
  • Nutch将处理抓取网站的过程。此外,Nutch提供Solr支持。这意味着您可以将从Nutch抓取的数据直接索引到Solr
  • 使用Solr Cloud我们可以设置多个具有分片和复制的群集,以防止数据丢失和快速数据检索。

实现自己的网络爬虫不是那么容易,对于搜索,常规RDBMS在运行时检索数据要复杂得多。

答案 3 :(得分:2)

我有抓取网站的经验,这是一个非常复杂的话题。 每当我遇到这方面的问题时,我都会看看这方面的最佳人选(烨,谷歌)。 他们有很多关于他们正在做什么的很好的演示,他们甚至发布了一些(他们的)工具。 例如,在网站上搜索特定数据时,phpQuery是一个很好的工具,如果您还不知道,我建议您查看它。

我在一个类似的项目中完成的一个小技巧就是有两个数据表。 数据必须尽可能最新,因此爬虫程序大部分时间都在运行,并且锁定表存在问题。因此,每当爬虫写入一个表时,另一个表对搜索引擎是免费的,反之亦然。

答案 4 :(得分:1)

我已经构建了一个用于检测新闻网站的Web爬虫 - 并且它的表现非常好。 它基本上下载整个页面,然后保存它准备用于寻找关键字的另一个抓取。然后,它基本上尝试使用关键字确定网站是否相关。死简单。

您可以在此处找到它的源代码。请帮助贡献:-) 它是一个专注的爬虫,除了寻找网站并根据关键字的存在对它们进行排名之外,它实际上并没有做任何其他事情。它不适用于大量数据负载,但它非常适合查找相关站点。

https://github.com/herreovertidogrom/crawler.git

记录得有点糟糕 - 但我会解决这个问题。

如果您想搜索已爬网数据,并且您拥有大量数据,并且希望构建面向未来的服务,则不应创建包含N列的表,每个搜索项对应一列。如果您认为URL是主键,这是一种常见的设计。相反,你应该避免像害虫一样的宽桌设计。这是因为IO磁盘读取在宽表设计上变得极其缓慢。您应该将所有数据存储在一个表中,指定键和值,然后在变量名上对表进行分区。

避免重复总是很难。根据我的经验,从数据仓库 - 设计主键并让DB完成工作。我尝试使用source + key +值作为主键,避免重复计算,并且几乎没有限制。

我建议您创建一个这样的表:

URL,变量,值和制作主键。

然后将所有数据写入该表,对不同变量进行分区,并仅在此表上实现搜索。 它避免了重复,它快速且易于压缩。

答案 5 :(得分:-1)

你试过http://simplehtmldom.sourceforge.net/manual.htm了吗?我发现它对于删除页面很有用,搜索内容可能会有所帮助。

使用asynchronous approach抓取并存储数据,以便您可以运行多个并行抓取和存储

ElasticSearch将有助于搜索存储的数据。

答案 6 :(得分:-2)

您可以使用以下代码搜索HTML:

<? 
    //Get the HTML
    $page = file_get_html('http://www.google.com')

    //Parse the HTML
    $html = new DOMDocument();
    $html->loadHTML($page);

    //Get the elemnts you are intersted in... 
    $divArr = $html->getElementsByTagName('div');
    foreach($divArr as $div) {
        echo $div->nodeValue;
    }
?>