SOCKET簡單爬蟲實現代碼和使用方法
阿新 • • 發佈:2017-12-25
apple 頭信息 cti 實例 組元 目錄 agent uniq nec
3、執行完成,在文件所在目錄下會有個
抓取一個網頁內容非常容易,常見的方式有curl、file_get_contents、socket以及文件操作函數file、fopen等。
下面使用SOCKET下的fsockopen()函數訪問Web服務器最常用的80端口,通過獲取80端口的數據,並進行分析,來模擬網絡爬蟲的工作方法。
1、實現SOCKET模擬網絡爬蟲主要包括以下幾個部分:
- 使用SOCKET獲取指定頁的內容。
- 使用get_meta_tags()函數分析網頁的META、TITLE等標簽內容。
- 解析TITLE、鏈接或網頁內容,可以使用正則表達式來取得需要的內容。
SOCKET爬蟲實現代碼,完整代碼如下:
簡單爬蟲實現代碼和使用方法
class Spider
{
private $_url = "";//定義用於保存URL的變量
private $_sites = "";//定義用於保存網站相關內容的變量
/**
* 構造函數,用於初始化變量
* @param $url
*/
public function __construct($url)
{
$this->_url = $url;
}
/**
* 開始爬頁面
*/
public function start()
{
$content = $this->socketOpen($this->_url);//使用socketOpen()方法鏈接指定的服務器
$this->_sites["meta"] = $this->getMeta($content);//使用getMeta()方法獲取meta信息
$this->_sites["title"] = $this->getTitle($content);//使用getTitle()方法獲取title信息
$this->_sites[ "detail"] = $this->getDetail($content);//使用getDetail()方法獲取內容信息
$this->_sites["links"] = $this->getLinks($content);//使用getLinks()方法獲取內容鏈接信息
}
/**
* 獲取網頁meta
* @param $content
* @return array
*/
protected function getMeta($content)
{
$file = "metaCache";//向於保存緩存文件的名稱
file_put_contents($file, $content);//將緩存保存到緩存文件中
$meta = get_meta_tags($file);//使用get_meta_tags()取得內容的meta信息
return $meta;//返回meta信息
}
/**
* 獲取body內容
* @param $contents
* @return string
*/
protected function getDetail($contents)
{
preg_match('/<body(.*?)>(.+)<\/body>/s', $contents, $matches);//使用正則表達式處理內容
//var_dump($matches);die;
$body = $this->StripHTML($matches[2]);//去掉特殊HTML字符
$body = strip_tags($body);//清除內容中的特殊標簽
return mb_substr($body, 0, 400);//返回內容的前400個字符
}
/**
* 獲取網頁標題
* @param $contents
* @return mixed
*/
protected function getTitle($contents)
{
preg_match('/<title>(.+)<\/title>/s', $contents, $matches);//使用正則表達式處理內容
return $matches[1];//返回處理結果中的標題部分
}
/**
* 獲取頁面超鏈接
* @param $content
* @return mixed
*/
protected function getLinks($content)
{
$pat = '/<a(.*?)href="(.*?)"(.*?)>(.*?)<\/a>/i';//處理鏈接的正則表達式
preg_match_all($pat, $content, $m);//使用正則表達式處理鏈接
return $m;
}
/**
* 抓取頁面內容
* @param $url
* @return bool|string
*/
protected function socketOpen($url)
{
$fp = fsockopen($url, 80, $errno, $errstr, 30);//使用fsockopen()建立SOCKET鏈接
if($fp === false){
echo "連接遠程服務器失敗:$errstr($errno)<br/>\n";
return false;
}else{
$out = "GET / HTTP/1.1\r\n";//創建要發送的頭文件信息
$out .= "Host: ".$url."\r\n";//指定頭文件信息中的主機內容
$out .= "User-Agent: Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/62.0.3202.94 Safari/537.36\r\n";
$out .= "Connection: keep-alive\r\n\r\n";
fwrite($fp, $out);//使用fwrite()函數發送請求
$contents = "";
while(!feof($fp)){//使用while循環讀取返回的數據
$contents .= fgets($fp, 1024);
}
fclose($fp);//關閉句柄
return $contents;//返回獲取的內容
}
}
/**
* 去掉HTML中不相關的代碼
* @param $string
* @return mixed
*/
protected function StripHTML($string)
{
$pattern=array(
"'<script[^>]*?>.*?</script>'si",
"'<style[^>]*?>.*?</style>'si"
);//建立正則表達式
$replace=array(
"",
""
);//建立替換字符數組
return preg_replace($pattern, $replace, $string);//替換內容中HTML並返回替換後的內容
}
/**
* 打印出抓取到的數據
*/
public function show()
{
echo "<pre>";
print_r($this->_sites);//顯示保存到$_sites公共變量中的內容
echo "</pre>";
}
/**
* 過濾分析數據中的超鏈接
*/
public function filterLinks()
{
$realLinks = "";
$links = $this->_sites["links"][2];//獲取保存鏈接的數組元素
//遍歷數組,清除不規範鏈接
foreach($links as $v){//遍歷鏈接數據
//只保存鏈接
if(preg_match('/^http:\/\//', $v) || preg_match('/^https:\/\//', $v)){
$realLinks[] = $v;
}
}
//去除重復的鏈接
$realLinks = array_unique($realLinks);
echo "<pre>";
print_r($realLinks);//顯示過濾後的鏈接
echo "</pre>";
}
}
//域名
$domainName = 'www.163.com';
//使用Web爬蟲的方法
$spider = new Spider($domainName);//實例化spider類,並設置需要抓取的網站
$spider->start();//開始抓取數據
//$spider->show();//顯示抓取的內容
$spider->filterLinks();
2、執行後結果
3、執行完成,在文件所在目錄下會有個metaCache
文件,用文本編輯器打開如下
在獲取超鏈接以後,就可以再使用Web爬蟲類對這些鏈接進行下一步的數據抓取。具體的實現代碼可以使用無限循環來實現。
4、註意
- 上述例子暫時不能爬去https的網站,這個待去探索
上述例子如需要爬取像
http://news.163.com/17/1225/14/D6GQU683000189FH.html
這樣的鏈接,還需要著手擴展下上述代碼中socketOpen
函數(設置下請求頭信息,詳細情況見另一篇博文使用SOCKET獲取網頁的內容),
參考資料
- 1.[PHP實例精通 (編程實例大講堂)] 宮垂剛
- 2.PHP: fsockopen - Manual
SOCKET簡單爬蟲實現代碼和使用方法