摘要:最近看了很多關于爬蟲入門的文章,發現其中大部分都是以知乎為爬取對象,所以這次我也以知乎為目標來進行爬取的演示,用到的爬蟲框架為編寫的。項目地址這次寫的內容為爬取知乎的用戶,下面就是詳細說一下寫爬蟲的過程了。
最近看了很多關于爬蟲入門的文章,發現其中大部分都是以知乎為爬取對象,所以這次我也以知乎為目標來進行爬取的演示,用到的爬蟲框架為 PHP 編寫的 Beanbun。
項目地址:https://github.com/kiddyuchina/Beanbun
這次寫的內容為爬取知乎的用戶,下面就是詳細說一下寫爬蟲的過程了。
爬取知乎用戶的思路比較簡單,就是從某個用戶開始,先抓取這個用戶關注的人和關注他的人,抓取到這些人后,再抓取他們的相關的用戶。
現在知乎是可以使用游客身份進行瀏覽的,也省去了注冊和登錄這一部分。先隨便找個大V吧,因為他們的關注者比較多,我選擇的是大名鼎鼎的張公子,張公子的關注者有13萬,就是說只爬取他的關注者,我們都能有13萬的用戶數據~
在用戶頁面中打開chrome瀏覽器的開發者選項,點擊關注者后就可以看到請求地址和數據。
就以這個作為入口開始爬取了~
此處跳過框架的安裝和隊列的開啟,直接上爬蟲的代碼:
(如果需要跳過的部分,可以看一下文檔)
name = "zhihu_user"; $beanbun->count = 5; $beanbun->interval = 4; $beanbun->seed = "https://www.zhihu.com/api/v4/members/zhang-jia-wei/followers?include=data%5B*%5D.answer_count%2Carticles_count%2Cgender%2Cfollower_count%2Cis_followed%2Cis_following%2Cbadge%5B%3F(type%3Dbest_answerer)%5D.topics&offset=0&limit=20"; $beanbun->logFile = __DIR__ . "/zhihu_user_access.log";
上面是對爬蟲的配置,開啟5個進程同時爬取,設置爬取間隔為4秒。在爬去前,我們還要設置一下請求的headers,好讓網站認為是人類再瀏覽他- -。headers的內容從開發者選項中一股腦粘貼進來。
$beanbun->beforeDownloadPage = function ($beanbun) { // 在爬取前設置請求的 headers $beanbun->options["headers"] = [ "Host" => "www.zhihu.com", "Connection" => "keep-alive", "Cache-Control" => "max-age=0", "Upgrade-Insecure-Requests" => "1", "User-Agent" => "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/57.0.2987.133 Safari/537.36", "Accept" => "application/json, text/plain, */*", "Accept-Encoding" => "gzip, deflate, sdch, br", "authorization" => "oauth c3cef7c66a1843f8b3a9e6a1e3160e20", ]; };
而在請求到數據后,我還需要把他們存到數據庫中,因為主要是演示,所以只保存用戶的id,name,follower,following這四個數據。
// 數據庫配置 Db::$config["zhihu"] = [ "server" => "127.0.0.1", "port" => "3306", "username" => "xxxx", "password" => "xxxx", "database_name" => "zhihu", "charset" => "utf8", ]; $beanbun->afterDownloadPage = function ($beanbun) { // 獲取的數據為 json,先解析 $data = json_decode($beanbun->page, true); // 如果沒有數據或報錯,那可能是被屏蔽了。就把地址才重新加回隊列 if (isset($data["error"]) || !isset($data["data"])) { $beanbun->queue()->add($beanbun->url); $beanbun->error(); } // 如果本次爬取的不是最后一頁,就把下一頁加入隊列 if ($data["paging"]["is_end"] == false) { $beanbun->queue()->add($data["paging"]["next"]); } $insert = []; $date = date("Y-m-d H:i:s"); foreach ($data["data"] as $user) { // 如果關注者或者關注的人小于5個,就不保存了 if ($user["follower_count"] < 5 || $user["following_count"] < 5) { continue ; } $insert[] = [ "id" => $user["id"], "name" => $user["name"], "follower" => $user["follower_count"], "following" => $user["following_count"], "created_at" => $date, ]; // 把用戶的關注者和關注的人列表加入隊列 $beanbun->queue()->add("https://www.zhihu.com/api/v4/members/" . $user["url_token"] . "/followers?include=data%5B*%5D.following_count%2Cfollower_count&limit=20&offset=0"); $beanbun->queue()->add("https://www.zhihu.com/api/v4/members/" . $user["url_token"] . "/followees?include=data%5B*%5D.following_count%2Cfollower_count&limit=20&offset=0"); } } if (count($insert)) { Db::instance("zhihu")->insert("zhihu_user", $insert); } // 把剛剛爬取的地址標記為已經爬取 $beanbun->queue()->queued($beanbun->queue); }; // 不需要框架來發現新的網址, $beanbun->discoverUrl = function () {}; $beanbun->start();
接下來在命令行運行爬蟲
$ php zhihu_user.php start
再去看一眼數據庫,源源不斷的用戶數據保存進來了~
在一切順利的情況下,我又稍微作了一下死,把爬取的間隔減到了2秒,于是在10幾分鐘之后,我被知乎封掉了....
這種情況比較常見的解決方式就是使用代理,下面就在原有爬蟲基礎上,增加一個簡單的可定時更新的代理池。
先停止爬蟲
$ php zhihu_user.php stop
網上有很多免費代理的網站,我隨便選了一個提供免費代理的網站,爬取到代理的數據后,先請求一下163,如果成功的話就加入代理池。
function getProxies($beanbun) { $client = new GuzzleHttpClient(); $beanbun->proxies = []; $pattern = "/(.+) (d+) (.+)(HTTP|HTTPS) get("http://www.mimiip.com/gngao/$i"); $html = str_replace([" ", " ", " "], "", $res->getBody()); preg_match_all($pattern, $html, $match); foreach ($match[1] as $k => $v) { $proxy = strtolower($match[4][$k]) . "://{$v}:{$match[2][$k]}"; echo "get proxy $proxy "; try { $res = $client->get("http://mail.163.com", [ "proxy" => $proxy, "timeout" => 6 ]); echo "success. "; } catch (Exception $e) { echo "error. "; } } } } if ($argv[1] == "start") { getProxies($beanbun); } $beanbun->startWorker = function($beanbun) { // 每隔半小時,更新一下代理池 Beanbun::timer(1800, "getProxies", $beanbun); };再在之前的 beforeDownloadPage 中加入
if (isset($beanbun->proxies) && count($beanbun->proxies)) { $beanbun->options["proxy"] = $beanbun->proxies[array_rand($beanbun->proxies)]; }再次啟動爬蟲,爬蟲還會接著之前的隊列繼續爬取。
$ php zhihu_user.php start再看看數據庫,使用代理可能會比之前慢一些,不過數據又繼續增加了。
最終的代碼可以在 Github 上查看https://github.com/kiddyuchin...
例子中的代理池還是比較簡陋的,只是用來說明框架的靈活,而爬取到數據在這里就不做圖表進行分析了,希望大家關注的也是寫爬蟲的過程。
最后如果你對這篇文章感興趣,希望能到 Github 上給個 star 啦,謝謝~https://github.com/kiddyuchin...
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/22915.html
相關文章
php爬蟲:知乎用戶數據爬取和分析
摘要:背景說明小拽利用的寫的爬蟲,實驗性的爬取了知乎用戶的基本信息同時,針對爬取的數據,進行了簡單的分析呈現。本程序抓取的是知乎對外提供用戶訪問的個人信息頁面抓取過程需要攜帶用戶才能獲取頁面。 背景說明:小拽利用php的curl寫的爬蟲,實驗性的爬取了知乎5w用戶的基本信息;同時,針對爬取的數據,進行了簡單的分析呈現。demo 地址 php的spider代碼和用戶dashboard的展現代碼...
php爬蟲:知乎用戶數據爬取和分析
摘要:背景說明小拽利用的寫的爬蟲,實驗性的爬取了知乎用戶的基本信息同時,針對爬取的數據,進行了簡單的分析呈現。本程序抓取的是知乎對外提供用戶訪問的個人信息頁面抓取過程需要攜帶用戶才能獲取頁面。 背景說明:小拽利用php的curl寫的爬蟲,實驗性的爬取了知乎5w用戶的基本信息;同時,針對爬取的數據,進行了簡單的分析呈現。demo 地址 php的spider代碼和用戶dashboard的展現代碼...
php爬蟲:知乎用戶數據爬取和分析
摘要:背景說明小拽利用的寫的爬蟲,實驗性的爬取了知乎用戶的基本信息同時,針對爬取的數據,進行了簡單的分析呈現。本程序抓取的是知乎對外提供用戶訪問的個人信息頁面抓取過程需要攜帶用戶才能獲取頁面。 背景說明:小拽利用php的curl寫的爬蟲,實驗性的爬取了知乎5w用戶的基本信息;同時,針對爬取的數據,進行了簡單的分析呈現。demo 地址 php的spider代碼和用戶dashboard的展現代碼...
發表評論
0條評論
tomato
男|高級講師
TA的文章
閱讀更多
Tor Browser 11.0 發布
閱讀 1699·2021-11-12 10:36
知識圖譜是什么?一文了解其技術與應用場景案例
閱讀 1615·2021-11-12 10:36
關于SSL證書10大統計數據
閱讀 3442·2021-11-02 14:46
sass介紹及使用
閱讀 3798·2019-08-30 15:56
CSDN 文章自動顯示全文
閱讀 3534·2019-08-30 15:55
30分鐘完成JavaScript中的記憶游戲
閱讀 1463·2019-08-30 15:44
另一種方式實現事務碼SE16里的結果集修改
閱讀 1044·2019-08-30 14:00
web前端性能優化
閱讀 2735·2019-08-29 18:41
閱讀需要支付1元查看