使用python爬蟲爬取愛課程視訊
CSDN上寫的第一篇部落格,初學程式設計,寫的疏漏頗多,還請見諒。
最初是自己想找一些大學公開課的資源,隨後發現了有一個叫愛課程的網站www.icourses.cn,上面提供了近千門視訊公開課,正符合我的需求,便找了本爬蟲的書,開始學習爬取視訊。
然而,爬取過程並不順利。
首先,視訊網站的視訊連結並不像京東淘寶的圖片一樣存在於當前頁面,你需要進入每個老師的課堂到達視訊播放頁才能提取到連結。
第二,也是困擾我長達一週多的東西,這個網站的url並不會隨著頁面的變化而變化,這和書上說的完全不一樣啊喂(#`O′),同樣的,網頁原始碼也始終和第一頁的程式碼保持一致,完全得不到後面四十多頁的任何資訊。當時我換了數個瀏覽器,百度了無數的內容,自行增添網址字尾,都沒有任何效果,絕望的我差點就要放棄了。
第一頁課程
第二頁課程
後來,和我一塊學習爬蟲的同學告訴我,在fiddler中可以看到第二頁之後的網頁原始碼
第一頁的網頁原始碼
第二頁的網頁原始碼
這讓我有了一絲繼續下去的希望,至少原始碼能看到了,只要把原始碼都搞到一個檔案裡,課堂的連結就都能提取出來了。
但是,很明顯,五十頁的網頁原始碼光復制貼上就覺得很麻煩,這種方法還是顯得太笨了。我依舊在思考如何能讓程式碼自動翻頁。
在我苦苦追尋答案的幾天裡,同學已經用上面的笨方法爬取了三十頁的視訊= =。
偶然的一天我注意到了網頁除了有get請求外還有post請求,而post請求是不會有url的變化的,之前書中介紹的post請求都是和模擬登陸有關我都沒在意,這一天我開啟瀏覽器按下了
果不其然!網頁是向一個videoSearchPage的地方傳送了post請求然後再返回來的!繼續開啟fiddler我查到了傳送請求所需的引數
緊接著我按照書中的教程寫出了爬取頁面的程式碼:
# -*- coding: utf-8 -*- """ Created on Wed Apr 11 15:57:56 2018 @author: 好讀秒 """ import re import urllib.request import urllib.parse a = 31 for a in range(31,35): url = "http://www.icourses.cn/web//sword/portal/videoSearchPage" postdata = urllib.parse.urlencode({ 'JSESSIONID':"EC283676A72516765DCB5844584D7A23-n1", 'Hm_lvt_787dbcb72bb32d4789a985fd6cd53a46':'1523326195,1523433916', 'Hm_lpvt_787dbcb72bb32d4789a985fd6cd53a46':'1523433987', 'currentPage':f'{a}', 'listType':'1' }).encode('utf-8') req = urllib.request.Request(url,postdata) req.add_header("User-Agent",'Mozilla/5.0(Windows NT 6.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/38.0.2125.122 Safari/537.36 SE 2.X MetaSr 1.0') data = urllib.request.urlopen(req).read() data = str(data) ptn = re.compile('<li class="pull-left.*?<div.*?</div>.*?href="(.*?)".*?</a>.*?<a.*?href=.*?title=', re.S) data2 = re.findall(ptn, data) fhandle = open("d:/1/7.txt",'a') fhandle.write(str(data2)) fhandle.close()
不知為何如果一次性爬多了網路會超時,我最多5頁5頁的爬取,並把這些課堂連結儲存到記事本里。
事情完成了一半,接下來的任務就是爬取記下來的連結中的視訊了。
其實使用urllib.request就能把視訊扒下來(大概),在這裡我想練一下scrapy框架。
開始建立一個scrapy工程(scrapy安裝就不說了):
在cmd中進入到你想要建立的目錄中,輸入scraoy startproject icourses:
開啟建立好的工程,首先編寫items.py,用來表示我要爬取的內容,對於我來說只需要視訊名稱(老師名)和視訊地址就夠了:
# -*- coding: utf-8 -*-
# Define here the models for your scraped items
#
# See documentation in:
# https://doc.scrapy.org/en/latest/topics/items.html
import scrapy
class IcoursesItem(scrapy.Item):
# define the fields for your item here like:
# name = scrapy.Field()
mp4name = scrapy.Field()
mp4url = scrapy.Field()
然後編寫pipelines.py檔案,用來設定爬取下來的東西的儲存位置:
# -*- coding: utf-8 -*-
# Define your item pipelines here
#
# Don't forget to add your pipeline to the ITEM_PIPELINES setting
# See: https://doc.scrapy.org/en/latest/topics/item-pipeline.html
import urllib.request
class IcoursesPipeline(object):
def process_item(self, item, spider):
num = [1,2,3,4,5,6,7,8]
for i in range(0,len(item["mp4url"])):
thisurl = item['mp4url'][i]
url = thisurl + '.mp4'
num[i] = i
name = item['mp4name']
thisname = name + [num[i]]
urllib.request.urlretrieve(url, filename="d:/1/mp4/"+str(thisname)+".mp4")
return item
然後設定settings.py檔案,去掉前面的註釋符號就可以啦:
ITEM_PIPELINES = {
'icourses.pipelines.IcoursesPipeline': 300,
}
重頭戲就是下面的主程式了,首先在工程內建立一個爬蟲:
這是建立了一個basic模板的爬蟲,還有其他模板書上沒細講,我也就放棄了。
之後開始修改建立的icourse.py檔案:
# -*- coding: utf-8 -*-
import scrapy
import re
from icourses.items import IcoursesItem
from scrapy.http import Request
class IcourseSpider(scrapy.Spider):
name = 'icourse'
allowed_domains = ['icourse.cn']
f= open(r"d:/1/7.json","r")
s = f.readlines()
f.close()
start_urls = ['']
def parse(self, response):
item = IcoursesItem()
pattern ='(http://res2.icourses.cn/video/mobile/.*?).mp4'
item['mp4url'] = re.compile(pattern).findall(str(response.body))
item['mp4name']=response.xpath("//a[@class='teacher-infor-name']/text()").extract()
yield item
首先start_url內填上自己想要爬取的網頁,我本來是想直接讀出記事本的內容填進去,沒想到總是出錯,於是我就把網頁直接複製進去了,網頁太多,就不寫出來了
其次xpath我還有很多地方搞不清楚,比如這裡的老師我可以用他爬出來,但是視訊連結怎麼也搞不到,只能使用正則表示式,但是正則表示式我學的也不好,比如視訊連結中有res1的內容:,也有res2的內容:,我寫的正則表示式只能匹配到res2中的東西,按照書上使用匹配符號之類的都行不通,還是學的不精啊。
最後執行爬蟲,還是在cmd中進入到工程目錄,輸入:
等著就行了,建議還是開著日誌,否則出錯了還得自己去找,太麻煩。
下載速度只有40k/s,下了整整一週才把後20頁下完,還僅僅是res2內容的:
中間遇到的無數的bug就不多說了,希望有人能看到這個東西並且有所收穫吧。
以上