0

スクレイピングされたコンテンツをMYSQLデータベースに保存するのに少し問題があります。

そこで、このサイト [http://www.ucc.ie/modules/descriptions/page014.html][1] のモジュール コードとモジュール タイトルを MYSQL データベースに保存しようとしています。サイトからコンテンツを取得できますが、スクレイピングされたコンテンツをデータベースに保存できないようです。クエリがそうでないときに、「クエリが空でした」というエラーが表示され続けます。

これを行うのに時間を費やしていて、それを回避できないようです。この問題を解決するための助けをいただければ幸いです。

<?php

//Here is a simple web scraping example using the PHP DOM that tries to get the largest      text body of a HTML document. I needed it for a spider 
//that had to show a short description for a page. It assumes that document annotation can be the largest <div>, <td> or <p> element in the //page.
//In the example I show a way to prevent a bug in the DOM as it sometimes just doesn't recognize html encoding. It seems to work if you put 
//charset meta tag right after the head tag of the document.

$host="localhost";
$user="root";
$password="";
mysql_connect($host,$user,$password) or die("could not connect to the host");
mysql_select_db("plot_a_coursedb");


$ch= curl_init();
curl_setopt ($ch, CURLOPT_URL, 'http://www.ucc.ie/modules/descriptions/page014.html' );
curl_setopt($ch, CURLOPT_HEADER, 0);
curl_setopt($ch,CURLOPT_VERBOSE,1);
curl_setopt($ch, CURLOPT_USERAGENT, 'Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.1.13) Gecko/20080311 Firefox/2.0.0.13');
curl_setopt ($ch, CURLOPT_REFERER, 'http://localhost:8080/extractsite/index2.html');     //just a fake referer
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch,CURLOPT_POST,0);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 20);

$html= curl_exec($ch);
$html1= curl_getinfo($ch);

//try to get page encoding as it was sent from server
if ($html1['content_type']){
$arr= explode('charset=',$html1['content_type']);
$csethdr= strtolower(trim($arr[1]));
} else {
$csethdr= false;
}

$cset= false;
$arr= array();

//This has to replace page meta tags for charset with utf-8, but it doesn't actually help(see the bug info).
if (preg_match_all('/(<meta\s*http-equiv="Content-Type"\s*content="[^;]*;
\s*charset=([^"]*?)(?:"|\;)[^>]*>)/' //merge this line
,$html,$arr,PREG_PATTERN_ORDER)){
$cset= strtolower(trim($arr[2][0]));
if ($cset!='utf-8'||$cset!=$csethdr){
    $new= str_replace($arr[2][0],'utf-8',$arr[1][0]);
    $html= str_replace($arr[1][0],$new,$html);
    $cset= $csethdr;
} else {
    $cset= false;
}

if ($cset=='utf-8'){
    $cset= false;
}
}
unset($arr);
if ($cset){
$html= iconv($cset,'utf-8',$html);
}
unset($cset);

//solve dom bug
$html=preg_replace('/<head[^>]*>/','<head><META HTTP-EQUIV="Content-Type"   CONTENT="text/html; charset=utf-8">',$html);

@$dom= new DOMDocument();
@$dom->loadHTML($html);
@$dom->preserveWhiteSpace = false;

function getMaxTextBody($dom){
$content = $dom->getElementsByTagname('div');
$content2= $dom->getElementsByTagname('td');
$content3= $dom->getElementsByTagname('p');
$content4 = $dom->getElementsByTagname('B');

$new = array();
foreach ($content as $value) {
    $new[]= $value;
    unset($value);
}
unset($content);

foreach ($content2 as $value) {
    $new[]= $value;
    unset($value);
}
unset($content2);

foreach ($content3 as $value) {
    $new[]= $value;
    unset($value);
}
unset($content3);

foreach ($content4 as $value) {
    $new[]= $value;
    unset($value);
}
unset($content4);

$maxlen= 0;
$result= '';
foreach ($new as $item)
{
    $str= $item->nodeValue;
    if (strlen($str)>$maxlen){
        $content1= $item->getElementsByTagName('div');
        $content2= $item->getElementsByTagname('td');
        $content3= $item->getElementsByTagname('p');
        $content4 = $dom->getElementsByTagname('b');
        
        $contentnew= array();
        foreach ($content1 as $value) {
            $contentnew[]= $value;
            unset($value);
        }
        unset($content1);
        
        foreach ($content2 as $value) {
            $contentnew[]= $value;
            unset($value);
        }
        unset($content2);
        
        foreach ($content3 as $value) {
            $contentnew[]= $value;
            unset($value);
        }
        unset($content3);
        
        foreach ($content4 as $value) {
            $contentnew[]= $value;
            unset($value);
        }
        unset($content4);



        // Insert data into database query
        $query = mysql_query("INSERT INTO data (div,td,p,b) VALUES ('$content1','$content2','$content3','$content4')"); 
        mysql_query($query) or die (mysql_error());

        // Close the database connection
        mysql_close();


        if (count($contentnew)==0){
            $result= $str;
        } else {
            foreach ($contentnew as $value) {
                $str1= getMaxTextBody($value);
                $str2= $value->nodeValue;
                    //let's say largest body has more than 50% of the text in its parent
                                if (strlen($str1)*2<strlen($str2)){
                    $str1= $str2;
                }
                if (strlen($str1)*2>strlen($str)&&strlen($str1)>$maxlen){
                    $result= $str1;
                } elseif (strlen($str1)>$maxlen){
                    $result= $str1;
                }
                $maxlen= strlen($result);
            }
        }
        $maxlen= strlen($result);
        unset($contnentnew);
    }
}

unset($new);
return $result;

}
print getMaxTextBody($dom);


?>

以下は、コンテンツを保存するために作成したMYSQLテーブルです

DROP TABLE IF EXISTS `data`;
CREATE TABLE `data` (
`div`  varchar(20) CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL ,
`td`  varchar(20) CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL ,
`p`  varchar(20) CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL ,
`b`  varchar(20) CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL ,
PRIMARY KEY (`div`)
)
ENGINE=InnoDB
DEFAULT CHARACTER SET=utf8 COLLATE=utf8_unicode_ci;
}

私のコンテンツがデータベースに保存されない理由を理解するための助けをいただければ幸いです。

4

4 に答える 4

2

コンテンツ変数は、SQLクエリを作成した時点では実際に空です-上記では設定されていません。

$query = mysql_query("INSERT INTO data (div,td,p,b) VALUES \
('$content1','$content2','$content3','$content4')"); 

おそらく、各 $content の $value の nodeValue コンテンツを $value 文字列としてその mysql クエリに配置する必要があると思います ($value->nodeValue を使用してノードのテキスト コンテンツにアクセスできます)。

たとえば、この例の P ノードなどのノードのテキスト コンテンツが必要な場合は、ノードを print_r すると次のようになります。

DOMElement Object
(
[tagName] => p
[schemaTypeInfo] =>
[nodeName] => p
[nodeValue] => Students should note that all of the modules below may not 
be available to them.
[nodeType] => 1
[parentNode] => (object value omitted)
[childNodes] => (object value omitted)
[firstChild] => (object value omitted)
[lastChild] => (object value omitted)
[previousSibling] => (object value omitted)
[nextSibling] => (object value omitted)
[attributes] => (object value omitted)
[ownerDocument] => (object value omitted)
[namespaceURI] =>
[prefix] =>
[localName] => p
[baseURI] =>
[textContent] => Students should note that all of the modules below may \\
not be available to them.
)

そのノードには、興味深いと思われる 2 つの値 ( textContent と nodeValue )があることがわかります。

これを行うことで、コードからこれらにアクセスできます。

  foreach ($content3 as $value) { // content3 contains the p nodes, I think?
           // let's see what the node looks like
          print_r($value); 
          // let's get hold of the text value from the node
          $mytempvariable=$value->nodeValue;
          print "CONTENT OF P NODE: \n\n$mytempvariable\n\n\n";
  }

これにより、すべての P ノードからテキストが出力されます。

于 2012-06-08T12:54:14.243 に答える
0

に挿入$content1されない理由$content4は、 foreach ループの後にそれらを設定解除するためです。したがって、値は挿入されません。

于 2012-06-08T13:12:51.460 に答える
0

memcache を使用すると、処理が高速になると思います。また、必要なdivのみを取得してmemcacheに保存し、必要に応じて一意のページ名を取得します

于 2012-06-08T12:54:42.307 に答える
0

クエリで変数 $contentX をエスケープしていません。あなたが起動したクエリは、あなたが思っているよりも複雑だと思います。

詳細については、 http://php.net/manual/en/function.mysql-escape-string.phpを確認してください。

より広い意味で、クエリには PDO 拡張機能と準備済みステートメントを使用する必要があります。

于 2012-06-08T12:55:19.390 に答える