宅宅很神 發表於 2022-3-7 12:21:01

PHP, Python, Node.js 哪個比較適合寫爬蟲?

PHP, Python, Node.js 哪個比較適合寫爬蟲?

就PHP而言,經驗之一是如下所述

這不是一個小眾的場景,所以無論是哪個語言,都有很多相應的生態庫。這裡介紹一下PHP的方案以及程式碼量:對頁面的解析能力PHP的官方擴充套件中有Dom擴充套件,但是我建議使用electrolinux/phpquery這個庫,他相當於一個PHP版的JQ。算上載入檔案,只要三行就能獲取title標籤內容。



作者:PHP武器庫
鏈接:https://www.zhihu.com/question/23643061/answer/2375718466
來源:知乎
著作權歸作者所有。商業轉載請聯繫作者獲得授權,非商業轉載請註明出處。


對頁面的解析能力

PHP的官方擴充套件中有Dom擴充套件,但是我建議使用electrolinux/phpquery這個庫,他相當於一個PHP版的JQ。

算上載入檔案,只要三行就能獲取title標籤內容。


<?php
include 'phpQuery-onefile.php';

$file = 'test.html'; // 需要載入的HTML

// 載入檔案
phpQuery::newDocumentFileHTML($file);

// 載入完成後,只要像JQ那樣操作即可
$titleElement = pq('title');

// 也可以使用對象的寫法
$title = $titleElement->html();



對資料庫的操作能力

PHP對資料庫的能力無庸置疑,原生擴充套件中支援PDO,這裡可以嘗試ThinkPHP的think-orm。

簡簡單單一學就會。


<?php
use think\facade\Db;
// 數據庫配置資訊設定(全域性有效)
Db::setConfig([
    // 預設數據連線標識
    'default'   => 'mysql',
    // 數據庫連線資訊
    'connections' => [
      'mysql' => [
            // 數據庫型別
            'type'   => 'mysql',
            // 主機地址
            'hostname' => '127.0.0.1',
            // 使用者名稱
            'username' => 'root',
            // 數據庫名
            'database' => 'demo',
            // 數據庫編碼預設採用utf8
            'charset'=> 'utf8',
            // 數據庫表字首
            'prefix'   => 'think_',
            // 數據庫除錯模式
            'debug'    => true,
      ],
    ],
]);

// 查詢
Db::name('user')->where('id', 1)->find();
// 新增
$data = ['foo' => 'bar', 'bar' => 'foo'];
Db::name('user')->insert($data);
//更新
Db::name('user')
    ->update(['id' => 1, 'name' => 'thinkphp']);
// 刪除
Db::table('think_user')->where('id', 1)->delete();


宅宅很神 發表於 2022-3-7 12:22:50

爬蟲效率

PHP對於效能的優化有很多很深的解決方案,包括使用協程等,這裡只介紹最簡單的的一種方式,使用guzzle這個庫(他使用curl 的並行載入特性).
<?php
use GuzzleHttp\Client;
use GuzzleHttp\Promise;

$client = new Client(['base_uri' => 'http://httpbin.org/']);

// 發起不阻塞的請求
$promises = [
    'image' => $client->getAsync('/image'),
    'png'   => $client->getAsync('/image/png'),
    'jpeg'=> $client->getAsync('/image/jpeg'),
    'webp'=> $client->getAsync('/image/webp')
];

// 等待所有請求完成
$responses = Promise\Utils::settle($promises)->wait();



程式碼量

如上面例子所示,程式碼量並不多,去掉配置檔案,只有十幾行程式碼,最關鍵的是我們需要的特性並沒有削弱.
比如:


[*]極簡的DOM解析
[*]健壯的SQL操作
[*]發起並行請求


解析JS

有時候我們要抓取的頁面是依賴JS執行的,這是需要一個無頭瀏覽器,此時介紹這樣一個庫,他能夠很簡單的完成對phantomjs的操作.

PHP PhantomJS 是一個靈活的 PHP 庫,讓PHP通過很簡單的程式碼來操作 PhantomJS 無頭瀏覽器載入頁面。 讓PHP載入的網頁地址執行JS/頁面截圖/導出PDF.

他可以非常方便的實現這些功能:

[*]使用無頭瀏覽器PhantomJS載入請求
[*]檢視詳細的響應數據,包括頁面內容、標題、狀態 程式碼等
[*]處理重定向
[*]檢視JS控制檯輸出報錯

[*]檢視詳細的PhantomJS除錯資訊
[*]儲存頁面的截圖

[*]將頁面導出為PDF
[*]設定瀏覽視窗大小
[*]為PDF導出設定頁首頁尾
[*]指定截圖位置x,y和寬高
[*]延遲頁面渲染(等待頁面載入完成)
[*]輕鬆構建和執行PhantomJS指令碼


PHP PhantomJS 只要求 PHP 5.4.0 或以上即可。



宅宅很神 發表於 2022-3-7 12:27:16

PhantomJS 基本用法
使用phantomjs發起一個請求非常簡單:



<?php

use JonnyW\PhantomJs\Client;

$client = Client::getInstance();

/**
   * @see JonnyW\PhantomJs\Http\Request
   **/
$request = $client->getMessageFactory()->createRequest('http://phpreturn.com', 'GET');

/**
   * @see JonnyW\PhantomJs\Http\Response
   **/
$response = $client->getMessageFactory()->createResponse();

// Send the request
$client->send($request, $response);

if($response->getStatus() === 200) {

      // Dump the requested page content
      echo $response->getContent();
}

將頁面截圖並儲存:

<?php

   use JonnyW\PhantomJs\Client;

   $client = Client::getInstance();

   $width= 800;
   $height = 600;
   $top    = 0;
   $left   = 0;

   /**
    * @see JonnyW\PhantomJs\Http\CaptureRequest
    **/
   $request = $client->getMessageFactory()->createCaptureRequest('http://phpreturn.com', 'GET');
   $request->setOutputFile('/path/to/save/capture/file.jpg');
   $request->setViewportSize($width, $height);
   $request->setCaptureDimensions($width, $height, $top, $left);

   /**
    * @see JonnyW\PhantomJs\Http\Response
    **/
   $response = $client->getMessageFactory()->createResponse();

   // Send the request
   $client->send($request, $response);

將頁面導出為PDF:

<?php

use JonnyW\PhantomJs\Client;

$client = Client::getInstance();

/**
   * @see JonnyW\PhantomJs\Http\PdfRequest
   **/
$request = $client->getMessageFactory()->createPdfRequest('http://phpreturn.com', 'GET');
$request->setOutputFile('/path/to/save/pdf/document.pdf');
$request->setFormat('A4');
$request->setOrientation('landscape');
$request->setMargin('1cm');

/**
   * @see JonnyW\PhantomJs\Http\Response
   **/
$response = $client->getMessageFactory()->createResponse();

// Send the request
$client->send($request, $response);

自定義一個超時時間:

預設情況下每個請求超時時間為5秒,我們可以自定義一個超時時間.


<?php

...

$timeout = 10000; // 10 秒

$request = $client->getMessageFactory()->createRequest('http://phpreturn.com');
$request->setTimeout($timeout);

...

宅宅很神 發表於 2022-3-7 12:30:59

定義延遲渲染

有時候我們希望等到頁面載入完才進行其他操作,此時只要簡單地設定一個延遲時間即可.
<?php

    ...

    $delay = 5; // 5 seconds

    $request = $client->getMessageFactory()->createCaptureRequest('http://phpreturn.com');
    $request->setDelay($delay);

    ...

設定等待所有請求載入完成才進行操作:


<?php

   ...

   use JonnyW\PhantomJs\Client;

   $client = Client::getInstance();
   $client->isLazy(); // 設定所有請求完成才渲染頁面

   $request= $client->getMessageFactory()->createRequest();
   $request->setTimeout(5000); // 設定一個超時時間

   ...

並且提供了一個簡單地設定方法,支援phantomjs所有的配置項:
$client = Client::getInstance();
$client->getEngine()->addOption('--config=/path/to/config.json');

其實主要看你對那個語言使用的更趁手,如果你不瞭解相應的生態,那麼無論選擇什麼樣的語言,都只能事倍功半.

作者:PHP武器庫
鏈接:https://www.zhihu.com/question/23643061/answer/2375718466
來源:知乎
著作權歸作者所有。商業轉載請聯繫作者獲得授權,非商業轉載請註明出處。



頁: [1]
檢視完整版本: PHP, Python, Node.js 哪個比較適合寫爬蟲?