神魂顛倒論壇

 取回密碼
 加入會員
搜尋
檢視: 3169|回覆: 3
收起左側

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

[複製連結]
發表於 2022-3-7 12:21:01 | 顯示全部樓層 |閱讀模式
PHP, Python, Node.js 哪個比較適合寫爬蟲?

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

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

PHPSS.png

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


對頁面的解析能力

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

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


[PHP] 純文本查看 複制代碼
<?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] 純文本查看 複制代碼
<?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] 純文本查看 複制代碼
<?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] 純文本查看 複制代碼
<?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] 純文本查看 複制代碼
<?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] 純文本查看 複制代碼
<?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] 純文本查看 複制代碼
<?php

...

$timeout = 10000; // 10 秒

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

...


 樓主| 發表於 2022-3-7 12:30:59 | 顯示全部樓層
定義延遲渲染

有時候我們希望等到頁面載入完才進行其他操作,此時只要簡單地設定一個延遲時間即可.
[PHP] 純文本查看 複制代碼
<?php

    ...

    $delay = 5; // 5 seconds

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

    ...


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

[PHP] 純文本查看 複制代碼
<?php

   ...

   use JonnyW\PhantomJs\Client;

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

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

   ...


並且提供了一個簡單地設定方法,支援phantomjs所有的配置項:
[PHP] 純文本查看 複制代碼
$client = Client::getInstance();
$client->getEngine()->addOption('--config=/path/to/config.json');


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

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



您需要登入後才可以回帖 登入 | 加入會員

本版積分規則

Archiver|手機版|小黑屋|Flash2u論壇

GMT+8, 2022-5-23 19:21 , Processed in 0.293243 second(s), 25 queries .

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

快速回覆 回到頂端 返回清單