计算将已爬网的网站从一个URL导航到另一个URL所需的步骤数

时间:2014-01-24 10:59:38

标签: mysql data-structures bigdata

情况: 完全爬网单个域(最多10.000.000个URL),并将所有URL保存到MySql数据库表中。每个URL都有一个唯一的ID。 URL之间的所有链接都保存在另一个表中。例如,带有ID 1的网址链接到包含ID 893的网址。一个URL可以链接到其他URL,反向链接和循环(URL 1链接到URL 6URL 6链接到URL 3URL 3链接回{{ 1}})。由于爬行性质,每个URL都必须有一个到根URL的路径。

我的目标是计算从根级别到达给定URL所需的步骤数量。最后,我想向用户提供URL 1离根级别12个链接(找到最短路径)的信息。

这个问题可能已经解决了,之后是一篇论文,甚至是一个如何解决这个问题但没有强制解决这个问题的例子?

1 个答案:

答案 0 :(得分:2)

算法:

Set root url distance to zero and others to null
Begin Loop  
Find urls matching the current distance  
Find their linked urls and if they are null set their distance to current + 1  
Increment current distance  
Loop if there are urls with distance not set yet

已使用您的数据(942个网址,27008个链接)对其进行了测试,并获得了以下结果:

起始页面的最短点击次数:

Distance    Count
   0           1
   1         149
   2         600
   3         141
   4          38
   5           7
   6           6

从/返回到开始页面的最短点击(取消注释3行UNION和SELECT):

Distance    Count
   0           1
   1         494
   2         447

我已经把它放在sql上,并提供了少量我自己的测试数据(不得不使用SQL Server,因为它只允许选择MySQL查询)。

http://sqlfiddle.com/#!6/efdd1/4

UPDATE crawl_urls SET Distance = NULL           -- Reset distances for the test
UPDATE crawl_urls SET Distance = 0              -- Start Root Url at 0 distance
WHERE ID = (SELECT MIN(ID) FROM crawl_urls)

DECLARE @UrlsToDo int = -1                      -- Count of Urls still to process
DECLARE @Distance int = 0                       -- Current Distance from root

WHILE (@UrlsToDo != 0)                          -- Loop while urls to process
BEGIN

 UPDATE crawl_urls                              -- Find urls at current distance
 SET Distance = @Distance + 1                   -- Set their linked urls distance
 WHERE Distance IS NULL AND ID IN (
   SELECT target_urls_id IDs FROM Links L1
   INNER JOIN crawl_urls A ON L1.crawl_urls_id = A.ID AND A.Distance = @Distance
 --UNION ALL                                    -- Union of both sides of link
 --  SELECT crawl_urls_id IDs FROM Links L2     -- Uncomment for shortest way BACK
 --  INNER JOIN crawl_urls B ON L2.target_urls_id = B.ID AND B.Distance = @Distance
 )

 SET @UrlsToDo = (SELECT COUNT(ID) FROM crawl_urls WHERE Distance IS NULL)
 SET @Distance = @Distance + 1

END                                             -- Increment Distance and loop

SELECT * FROM crawl_urls ORDER BY Distance      -- Output results

注意事项:您需要确保根网址距离为0。还要注意,如果有一个没有链接到别人的孤儿网址,循环可以无限期地进行,尽管理论上这不可能,除非在抓取和记录被跳过时出现错误。正确的索引将对更大的数据集产生巨大的影响。

我将尽快做一些与此类似的事情,这里有一些我注意到的事情。在Links表中有5%的重复项,只允许使用uniques可以大大加快速度 - 减少记录和更好的索引。此外,主页已添加两次(有和没有'/'结尾),因此在两个方向上会有很多额外的重复链接,这也可能适用于搜索友好的网址和文件夹名称。