【问题标题】:PHP crawling data from websitePHP从网站抓取数据
【发布时间】:2014-06-18 13:15:14
【问题描述】:

我目前正在尝试从一个网站上抓取大量数据,但是我有点挣扎。它有一个 a-z 索引和 1-20 索引,所以它里面有一堆循环和 DOM 的东西。但是,它在第​​一次运行时设法爬取并保存了大约 10.000 行,但现在我在 15.000 左右,每次运行只爬取大约 100 行。

这可能是因为它必须跳过它已经插入的行,(对此进行了检查)。我想不出一种轻松跳过某些页面的方法,因为 1-20 索引变化很大(一个字母有 18 页,其他字母只有 2 页)。

我正在检查是否已经存在具有给定 ID 的记录,如果没有,则插入它。我认为这会很慢,所以现在在脚本启动之前我检索所有行,然后使用 in_array() 检查,假设那更快。但它就是行不通。

所以我的爬虫导航 26 个字母,每个字母 20 页,然后每页最多 50 次,所以如果你计算一下,它会很多。

想逐个字母地运行它,但这不会真正起作用,因为我仍然停留在“a”并且不能只跳到“b”,因为我会错过来自“a”的记录。

希望我已经很好地解释了这个问题,以便有人帮助我。我的代码有点像这样:(我在这里和那里删除了一些东西,猜猜所有重要的东西都在这里给你一个想法)

function in_array_r($needle, $haystack, $strict = false) {
    foreach ($haystack as $item) {
        if (($strict ? $item === $needle : $item == $needle) || (is_array($item) && in_array_r($needle, $item, $strict))) {
            return true;
        }
    }

    return false;
}
/* CONNECT TO DB */
mysql_connect()......



$qry = mysql_query("SELECT uid FROM tableName");
$all = array();
while ($row = mysql_fetch_array($qru)) {
    $all[] = $row;
} // Retrieving all the current database rows to compare later

foreach (range("a", "z") as $key) {
    for ($i = 1; $i < 20; $i++) {
        $dom = new DomDocument();
        $dom->loadHTMLFile("http://www.crawleddomain.com/".$i."/".$key.".htm");
        $finder = new DomXPath($dom);
        $classname="table-striped";
        $nodes = $finder->query("//*[contains(concat(' ', normalize-space(@class), ' '), ' $classname ')]");
        foreach ($nodes as $node) {
            $rows = $finder->query("//a[contains(@href, '/value')]", $node);
            foreach ($rows as $row) {
                $url = $row->getAttribute("href");
                $dom2 = new DomDocument();
                $dom2->loadHTMLFile("http://www.crawleddomain.com".$url);
                $finder2 = new DomXPath($dom2);
                $classname2="table-striped";
                $nodes2 = $finder2->query("//*[contains(concat(' ', normalize-space(@class), ' '), ' $classname2 ')]");
                foreach ($nodes2 as $node2) {

                    $rows2 = $finder2->query("//a[contains(@href, '/loremipsum')]", $node2);
                    foreach ($rows2 as $row2) {

                        $dom3 = new DomDocument();
                        //
                        // not so important variable declarations..
                        //


                        $dom3->loadHTMLFile("http://www.crawleddomain.com".$url);
                        $finder3 = new DomXPath($dom3);
                        //2 $finder3->query() right here


                        $query231 = mysql_query("SELECT id FROM tableName WHERE uid='$uid'");
                        $result = mysql_fetch_assoc($query231);
                        //Doing this to get category ID from another table, to insert with this row..
                        $id = $result['id'];


                        if (!in_array_r($uid, $all)) { // if not exist
                            mysql_query("INSERT INTO')"); // insert the whole bunch
                        }

                    }
                }
            }
        }
    }
}

【问题讨论】:

  • $uid 定义在哪里?
  • uid 上创建一个唯一索引,然后使用 INSERT ON DUPLICATE KEY IGNORE 将您的插入到 db 让 db 完成这项艰巨的工作。
  • 我不能使用它,因为uid可以相同,因为标题可以存在于其他类别中。我无法将它们结合起来,因为它们是完全不同的文章,但名称相同。找到了解决方案,但对我来说不是解决方案,太糟糕了......

标签: php mysql performance web-crawler


【解决方案1】:

$uid 没有定义,同样,这个查询没有意义:

mysql_query("INSERT INTO')");

您应该打开错误报告:

ini_set('display_errors',1); 
error_reporting(E_ALL);

查询后,您应该发送or die(mysql_error());

另外,我也可以说,如果我不说,其他人会说。不要使用mysql_* 函数。它们已被弃用,将从 PHP 的未来版本中删除。试试PDO

【讨论】:

  • 正如我所说,我已经删除了诸如无用变量声明之类的东西并缩短了一些查询。它们都在工作并且完好无损。由于这必须与查询数量和爬网有关,我认为保留所有代码是没有用的。不用担心,路径正在运行并且所有变量都已定义。
  • 好的,但是,INSERT INTO') 仍然不是一个正确的查询。
  • @Adelphia 他删除了一些代码来创建一个小例子。
  • @ArkoElsenaar 如果你想要一个有用的答案,你应该用你最近的代码更新你的问题,你知道吗? ;)
  • @ArkoElsenaar 你可能是对的,但话又说回来:如果没关系,我们为什么要花这些时间来阅读你的问题呢?这种态度对试图帮助你的人是错误的。
猜你喜欢
  • 2013-03-14
  • 1970-01-01
  • 2014-07-06
  • 2018-07-01
  • 1970-01-01
  • 2012-02-28
  • 1970-01-01
相关资源
最近更新 更多