PHP抓取資料的3中形式
什麼叫採集?
就是使用PHP程式,把其他網站中的資訊抓取到我們自己的資料庫中、網站中。
PHP製作採集的技術:
從底層的socket到高層的檔案操作函式,一共有3種方法可以實現採集。
1. 使用socket技術採集:
socket採集是最底層的,它只是建立了一個長連線,然後我們要自己構造http協議字串去傳送請求。
- <?php
- //連線,$error錯誤編號,$errstr錯誤的字串,30s是連線超時時間
- $fp=fsockopen("www.youku.com",80,$errno,$errstr,30);
- if(!$fp) die("連線失敗".$errstr);
- //構造http協議字串,因為socket程式設計是最底層的,它還沒有使用http協議
- $http="GET /?spm=a2hww.20023042.topNav.5~1~3!2~A HTTP/1.1\r\n"; // \r\n表示前面的是一個命令
- $http.="Host:www.youku.com\r\n"; //請求的主機
- $http.="Connection:close\r\n\r\n"; // 連線關閉,最後一行要兩個\r\n
- //傳送這個字串到伺服器
- fwrite($fp,$http,strlen($http));
- //接收伺服器返回的資料
- $data='';
- while (!feof($fp)) {
- $data.=fread($fp,4096); //fread讀取返回的資料,一次讀取4096位元組
- }
- //關閉連線
- fclose($fp);
- var_dump($data);
- ?>
打印出的結果如下,包含了返回的頭資訊及頁面的原始碼:
2. 使用curl_一套函式
curl把HTTP協議都封裝成了很多函式,直接傳相應引數即可,降低了編寫HTTP協議字串的難度。
前提:在php.ini中要開啟curl擴充套件。
- //生成一個curl物件
- $curl=curl_init();
- //設定URL和相應的選項
- curl_setopt($curl, CURLOPT_URL, "http://www.youku.com");
- curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
- //執行curl操作
- $data=curl_exec($curl);
- var_dump($data);
3. 直接使用file_get_contents(最頂層的)
前提:在php.ini中設定允許開啟一個網路的url地址。
- //使用file_get_contents()
- $data=file_get_contents("http://www.youku.com");
- var_dump($data);
3種方式的選擇
網路之間通訊主要使用的是以上三種。其中後兩種用的較多:如果要批量採集大量的資料時使用第二種【CURL】,效能好、穩定。
偶爾發幾個請求發的頻繁不密集時使用第三種。
擴充套件:圖片的防盜鏈如何破?
比如7060網站上的圖片做了防盜鏈:在他的網站中可以看到圖片,把圖片拿到站外就無法訪問。
原理:在HTTP協議中有一個referer項,代表發這個請求的來源地址,伺服器會判斷如果這個請求不是這個網站發來的就會過濾掉這個請求:
解決辦法:發HTTP時自己模擬referer即可:
擴充套件:有些要採集資料時時必須先登入,可以使用模擬的試模擬在登入狀態下的採集:
a. 先用瀏覽登入一下,登入完,瀏覽器的COOKIE中就會有SESSIONID
b. 發PHP發HTTP協議時,把瀏覽器中的SESSIONID放到PHP的HTTP協議請求裡,這樣就在以登入的狀態發請求。
總結:所有客戶端發過來的資料都可以被模擬,所以伺服器上的程式必須要必要的地方過濾客戶端的資料。
什麼時候用以上東西?介面開發時、採集時。
二、資料採集
例如我要採集這個url裡的所有美國電影的資訊,
則先要知道電影所在的節點的結構,我們使用firebug檢視。
然後開始寫程式碼:完整程式碼如下
- /**
- * 發一個GET請求獲取資料
- */
- function get($url)
- {
- global$curl;
- // 配置curl中的http協議->可配置的薦可以查PHP手冊中的curl_
- curl_setopt($curl, CURLOPT_URL, $url);
- curl_setopt($curl, CURLOPT_RETURNTRANSFER, TRUE);
- curl_setopt($curl, CURLOPT_HEADER, FALSE);
- // 執行這個請求
- return curl_exec($curl);
- }
- // 生成一個curl物件
- $curl = curl_init();
- $url='http://list.youku.com/category/show/c_96_a_%E7%BE%8E%E5%9B%BD_s_1_d_1_p_3.html';
- $data=get($url);
- // 匹配電影所在位置
- $list_preg = '/<li class="yk-col4 mr1">.+<\/li>/Us';
- // 匹配img標籤上的src和alt
- $img_preg = '/<img class="quic" _src="(.*)" src="(.*)" alt="(.*)" \/>/U';
- //匹配電影的url
- $video_preg='/<a href="(.*)" title="(.*)" target="(.*)"><\/a>/U';
- //把所有的li存到$list裡,$list是個二維陣列
- preg_match_all($list_preg,$data,$list);
- //var_dump($list);
- foreach ($list[0] as$k => $v) { //這裡$v就是每一個li標籤
- /* 獲取圖片及電影名稱
- preg_match($img_preg,$v,$img); //把匹配到的圖片的資訊存到$img裡
- var_dump($img);
- */
- /*獲取電影地址
- preg_match($video_preg,$v,$video); //把匹配到的電影的資訊存到$video裡
- var_dump($video);
- */
- preg_match($img_preg,$v,$img);
- preg_match($video_preg,$v,$video);
- echo$img[0].'<a href="'.$video[1].'">'.$video[2].'</a>';
- }
測試:
列印$list;
列印$img
列印$video
最終效果:
如果需要把圖片拷貝到硬碟上,則在foreach迴圈里加上以下程式碼:
- $imgData = get($img[1]);
- // 把圖片檔案寫到硬碟上【下載】
- // 因為作業系統是GBK的,所以要把UTF8轉成GBK
- is_dir('./youkuimg/') ? '': mkdir('./youkuimg/');
- file_put_contents('./youkuimg/'.mb_convert_encoding($img[3], 'gbk', 'utf-8').'.jpg', $imgData);
效果如下:在當前目錄下的youkuimg目錄下就會有下載好的圖片。