iT邦幫忙

第 11 屆 iT 邦幫忙鐵人賽

DAY 9
1
Modern Web

寫給PHP開發者的30堂網路爬蟲開發系列 第 9

Day 9:擷取!案例研究 1-2 擷取所有消息為例

前言

前一天提到,每個訊息分類可能載入的方式,因此在本日文章則是要做以下的事情:

  1. 以「最新消息」為例,把所有最新消息都擷取下來
  2. 搭配不同的「Form Data」的欄位值,並丟分頁試試不同的回應結果與內容

擷取步驟

首先,先將「php_crawler」Docker image啟動,啟動的指令如下:

docker run --name=php_crawler -d -it php_crawler bash

接著,建立一個檔案叫做「lab1-2.php」並把下面的程式碼放進去。

<?php

require_once __DIR__ . '/vendor/autoload.php';

use GuzzleHttp\Client;
use Symfony\Component\DomCrawler\Crawler;

$latestNews = 'https://www.nttu.edu.tw/app/index.php?Action=mobileassocgmolist';
$client = new Client();
$formParams =  [
    'form_params' => [
        'Cg' => '1009',
        'IsTop' => '0',
        'Op' => 'getpartlist',
        'Page' => '1',
    ],
];

$response = $client->request('POST', $latestNews, $formParams);

$latestNewsString = (string)$response->getBody();

var_dump($latestNewsString);

接著再用下面指令把「lab1-2.php」傳到運行的Docker container中。

接著再使用下列指令運行「lab1-2.php」。

docker exec -it php_crawler php lab1-2.php 

接著就會得到類似下面回應的內容:

string(2855) "{"content":"\n\n\t<div class=\"row listBS\">\n\t\n\t\n\t\t\n\t\t<div class=\"d-item d-title col-sm-12\">\n<div class=\"mbox\">\n\t<div class=\"d-txt\">\n      <div class=\"mtitle\">\n\t\t\t\n\t\t\t<a href=\"https:\/\/aa.nttu.edu.tw\/p\/404-1002-91667-1.php\">\n\t\t\t\t\u3010\u6559\u52d9\u8655\u3011108\u5e7410\u670805\u65e5\uff08\u516d\uff09\u70ba\u88dc\u4e0a\u8ab2\u65e5\u901a\u77e5(108.09.23\u516c\u544a)\n\t\t\t<\/a>\n\t\t\t\n\t\t\t<span class=\"subsitename newline\"><\/span>\n\t\t<\/div>\n\t<\/div>\n\t\n<\/div>\n<\/div>\n\n\t\t<\/div><div class=\"row listBS\">\n\t\n\t\t\n\t\t<div class=\"d-item d-title col-sm-12\">\n<div class=\"mbox\">\n\t<div class=\"d-txt\">\n      <div class=\"mtitle\">\n\t\t\t\n\t\t\t<a href=\"https:\/\/dga.nttu.edu.tw\/p\/404-1008-91751-1.php\">\n\t\t\t\t\u3010\u7e3d\u52d9\u8655\u51fa\u7d0d\u7d44\u3011\u570b\u7acb\u81fa\u6771\u5927\u5b78108\u5b78\u5e74\u5ea6\u7b2c1\u5b78\u671f\u7e73\u4ea4\u5b78\u5206\u8cbb\u516c\u544a\n\t\t\t<\/a>\n\t\t\t\n\t\t\t<span class=\"subsitename newline\"><\/span>\n\t\t<\/div>\n\t<\/div>\n\t\n<\/div>\n<\/div>\n\n\t\t<\/div><div class=\"row listBS\">\n\t\n\t\t\n\t\t<div class=\"d-item d-title col-sm-12\">\n<div class=\"mbox\">\n\t<div class=\"d-txt\">\n      <div class=\"mtitle\">\n\t\t\t\n\t\t\t<a href=\"https:\/\/wdsa.nttu.edu.tw\/p\/404-1009-51852-1.php\">\n\t\t\t\t\u3010\u5b78\u52d9\u8655\u8ab2\u5916\u7d44\u3011107\u5b78\u5e74\u5ea6\u7b2c2\u5b78\u671f\u5b78\u696d\u7e3e\u512a\u73ed\u7d1a\u524d\u4e09\u540d\u734e\u5b78\u91d1\u7533\u8acb\u516c\u544a\n\t\t\t<\/a>\n\t\t\t\n\t\t\t<span class=\"subsitename newline\"><\/span>\n\t\t<\/div>\n\t<\/div>\n\t\n<\/div>\n<\/div>\n\n\t\t<\/div><div class=\"row listBS\">\n\t\n\t\t\n\t\t<div class=\"d-item d-title col-sm-12\">\n<div class=\"mbox\">\n\t<div class=\"d-txt\">\n      <div class=\"mtitle\">\n\t\t\t\n\t\t\t<a href=\"https:\/\/rd.nttu.edu.tw\/p\/404-1007-91275-1.php\">\n\t\t\t\t\u3010\u7814\u767c\u8655\u3011Language Corner \u8a9e\u8a00\u4ea4\u6d41\u5925\u4f34\u6d3b\u52d5~\u958b\u59cb\u63a5\u53d7\u9810\u7d04\uff0c\u4ea6\u6b61\u8fce\u73fe\u5834\u5831\u540d\u5537^^\n\t\t\t<\/a>\n\t\t\t\n\t\t\t<span class=\"subsitename newline\"><\/span>\n\t\t<\/div>\n\t<\/div>\n\t\n<\/div>\n<\/div>\n\n\t\t<\/div><div class=\"row listBS\">\n\t\n\t\t\n\t\t<div class=\"d-item d-title col-sm-12\">\n<div class=\"mbox\">\n\t<div class=\"d-txt\">\n      <div class=\"mtitle\">\n\t\t\t\n\t\t\t<a href=\"https:\/\/rd.nttu.edu.tw\/p\/404-1007-91187-1.php\">\n\t\t\t\t\u3010\u7814\u767c\u8655\u3011109\u5b78\u5e74\u50d1\u751f\u53ca\u6e2f\u6fb3\u751f\u55ae\u7368\u62db\u751f\u7c21\u7ae0\u53ca\u7533\u8acb\u6642\u9593\u516c\u544a(2020\u5e749\u6708\u5165\u5b78\uff0c\u9650\u5b78\u58eb\u73ed)\n\t\t\t<\/a>\n\t\t\t\n\t\t\t<span class=\"subsitename newline\"><\/span>\n\t\t<\/div>\n\t<\/div>\n\t\n<\/div>\n<\/div>\n\n\t\t\n\t\n\t<\/div>\n\n\n\n","stat":null}"

從回應的內容來看,看起來像是回應JSON內容。所以在拿到回應的內容之後,需要利用json_decode函式解碼JSON內容。因此把上述的程式碼改成這樣即可解出訊息內容了。

$latestNews = 'https://www.nttu.edu.tw/app/index.php?Action=mobileassocgmolist';
$client = new Client();
$formParams =  [
    'form_params' => [
        'Cg' => '1009',
        'IsTop' => '0',
        'Op' => 'getpartlist',
        'Page' => '1',
    ],
];

$response = $client->request('POST', $latestNews, $formParams);

$latestNewsString = (string)$response->getBody();
$latestNewsString = json_decode($latestNewsString, true);

var_dump($latestNewsString);

接著再重複上述的動作,把程式丟進運行container並再執行一次,則會得到解析過後的中文訊息Associative Array(關聯陣列)內容了:

array(2) {
  ["content"]=>
  string(2021) "

	<div class="row listBS">
	
	
		
		<div class="d-item d-title col-sm-12">
<div class="mbox">
	<div class="d-txt">
      <div class="mtitle">
			
			<a href="https://aa.nttu.edu.tw/p/404-1002-91667-1.php">
				【教務處】108年10月05日(六)為補上課日通知(108.09.23公告)
			</a>
			
			<span class="subsitename newline"></span>
		</div>
	</div>
	
</div>
</div>

		</div><div class="row listBS">
	
		
		<div class="d-item d-title col-sm-12">
<div class="mbox">
	<div class="d-txt">
      <div class="mtitle">
			
			<a href="https://dga.nttu.edu.tw/p/404-1008-91751-1.php">
				【總務處出納組】國立臺東大學108學年度第1學期繳交學分費公告
			</a>
			
			<span class="subsitename newline"></span>
		</div>
	</div>
	
</div>
</div>

		</div><div class="row listBS">
	
		
		<div class="d-item d-title col-sm-12">
<div class="mbox">
	<div class="d-txt">
      <div class="mtitle">
			
			<a href="https://wdsa.nttu.edu.tw/p/404-1009-51852-1.php">
				【學務處課外組】107學年度第2學期學業績優班級前三名獎學金申請公告
			</a>
			
			<span class="subsitename newline"></span>
		</div>
	</div>
	
</div>
</div>

		</div><div class="row listBS">
	
		
		<div class="d-item d-title col-sm-12">
<div class="mbox">
	<div class="d-txt">
      <div class="mtitle">
			
			<a href="https://rd.nttu.edu.tw/p/404-1007-91275-1.php">
				【研發處】Language Corner 語言交流夥伴活動~開始接受預約,亦歡迎現場報名唷^^
			</a>
			
			<span class="subsitename newline"></span>
		</div>
	</div>
	
</div>
</div>

		</div><div class="row listBS">
	
		
		<div class="d-item d-title col-sm-12">
<div class="mbox">
	<div class="d-txt">
      <div class="mtitle">
			
			<a href="https://rd.nttu.edu.tw/p/404-1007-91187-1.php">
				【研發處】109學年僑生及港澳生單獨招生簡章及申請時間公告(2020年9月入學,限學士班)
			</a>
			
			<span class="subsitename newline"></span>
		</div>
	</div>
	
</div>
</div>

		
	
	</div>



"
  ["stat"]=>
  NULL
}

接著去看有沒有第2頁,把上面的lab1-2.php程式中的$formParams裡面的參數稍微改成如下:

$formParams =  [
    'form_params' => [
        'Cg' => '1009',
        'IsTop' => '0',
        'Op' => 'getpartlist',
        'Page' => '2',
    ],
];

接著再重複上面的動作,把改好的lab1-2.php丟到現在正運行的Docker container中。

接著會得到下面的內容:

array(2) {
  ["content"]=>
  string(1991) "

	<div class="row listBS">
	
	
		
		<div class="d-item d-title col-sm-12">
<div class="mbox">
	<div class="d-txt">
      <div class="mtitle">
			
			<a href="https://rd.nttu.edu.tw/p/404-1007-91140-1.php">
				【研發處】外國學生申請入學(2020年春季班)現正報名中 International Student Admissions(Spring Semester 2020)
			</a>
			
			<span class="subsitename newline"></span>
		</div>
	</div>
	
</div>
</div>

		</div><div class="row listBS">
	
		
		<div class="d-item d-title col-sm-12">
<div class="mbox">
	<div class="d-txt">
      <div class="mtitle">
			
			<a href="https://dga.nttu.edu.tw/p/404-1008-91078-1.php">
				【總務處出納組】108學年度第一學期(進修學士班新生)繳交學雜費公告
			</a>
			
			<span class="subsitename newline"></span>
		</div>
	</div>
	
</div>
</div>

		</div><div class="row listBS">
	
		
		<div class="d-item d-title col-sm-12">
<div class="mbox">
	<div class="d-txt">
      <div class="mtitle">
			
			<a href="https://aa.nttu.edu.tw/p/404-1002-90908-1.php">
				【教務處】大一優秀新生獎學金、設籍臺東獎學金(含轉學新生)申請公告
			</a>
			
			<span class="subsitename newline"></span>
		</div>
	</div>
	
</div>
</div>

		</div><div class="row listBS">
	
		
		<div class="d-item d-title col-sm-12">
<div class="mbox">
	<div class="d-txt">
      <div class="mtitle">
			
			<a href="https://aa.nttu.edu.tw/p/404-1002-90907-1.php">
				【教務處】大一新生「運動、美術、音樂」績優獎學金申請公告
			</a>
			
			<span class="subsitename newline"></span>
		</div>
	</div>
	
</div>
</div>

		</div><div class="row listBS">
	
		
		<div class="d-item d-title col-sm-12">
<div class="mbox">
	<div class="d-txt">
      <div class="mtitle">
			
			<a href="https://enews.nttu.edu.tw/p/404-1045-90881-1.php">
				【秘書室】東大簡訊-13號刊(20190903)
			</a>
			
			<span class="subsitename newline"></span>
		</div>
	</div>
	
</div>
</div>

		
	
	</div>



"
  ["stat"]=>
  NULL
}

從本來頁面的完整訊息列表還是有些差距,因此研判還有第3頁,接著再次重複上述動作,只是把Page改成3

$formParams =  [
    'form_params' => [
        'Cg' => '1009',
        'IsTop' => '0',
        'Op' => 'getpartlist',
        'Page' => '3',
    ],
];

接著拿到下面的內容:

array(2) {
  ["content"]=>
  string(759) "

	<div class="row listBS">
	
	
		
		<div class="d-item d-title col-sm-12">
<div class="mbox">
	<div class="d-txt">
      <div class="mtitle">
			
			<a href="https://enews.nttu.edu.tw/p/404-1045-90876-1.php">
				【秘書室】恭賀!音樂學系何育真老師榮升副教授
			</a>
			
			<span class="subsitename newline"></span>
		</div>
	</div>
	
</div>
</div>

		</div><div class="row listBS">
	
		
		<div class="d-item d-title col-sm-12">
<div class="mbox">
	<div class="d-txt">
      <div class="mtitle">
			
			<a href="https://aa.nttu.edu.tw/p/404-1002-90906-1.php">
				【教務處】核發108-1舊生續領設籍臺東獎學金公告
			</a>
			
			<span class="subsitename newline"></span>
		</div>
	</div>
	
</div>
</div>

		
	
	</div>



"
  ["stat"]=>
  string(4) "over"
}

總結

注意到了嘛?stat有寫分頁的狀態,如果還有下一個分頁內容,statNULL,若已經是最後一個頁面了,則是over

所以這邊可以總結一個很簡單的方法去把所有的訊息解析出來:

  • 使用while迴圈,直到statover停止迴圈。
  • 中間就是解析指定的訊息種類中的分頁所有的訊息內容。

本日已經完成前天所提到方法,並完成實做。接下來就是解析訊息內容了,敬請期待!


上一篇
Day 8:案例研究 1-2 擷取所有消息為例之分析方法
下一篇
Day 10:案例研究 1-2 解析所有消息為例
系列文
寫給PHP開發者的30堂網路爬蟲開發30

尚未有邦友留言

立即登入留言