PHP爬蟲技術知識點總結

不言
發布: 2023-03-23 06:42:01
原創
1936 人瀏覽過


在的爬蟲框架很多,比較流行的是基於python,nodejs,java,C#,PHP的的框架,其中又以基於python的爬蟲流行最為廣泛,還有的已經是一套傻瓜式的軟體操作,如八爪魚,火車頭等軟體。

 今天我們首先嘗試的是使用PHP實作一個爬蟲程序,首先在不使用爬蟲框架的基礎上實踐也是為了理解爬蟲的原理,然後再利用PHP的lib,框架和擴展進行實踐。



#1.PHP簡單的爬蟲–原型

爬蟲的原理:

  • #給定原始的url;

  • #分析鏈接,根據設定的正規表示式取得連結中的內容;

  • 有的會更新原始的url再進行分析鏈接,獲取特定內容,周而復始。

  • 將取得的內容保存在資料庫中(mysql)或本機檔案中

    #

下面是網路上一個例子,我們列下來然後分析
##main函數開始

\'\"\ ]*).*?>/'; $result = preg_match_all($reg_tag_a, $web_content, $match_result); if ($result) { return $match_result[1]; } } /** * 修正相对路径 * @param string $base_url * @param array $url_list * @return array */function _reviseUrl($base_url, $url_list) { $url_info = parse_url($base_url);//解析url $base_url = $url_info["scheme"] . '://'; if ($url_info["user"] && $url_info["pass"]) { $base_url .= $url_info["user"] . ":" . $url_info["pass"] . "@"; } $base_url .= $url_info["host"]; if ($url_info["port"]) { $base_url .= ":" . $url_info["port"]; } $base_url .= $url_info["path"]; if (is_array($url_list)) { foreach ($url_list as $url_item) { if (preg_match('/^http/', $url_item)) { // 已经是完整的url $result[] = $url_item; } else { // 不完整的url $real_url = $base_url . '/' . $url_item; $result[] = $real_url; } } return $result; } else { return; } } /** * 爬虫 * @param string $url * @return array */function crawler($url) { $content = _getUrlContent($url); if ($content) { $url_list = _reviseUrl($url, _filterUrl($content)); if ($url_list) { return $url_list; } else { return ; } } else { return ; } } /** * 测试用主程序 */function main() { $file_path = "url-01.txt"; $current_url = "http://www.baidu.com/"; //初始url if(file_exists($file_path)){ unlink($file_path); } $fp_puts = fopen($file_path, "ab"); //记录url列表 $fp_gets = fopen($file_path, "r"); //保存url列表 do { $result_url_arr = crawler($current_url); if ($result_url_arr) { foreach ($result_url_arr as $url) { fputs($fp_puts, $url . "\r\n"); } } } while ($current_url = fgets($fp_gets, 1024)); //不断获得url} main();?>
登入後複製

2.使用crul lib

#Curl是比較成熟的一個lib,異常處理、http header、POST之類都做得很好,重要的是PHP下操作MySQL進行入庫操作比較省心。關於curl的說明具體可以查看PHP官方文檔,不過在多線程Curl(Curl_multi)方面比較麻煩。

開啟crul針對winow系統:
- php.in中修改(註解;去掉即可)

##extension =php_curl.dll

  • php資料夾下的libeay32.dll, ssleay32.dll, libssh2.dll 還有php/ext下的php_curl4個檔案移入windows /system32

使用crul爬蟲的

步驟:- 使用cURL函數的基本想法是先用curl_init()初始化一個cURL會話;- 接著你可以透過curl_setopt()設定你需要的全部選項;
- 然後使用curl_exec()來執行會話;
- 執行完會話後使用curl_close()關閉會話。

範例

#$ch= curl_init("http://www.example.com/");

$fp= fopen("example_homepage.txt","w"# );curl_setopt($ch, CURLOPT_FILE,$fp);curl_setopt($ch, CURLOPT_HEADER,0);curl_exec($ch);curl_close($ch);fclose($fp);?>

#


一个完整点的例子:

\'\"\ ]*).*?>/'; $result = preg_match_all($reg_tag_a, $web_content, $match_result); if ($result) { return $match_result[1]; } } /** * 修正相对路径 * @param string $base_url * @param array $url_list * @return array */function _reviseUrl($base_url, $url_list) { $url_info = parse_url($base_url);//解析url $base_url = $url_info["scheme"] . '://'; if ($url_info["user"] && $url_info["pass"]) { $base_url .= $url_info["user"] . ":" . $url_info["pass"] . "@"; } $base_url .= $url_info["host"]; if ($url_info["port"]) { $base_url .= ":" . $url_info["port"]; } $base_url .= $url_info["path"]; if (is_array($url_list)) { foreach ($url_list as $url_item) { if (preg_match('/^http/', $url_item)) { // 已经是完整的url $result[] = $url_item; } else { // 不完整的url $real_url = $base_url . '/' . $url_item; $result[] = $real_url; } } return $result; } else { return; } } /** * 爬虫 * @param string $url * @return array */function crawler($url) { $content = _getUrlContent($url); if ($content) { $url_list = _reviseUrl($url, _filterUrl($content)); if ($url_list) { return $url_list; } else { return ; } } else { return ; } } /** * 测试用主程序 */function main() { $file_path = "./url-03.txt"; if(file_exists($file_path)){ unlink($file_path); } $current_url = "http://www.baidu.com"; //初始url //记录url列表  ab- 追加打开一个二进制文件,并在文件末尾写数据 $fp_puts = fopen($file_path, "ab"); //保存url列表 r-只读方式打开,将文件指针指向文件头 $fp_gets = fopen($file_path, "r"); do { $result_url_arr = crawler($current_url); echo "

$current_url

"; if ($result_url_arr) { foreach ($result_url_arr as $url) { fputs($fp_puts, $url . "\r\n"); } } } while ($current_url = fgets($fp_gets, 1024)); //不断获得url} main();?>
登入後複製

要对https支持,需要在_getUrlContent函数中加入下面的设置:

curl_setopt($ch, CURLOPT_HTTPAUTH, CURLAUTH_BASIC ) ; curl_setopt($ch, CURLOPT_USERPWD, "username:password"); curl_setopt($ch, CURLOPT_SSLVERSION,3); curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE); curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 2);
登入後複製

结果疑惑:
我们通过1和2部分得到的结果差异很大,第1部分能得到四千多条url数据,而第2部分却一直是45条数据。

还有我们获得url数据可能会有重复的,这部分处理在我的github上,对应demo2-01.php,或者demo2-02.php

3.file_get_contents/stream_get_contents与curl对比

3.1 file_get_contents/stream_get_contents对比

  • stream_get_contents — 读取资源流到一个字符串
    与 [file_get_contents()]一样,但是stream_get_contents()是对一个已经打开的资源流进行操作,并将其内容写入一个字符串返回


$handle= fopen($url##,"r");

$content# = stream_get_contents($handle#, -1);

//讀取資源流到一個字串,第二個參數需要讀取的最大的位元組數。預設是-1(讀取全部的緩衝資料)


#

  • file_get_contents — 将整个文件读入一个字符串

$content = file_get_contents($url, 1024 * 1024);
【注】 如果要打开有特殊字符的 URL (比如说有空格),就需要使用进行 URL 编码。
登入後複製

3.2 file_get_contents/stream_get_contents与curl对比

- fopen /file_get_contents 每次请求都会重新做DNS查询,并不对 DNS信息进行缓存。但是CURL会自动对DNS信息进行缓存。对同一域名下的网页或者图片的请求只需要一次DNS查询。这大大减少了DNS查询的次数。所以CURL的性能比fopen /file_get_contents 好很多。

  • fopen /file_get_contents 在请求HTTP时,使用的是http_fopen_wrapper,不会keeplive。而curl却可以。这样在多次请求多个链接时,curl效率会好一些。

  • fopen / file_get_contents 函数会受到php.ini文件中allow_url_open选项配置的影响。如果该配置关闭了,则该函数也就失效了。而curl不受该配置的影响。

  • curl 可以模拟多种请求,例如:POST数据,表单提交等,用户可以按照自己的需求来定制请求。而fopen / file_get_contents只能使用get方式获取数据

相关推荐:

一个简单的开源PHP爬虫框架『Phpfetcher』

以上是PHP爬蟲技術知識點總結的詳細內容。更多資訊請關注PHP中文網其他相關文章!

相關標籤:
來源:php.cn
本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn
作者最新文章
最新下載
更多>
網站特效
網站源碼
網站素材
前端模板
關於我們 免責聲明 Sitemap
PHP中文網:公益線上PHP培訓,幫助PHP學習者快速成長!