最近有一個小需求,須要根據用戶輸入的某寶的店鋪 url,檢查地址是否存在,並抓取店鋪名稱。某寶店鋪 url 的 title 一般是 xx-xx-xx 的形式,中間的 xx 就是對應的店鋪名稱。html
這個需求很簡單,根據 url 直接發送 get 請求,利用 cheerio 解析獲得的 html 文件,就能夠得到 title 的內容,再切割字符串就能夠得到店鋪名稱。git
爲了驗證某寶店鋪頁面的 title 均是 xx-xx-xx 形式,而且中間的 xx 就是店鋪名稱,就要搜索大量店鋪頁面名稱。一個個查看即耗時間也不實際,因而決定利用爬蟲快速獲取店鋪名稱。其實爬蟲的基本思路並不難,更重要的在於分析頁面結構,以獲取須要的內容。github
頁面大體分爲3種狀況:web
① 直出頁面,獲取到 html 文件就能夠解析須要的內容瀏覽器
② 動態頁面,所需內容是數據經過接口得到的,直接請求接口便可併發
③ 動態頁面,找不到相關數據接口,藉助 PhantomJS 獲取完整的頁面性能
怎樣能快速得到大量的店鋪 url 呢?某寶的寶貝列表中,寶貝信息實際上是包含了該寶貝所在店鋪首頁的連接,經過寶貝列表就能夠快速得到店鋪 url。經過分析頁面,很不幸,寶貝列表是腳本動態加載的,而且找不到相關數據的接口,惟有藉助 PhantomJS 了。PhantomJS 雖然強大,但性能並非很好,不過爲了知足個人好奇心,足夠了。lua
PhantomJSurl
PhantomJS 是一個 webkit 的 JavaScript API,至關於一個閹割版的瀏覽器,詳情可查看官網spa
PhantomJS 獲取並解析頁面的語法也很簡單,完整demo
// page。open 打開並加載 url,這裏的 url 爲寶貝列表頁面
page.open(url, function (s) { console.log('index ' + index + ' ' + s) if (s === 'success') { setTimeout(function () {
// page.evaluate 用於解析頁面內容,詳情請看官網 const shopUrl = page.evaluate(function () { const urls = [] const ele = document.getElementsByClassName('J_ShopInfo') for(var i = 0, len = ele.length; i < len; ++i) { const item = ele[i] urls.push(item.href) } return urls }) getTitle(shopUrl, 0, getShopsName(index + 44, max)) }, 1500) } })
getTitle 用於獲取店鋪首頁 url 的 title
function getTitle (urls, i, cb) { if (i < urls.length) { const url = urls[i] page.open(url, function(s) { if (s === 'success') { const result = page.evaluate(function () { return document.title }) console.log(i + ' ' + result) titles.push(result) getTitle (urls, i + 1, cb) } }) } else { cb && cb() } }
在訪問寶貝列表頁面和店鋪頁面時,因爲某寶的反爬蟲措施,這裏都用了遞歸搜索,確保不是併發請求頁面,不然頁面會獲取失敗。setTimeout 是爲了等待頁面中所需內容已加載後再解析。若是獲取到頁面後當即解析,只會獲得一個幾乎空白的頁面。
因爲頁面都包含大量的圖片信息,能夠經過設置
page.settings.loadImages = false
不加載內聯圖片,減小 PhantomJS 的性能消耗。
讓程序本身一直循環執行,就能夠獲取到大量的數據啦