網易雲課堂Excel課程爬蟲思路
由於即將畢業,馬上進入職場,想來是時候需要鞏固一下基本職場技能了,特別是Excel這種殺手級職場應用。
可是如今網路這麼發達,到處都充斥著Excel課程、視頻、教程,真的很容易讓人眼花繚亂,不知所措。
看書來的太慢了,還是直接看視頻吧,簡單粗暴,學習之前總要熟悉一下Excel教學行業的大致情況吧,今天就拿網易雲課堂的Excel板塊作為目標,在練習數據爬取的同時,順便了解一下Excel培訓行業的行情,知己知彼才能百戰不殆,才能更加集中精力的學習那些精品課程。
url<-"http://study.163.com/category/excel#/" n
#Excel板塊首頁網址
url<-"http://study.163.com/category/excel#/?p=2" n
#載入第二頁之後的網址
網易雲課堂的網頁不是很複雜,而且URL是很規律的參數拼接,反倒最底部可以看到,它是點擊翻頁,一共只有9頁,而且頁面是順序載入,OK,可以直接手動拼接遍歷網址了。
url<-paste0("http://study.163.com/category/excel#/?p=",1:9)n
library("rvest")nlibrary("XML")nlibrary("RCurl")npostForm(url[1],)nweb<-read_html(url[1],encoding="UTF-8")%>% nhtml_nodes("div.uc-ykt-coursecard-wrap_tit > h3") %>% html_text()n
but以上嘗試都失敗了!
當我想當然的以為網易雲課堂用R可以輕鬆搞定的時候,猛然發現他用的XHR技術,奔潰……
首先我們再次分析網頁,打開雲課堂Excel模塊首頁,按F12翻到XHR菜單
在底部你可以看到studycourse.json文件,點開之後可以看到右側的Preview欄目裡面全部都是課程信息,是一個json文件。
這個模塊是Chrome的開發者工具後台,就是我們常說的抓包工具,現在切換到Headers欄目,可以看到雲課堂所有的課程信息都是在一個.josn網頁裡面存放著,這裡便是阻礙我們使用普通方法爬取數據的困難之源。
仔細看你會發現General裡面用到的Request Method 是Post,Post方法在 提交網址和參數的同時,要提交表單數據,這時候我們需要詳細的查看Request Headers裡面的參數信息。
因為POST方法涉及到傳遞表單參數,所以構造報頭一定要添加Content-Type參數,這裡的Content-Type參數是application/json,需要傳遞json字元串。
看來今天這個案例用R語言有些困哪了(使用 webdriver除了偷懶,並不能鍛煉你什麼能力),本案例POST要傳遞json表單參數,R裡面沒有很多的處理json的方式,再加上RCurl裡面的POST方法資料太少,沒有什麼可參考資料。(還是R語言的爬蟲生態太弱了)。
所以今天用Pyhton來演示本案例:
import jsonnimport requestsnimport pandas as pdnimport osn
第一步:分析XHR中POST方法的表單規律:
使用POST方法爬取數據,需要重點關注Request Headers中的User-Agent、Content-Type以及最後面的表單體。
本例的網頁,雖然看上去分了9個子頁面,但是實際上其調用的json僅有一個主頁:nhttp://study.163.com/p/search/studycourse.jsonn
而不同子頁面主要是用過表單體中的參數來確定到的。
{"pageIndex":1,"pageSize":50,"relativeOffset":0,"frontCategoryId":"400000000149040","searchTimeType":-1,"orderType":0,"priceType":-1,"activityId":0}n{"pageIndex":2,"pageSize":50,"relativeOffset":50,"frontCategoryId":"400000000149040","searchTimeType":-1,"orderType":0,"priceType":-1,"activityId":0}n{"pageIndex":3,"pageSize":50,"relativeOffset":100,"frontCategoryId":"400000000149040","searchTimeType":-1,"orderType":0,"priceType":-1,"activityId":0}n……n{"pageIndex":9,"pageSize":50,"relativeOffset":400,"frontCategoryId":"400000000149040","searchTimeType":-1,"orderType":0,"priceType":-1,"activityId":0}n
以上我給出了9個頁面的表單體信息中的前三個和最後一個,通過找規律你會發現,差異僅在pageIndex和relativeOffset參數上,其他參數都是一樣的。pageIndex和relativeOffset分別代表頁面id和主頁中信息條目的偏移量。偏移量間隔50,也就是我們在網頁上看到的單頁展示課程數目。
構造表單體:
payload = {n "pageIndex":1,n "pageSize":50,n "relativeOffset":100,n "frontCategoryId":"400000000149040"n }n
一共9個子頁面,通過表單體參數進行頁面遍歷控制
構造報頭信息:
headers = {n Accept:application/json,n content-type:application/json,n User-Agent:Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/61.0.3163.79 Safari/537.36n }n
第二步:構造網頁爬取函數:
url = http://study.163.com/p/search/studycourse.jsonnr=requests.post(url,data=json.dumps(payload),headers=headers);rn<Response [200]>n狀態碼OK!ncontent=r.json();contentn
type(content)ndict ###返回內容類型為字典n返回的是一個字典,裡面嵌套有很多層,仔細觀察你會先發,我們需要的內容都存放在content[result][list]裡面ncontent[result][list] n
type(content[result][list])nlist ###返回類型是列表n
OK,構造一個循環,將每一次請求返回提取的內容拼接在一個列表裡面:
fullinfo=[]nfor i in list(range(1,10)):n payload[pageIndex]=in payload[relativeOffset]=50*i-50n r=requests.post(url,data=json.dumps(payload),headers=headers)n content=r.json()n fullinfo=fullinfo+content[result][list]n print("第{}部分已載入".format(i))n
df1=pd.DataFrame(fullinfo)ndf1.columns ###返回所有列信息nIndex([activityIds, bigImgUrl, courseCardProps, courseId,n description, discountPrice, discountRate, displayType,n endTime, forumTagLector, gmtModified, imgUrl, isPromStatus,n learnerCount, lectorName, originalPrice, productId,n productName, productType, provider, published,n schoolShortName, score, scoreLevel, startTime, tagIap,n tagLectorTime],n dtype=object)n###提取我們需要的列:nmydata=df1[["productName","discountPrice","discountRate","lectorName","originalPrice","description","provider","score","scoreLevel"]]n
存儲本地:
os.chdir(D:/Python/Data)nmydata.to_csv(yunketang.csv,index=False)n
存儲到本地硬碟,搞完收工!一共421條Excel課程信息,和後台的信息一致。
下一篇針對這一次爬蟲結果做可視化分析!
Hellobi Live | 9月12日 R語言可視化在商務場景中的應用
推薦閱讀:
※你眼中的我
※[R]利用R Markdown生成爬蟲分析報告
※現在的網路爬蟲的研究成果和存在的問題有哪些?
※我該如何用PHP的cURL獲取這個奇葩的網頁內容?
※selenium 怎樣設置請求頭?