欧美三区_成人在线免费观看视频_欧美极品少妇xxxxⅹ免费视频_a级毛片免费播放_鲁一鲁中文字幕久久_亚洲一级特黄

Python爬取Coursera課程資源的詳細過程

系統 1822 0

有時候我們需要把一些經典的東西收藏起來,時時回味,而Coursera上的一些課程無疑就是經典之作。Coursera中的大部分完結課程都提供了完整的配套教學資源,包括ppt,視頻以及字幕等,離線下來后會非常便于學習。很明顯,我們不會去一個文件一個文件的下載,只有傻子才那么干,程序員都是聰明人!

那我們聰明人準備怎么辦呢?當然是寫一個腳本來批量下載了。首先我們需要分析一下手工下載的流程:登錄自己的Coursera賬戶(有的課程需要我們登錄并選課后才能看到相應的資源),在課程資源頁面里,找到相應的文件鏈接,然后用喜歡的工具下載。

很簡單是吧?我們可以用程序來模仿以上的步驟,這樣就可以解放雙手了。整個程序分為三個部分就可以了:

登錄Coursera;在課程資源頁面里面找到資源鏈接;根據資源鏈接選擇合適的工具下載資源。

下面就來具體的實現以下吧!

登錄

剛開始時自己并沒有添加登錄模塊,以為訪客就可以下載相應的課程資源,后來在測試 comnetworks-002 這門課程時發現訪客訪問資源頁面時會自動跳轉到登錄界面,下圖是chrome在隱身模式訪問該課程資源頁面時的情況。

Python爬取Coursera課程資源的詳細過程_第1張圖片

要想模擬登錄,我們先找到登錄的頁面,然后利用google的 Developer Tools 分析賬號密碼是如何上傳到服務器的。

我們在登錄頁面的表單中填入賬號密碼,然后點擊登錄。與此同時,我們需要雙眼緊盯 Developer Tools――Network ,找到提交賬號信息的url。一般情況下,如果要向服務器提交信息,一般都用post方法,這里我們只需要先找到Method為post的url。悲劇的是,每次登錄賬號時,Network里面都找不到提交賬戶信息的地址。猜測登錄成功后,直接跳轉到登錄成功后的頁面,想要找的內容一閃而過了。

于是就隨便輸入了一組賬號密碼,故意登錄失敗,果真找到了post的頁面地址,如下圖:

Python爬取Coursera課程資源的詳細過程_第2張圖片

地址為: https://accounts.coursera.org/api/v1/login 。為了知道向服務器提交了哪些內容,進一步觀察post頁面中表單中內容,如下圖:

Python爬取Coursera課程資源的詳細過程_第3張圖片

我們看到一共有三個字段:

email:賬號的注冊郵箱password:賬號密碼webrequest:附加的字段,值為true。

接下來就動手寫吧,我選擇用python的 Requests 庫來模擬登錄,關于Requests官網是這樣介紹的。

Requests is an elegant and simple HTTP library for Python, built for human beings.

事實上requests用起來確實簡單方便,不虧是專門為人類設計的http庫。requests提供了 Session對象 ,可以用來在不同的請求中傳遞一些相同的數據,比如在每次請求中都攜帶cookie。

初步的代碼如下:

          
            signin_url = "https://accounts.coursera.org/api/v1/login"
            
logininfo = {"email": "...",
???????????? "password": "...",
???????????? "webrequest": "true"
???????????? }
          
            user_agent = ("Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_4) "
            
????????????? "AppleWebKit/537.36 (KHTML, like Gecko) "
????????????? "Chrome/36.0.1985.143 Safari/537.36")
          
            post_headers = {"User-Agent": user_agent,
            
??????????????? "Referer": "https://accounts.coursera.org/signin"
??????????????? }
coursera_session = requests.Session()
          
            login_res = coursera_session.post(signin_url,
            
????????????????????????????????? data=logininfo,
????????????????????????????????? headers=post_headers,
????????????????????????????????? )
if login_res.status_code == 200:
??? print "Login Successfully!"
else:
??? print login_res.text

將表單中提交的內容存放在字典中,然后作為data參數傳遞給Session.post函數。一般情況下,最好是加上請求 User-Agent Referer 等請求頭部,User-Agent用來模擬瀏覽器請求,Referer用來告訴服務器我是從referer頁面跳轉到請求頁面的,有時候服務器會檢查請求的Referer字段來保證是從固定地址跳到當前請求頁的。

上面片段的運行結果很奇怪,顯示如下信息: Invalid CSRF Token 。后來在github上面搜索到一個Coursera的批量下載腳本,發現人家發送頁面請求時headers多了 XCSRF2Cookie, XCSRF2Token, XCSRFToken, cookie 4個字段。于是又重新看了一下post頁面的請求頭部,發現確實有這幾個字段,估計是服務器端用來做一些限制的。

用瀏覽器登錄了幾次,發現XCSRF2Token, XCSRFToken是長度為24的隨機字符串,XCSRF2Cookie為"csrf2_token_"加上長度為8的隨機字符串。不過一直沒搞明白Cookie是怎么求出來的,不過看github上面代碼,Cookie似乎只是"csrftoken"和其他三個的組合,試了一下竟然可以。

在原來的代碼上添加以下部分就足夠了。

          
            def randomString(length):
            
??? return ''.join(random.choice(string.letters + string.digits) for i in xrange(length))
XCSRF2Cookie = 'csrf2_token_%s' % ''.join(randomString(8))
XCSRF2Token = ''.join(randomString(24))
XCSRFToken = ''.join(randomString(24))
cookie = "csrftoken=%s; %s=%s" % (XCSRFToken, XCSRF2Cookie, XCSRF2Token)
post_headers = {"User-Agent": user_agent,
??????????????? "Referer": "https://accounts.coursera.org/signin",
??????????????? "X-Requested-With": "XMLHttpRequest",
??????????????? "X-CSRF2-Cookie": XCSRF2Cookie,
??????????????? "X-CSRF2-Token": XCSRF2Token,
??????????????? "X-CSRFToken": XCSRFToken,
??????????????? "Cookie": cookie
??????????????? }

至此登錄功能初步實現。

分析資源鏈接

登錄成功后,我們只需要get到資源頁面的內容,然后過濾出自己需要的資源鏈接就行了。資源頁面的地址很簡單,為 https://class.coursera.org/name/lecture ,其中name為課程名稱。比如對于課程comnetworks-002,資源頁面地址為https://class.coursera.org/comnetworks-002/lecture。

抓取到頁面資源后,我們需要分析html文件,這里選擇使用 BeautifulSoup 。BeautifulSoup是一個可以從HTML或XML文件中提取數據的Python庫,相當強大。具體使用官網上有很詳細的文檔,這里不再贅述。在使用BeautifulSoup前,我們還得找出資源鏈接的規律,方便我們過濾。

其中課程每周的總題目為 class=course-item-list-header 的div標簽下,每周的課程均在 class=course-item-list-section-list 的ul標簽下,每節課程在一個li標簽中,課程資源則在li標簽中的div標簽中。

查看了幾門課程之后,發現過濾資源鏈接的方法很簡單,如下:

ppt和ppt資源:用正則表達式匹配鏈接;字幕資源:找到 title="Subtitles (srt)" 的標簽,取其 href 屬性;視頻資源:找到 title="Video (MP4)" 的標簽,取其 href 屬性即可。

字幕和視頻也可以用正則表達式過濾,不過用BeautifulSoup根據title屬性來匹配,有更好的易讀性。而ppt和pdf資源,沒有固定的title屬性,只好利用正則表達式來匹配。

具體代碼如下:

          
            soup = BeautifulSoup(content)
            
chapter_list = soup.find_all("div", class_="course-item-list-header")
lecture_resource_list = soup.find_all("ul", class_="course-item-list-section-list")
ppt_pattern = re.compile(r'https://[^"]*\.ppt[x]?')
pdf_pattern = re.compile(r'https://[^"]*\.pdf')
for lecture_item, chapter_item in zip(lecture_resource_list, chapter_list):
??? # weekly title
??? chapter = chapter_item.h3.text.lstrip()
??? for lecture in lecture_item:
??????? lecture_name = lecture.a.string.lstrip()
??????? # get resource link
??????? ppt_tag = lecture.find(href=ppt_pattern)
??????? pdf_tag = lecture.find(href=pdf_pattern)
??????? srt_tag = lecture.find(title="Subtitles (srt)")
??????? mp4_tag = lecture.find(title="Video (MP4)")
??????? print ppt_tag["href"], pdf_tag["href"]
??????? print srt_tag["href"], mp4_tag["href"]

下載資源

既然已經得到了資源鏈接,下載部分就很容易了,這里我選擇使用curl來下載。具體思路很簡單,就是輸出 curl resource_link -o file_name 到一個種子文件中去,比如到feed.sh中。這樣只需要給種子文件執行權限,然后運行種子文件即可。

為了便于歸類課程資源,可以為課程每周的標題建立一個文件夾,之后該周的所有課程均下載在該目錄下。為了方便我們快速定位到每節課的所有資源,可以把一節課的所有資源文件均命名為 課名.文件類型 。具體的實現比較簡單,這里不再給出具體程序了。可以看一下一個測試例子中的feed.sh文件,部分內容如下:

          
            mkdir 'Week 1: Introduction, Protocols, and Layering'
            
cd 'Week 1: Introduction, Protocols, and Layering'
curl https://d396qusza40orc.cloudfront.net/comnetworks/lect/1-readings.pdf -o '1-1 Goals and Motivation (15:46).pdf'
curl https://class.coursera.org/comnetworks-002/lecture/subtitles?q=25_en&format=srt -o '1-1 Goals and Motivation (15:46).srt'
curl https://class.coursera.org/comnetworks-002/lecture/download.mp4?lecture_id=25 -o '1-1 Goals and Motivation (15:46).mp4'
curl https://d396qusza40orc.cloudfront.net/comnetworks/lect/1-readings.pdf -o '1-2 Uses of Networks (17:12).pdf'
curl https://class.coursera.org/comnetworks-002/lecture/subtitles?q=11_en&format=srt -o '1-2 Uses of Networks (17:12).srt'
curl https://class.coursera.org/comnetworks-002/lecture/download.mp4?lecture_id=11 -o '1-2 Uses of Networks (17:12).mp4'

到這里為止,我們已經成功完成爬取Coursera課程資源的目標,具體的代碼放在gist上。使用時,我們只需要運行程序,并把課程名稱作為參數傳遞給程序就可以了(這里的課程名稱并不是整個課程的完整名字,而是在課程介紹頁面地址中的縮略名字,比如Computer Networks這門課,課程名稱是comnetworks-002)。

其實,這個程序可以看做一個簡單的小爬蟲程序了,下面粗略介紹下爬蟲的概念。

一點都不簡單的爬蟲

關于什么是爬蟲,wiki上是這樣說的

A Web crawler is an Internet bot that systematically browses the World Wide Web, typically for the purpose of Web indexing.

爬蟲的總體架構圖如下(圖片來自wiki):

Python爬取Coursera課程資源的詳細過程_第4張圖片

簡單來說,爬蟲從Scheduler中獲取初始的urls,下載相應的頁面,存儲有用的數據,同時分析該頁面中的鏈接,如果已經訪問就pass,沒訪問的話加入到Scheduler中等待抓取頁面。

當然有一些協議來約束爬蟲的行為規范,比如許多網站都有一個 robots.txt 文件來規定網站哪些內容可以被爬取,哪些不可以。

每個搜索引擎背后都有一個強大的爬蟲程序,把觸角伸到網絡中的所有角落,不斷去收集有用信息,并建立索引。這種搜索引擎級別的爬蟲實現起來非常復雜,因為網絡上的頁面數量太過龐大,只是遍歷他們就已經很困難了,更不要說去分析頁面信息,并建立索引了。

實際應用中,我們只需要爬取特定站點,抓取少量的資源,這樣實現起來簡單很多。不過仍然有許多讓人頭疼的問題,比如許多頁面元素是javascript生成的,這時候我們需要一個javascript引擎,渲染出整個頁面,再加以過濾。

更糟糕的是,許多站點都會用一些措施來阻止爬蟲爬取資源,比如限定同一IP一段時間的訪問次數,或者是限制兩次操作的時間間隔,加入驗證碼等等。絕大多數情況下,我們不知道服務器端是如何防止爬蟲的,所以要想讓爬蟲工作起來確實挺難的。


更多文章、技術交流、商務合作、聯系博主

微信掃碼或搜索:z360901061

微信掃一掃加我為好友

QQ號聯系: 360901061

您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點擊下面給點支持吧,站長非常感激您!手機微信長按不能支付解決辦法:請將微信支付二維碼保存到相冊,切換到微信,然后點擊微信右上角掃一掃功能,選擇支付二維碼完成支付。

【本文對您有幫助就好】

您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描上面二維碼支持博主2元、5元、10元、自定義金額等您想捐的金額吧,站長會非常 感謝您的哦!!!

發表我的評論
最新評論 總共0條評論
主站蜘蛛池模板: 一级毛片免费视频 | 亚洲国产99在线精品一区二区 | 国产国语一级a毛片高清视频 | 精品亚洲欧美高清不卡高清 | 男人天堂中文字幕 | 国产精品久久久久久无遮挡 | 1级毛片 | 午夜寂寞影院在线观看 | 狠狠影院 | 色视频网站在线观看 | 日韩精品一区二区三区在线观看 | 亚洲精品一区二区三区蜜桃久 | 国产精品久久久久一区二区 | 亚洲精品一区二区三区四区 | 天堂色网站 | 午夜精品久久久久久久99蜜桃i | 欧美日本另类xxx乱大交 | 亚洲人成在线播放 | 国产精品乱码人人做人人爱 | 日本污视频在线观看 | 91成人影院 | 99青草青草久热精品视频 | 欧美在线看 | 午夜精品久久久久久久星辰影院 | 国产精品久久久久久免费软件 | 国产男女爽爽爽免费视频 | 91高清视频在线 | 成人福利在线视频 | 久久com | 噜噜噜天天躁狠狠躁夜夜精品 | 激情91| 精品免费视频 | 久久精品国产亚洲一区二区 | 国产一级毛片在线看 | 精品久久一区二区三区 | 999毛片| 日本中文字幕一区 | 色狠狠成人综合网 | 久久久久国产一区二区三区四区 | 亚洲成色www久久网站 | 三A级做爰片免费观看国产电影 |