puppeteer爬蟲的奇妙之旅
@(爬蟲)[puppeteer|]
爬蟲又稱網路機器人。每天或許你都會使用搜索引擎,爬蟲便是搜尋引擎重要的組成部分,爬取內容做索引。現如今大資料,資料分析很火,那資料哪裡來呢,可以通過網路爬蟲爬取啊。那我萌就來探討一下網路爬蟲吧。

[TOC]
爬蟲的工作原理
如圖所示,這是爬蟲的流程圖,可以看到通過一個種子URL開啟爬蟲的爬取之旅,通過下載網頁,解析網頁中內容儲存,同時解析中網頁中的URL 去除重複後加入到等待爬取的佇列。然後從佇列中取到下一個等待爬取的URL重複以上步驟,是不是很簡單呢?
廣度(BFS)還是深度(DFS)優先策略
上面也提到在爬取完一個網頁後從等待爬取的佇列中選取一個URL去爬去,那如何選擇呢?是選擇當前爬取網頁中的URL 還是繼續選取當前URL中同級URL呢?這裡的同級URL是指來自同一個網頁的URL,這就是爬取策略之分。

廣度優先策略(BFS)
廣度優先策略便是將當前某個網頁中URL先爬取完全,再去爬取從當前網頁中的URL爬取的URL,這就是BFS,如果上圖的關係圖表示網頁的關係,那麼BFS的爬取策略將會是:(A->(B,D,F,G)->(C,F));
深度優先策略(DFS)
深度優先策略爬取某個網頁,然後繼續去爬取從網頁中解析出的URL,直到爬取完。 (A->B->C->D->E->F->G)
下載網頁
下載網頁看起來很簡單,就像在瀏覽器中輸入連結一樣,下載完後瀏覽器便能顯示出來。當然結果是並不是這樣的簡單。 ####模擬登入 對於一些網頁來說需要登入才能看到網頁中內容,那爬蟲怎麼登入呢?其實登入的過程就是獲取訪問的憑證(cookie,token...)
let cookie = ''; let j = request.jar() async function login() { if (cookie) { return await Promise.resolve(cookie); } return await new Promise((resolve, reject) => { request.post({ url: 'url', form: { m: 'username', p: 'password', }, jar: j }, function(err, res, body) { if (err) { reject(err); return; } cookie = j.getCookieString('url'); resolve(cookie); }) }) } 複製程式碼
這裡是個簡單的栗子,登入獲取cookie, 然後每次請求都帶上cookie.
獲取網頁內容
有的網頁內容是服務端渲染的,沒有CGI能夠獲得資料,只能從html中解析內容,但是有的網站的內容並不是簡單的便能獲取內容,像linkedin這樣的網站並不是簡單的能夠獲得網頁內容,網頁需要通過瀏覽器執行後才能獲得最終的html結構,那怎麼解決呢?前面我萌提到瀏覽器執行,那麼我萌有沒有可程式設計的瀏覽器呢? Chrome%2Fpuppeteer" rel="nofollow,noindex">puppeteer ,谷歌chrome團隊開源的無頭瀏覽器專案,利用無頭瀏覽器便能模擬使用者訪問,便能獲取最重網頁的內容,抓取內容。 利用puppeteer 模擬登入
async function login(username, password) { const browser = await puppeteer.launch(); page = await browser.newPage(); await page.setViewport({ width: 1400, height: 1000 }) await page.goto('https://maimai.cn/login'); console.log(page.url()) await page.focus('input[type=text]'); await page.type(username, { delay: 100 }); await page.focus('input[type=password]'); await page.type(password, { delay: 100 }); await page.$eval("input[type=submit]", el => el.click()); await page.waitForNavigation(); return page; } 複製程式碼
執行 login()
後便能像在瀏覽器中登入後,便能像瀏覽器中登入後便能獲取html中的內容,當讓w哦萌也可以直接請求CGI
async function crawlData(index, data) { let dataUrl = `https://maimai.cn/company/contacts?count=20&page=${index}&query=&dist=0&cid=${cinfo.cid}&company=${cinfo.encodename}&forcomp=1&searchTokens=&highlight=false&school=&me=&webcname=&webcid=&jsononly=1`; await page.goto(dataUrl); let res = await page.evaluate((e) => { return document.body.querySelector('pre').innerHTML; }); console.log(res) res = JSON.parse(res); if (res && res.result == 'ok' && res.data.contacts && res.data.contacts.length) { data = data.concat(res.data.contacts.map((item) => { let contact = item.contact; console.log(contact.name) return { name: contact.name, occupation: contact.line4.split(',')[0], company: contact.company, title: contact.position } })); return await crawlData(++index, data); } return data; } 複製程式碼
像有的網站,拉鉤,每次爬取的cookie都一樣,也能利用無頭瀏覽器取爬取,這樣每次就不用每次爬取的時候擔心cookie.
寫在最後
當然爬蟲不僅僅這些,更多的是對網站進行分析,找到合適的爬蟲策略。對後關於 puppeteer
,不僅僅可以用來做爬蟲,因為可以程式設計,無頭瀏覽器,可以用來自動化測試等等。