Web crawler with Python - 03.豆瓣電影TOP250(轉)

作者:xlzd

鏈接:https://zhuanlan.zhihu.com/p/20423182

來源:知乎

著作權歸作者所有舌剂。商業(yè)轉載請聯(lián)系作者獲得授權济锄,非商業(yè)轉載請注明出處。

開發(fā)環(huán)境已經搭建完成霍转,那么讓我們正式開始第一個爬蟲程序吧荐绝,今天,我們的目標是——豆瓣電影TOP250避消。

和完成其他代碼一樣低滩,編寫爬蟲之前,我們需要先思考爬蟲需要干什么岩喷、目標網(wǎng)站有什么特點恕沫,以及根據(jù)目標網(wǎng)站的數(shù)據(jù)量和數(shù)據(jù)特點選擇合適的架構。編寫爬蟲之前纱意,推薦使用Chrome的開發(fā)者工具來觀察網(wǎng)頁結構婶溯。在OS X上,通過"option+command+i"可以打開Chrome的開發(fā)者工具,在Windows和Linux迄委,對應的快捷鍵是"F12"褐筛。效果如下:

OK,可以看出叙身,這個頁面其實有一個列表渔扎,其中放著25條電源信息。我們選中某一條電影信轿,右鍵選擇檢查即可查看選中條目的HTML結構晃痴。如下圖所示:

到這一步,我們已經得到的信息有如下:

每頁有25條電影财忽,共有10頁倘核。

電影列表在頁面上的位置為一個class屬性為grid_view的ol標簽中。

每條電影信息放在這個ol標簽的一個li標簽里即彪。

到這一步笤虫,我們可以開始寫代碼了。先完成下載網(wǎng)頁源碼的代碼吧祖凫,這里我們使用requests庫:

#!/usr/bin/env python# encoding=utf-8importrequestsDOWNLOAD_URL='http://movie.douban.com/top250'defdownload_page(url):data=requests.get(url).contentreturndatadefmain():printdownload_page(DOWNLOAD_URL)if__name__=='__main__':main()

先來簡單測試一下,沒想到運行之后得到的結果是:

403 Forbidden

403 Forbidden


dae

產生403的原因酬凳,一般可能是因為需要登錄的網(wǎng)站沒有登錄或者被服務器認為是爬蟲而拒絕訪問惠况,這里很顯然屬于第二種情況。一般宁仔,瀏覽器在向服務器發(fā)送請求的時候稠屠,會有一個請求頭——User-Agent,它用來標識瀏覽器的類型.當我們使用requests來發(fā)送請求的時候翎苫,默認的User-Agent是python-requests/2.8.1(后面的數(shù)字可能不同权埠,表示版本號)。那么煎谍,我們試試看如果將User-Agent偽裝成瀏覽器的攘蔽,會不會解決這個問題呢?

#!/usr/bin/env python# encoding=utf-8importrequestsDOWNLOAD_URL='http://movie.douban.com/top250/'defdownload_page(url):headers={'User-Agent':'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/47.0.2526.80 Safari/537.36'}data=requests.get(url,headers=headers).contentreturndatadefmain():printdownload_page(DOWNLOAD_URL)if__name__=='__main__':main()

上面的代碼中呐粘,我們通過手動指定User-Agent為Chrome瀏覽器满俗,再此訪問就得到了真實的網(wǎng)頁源碼。服務器通過校驗請求的U-A來識別爬蟲作岖,這算是最簡單的一種反爬蟲機制了唆垃,通過模擬瀏覽器的U-A,能夠很輕松地繞過這個問題痘儡。

當我們拿到網(wǎng)頁源碼之后辕万,就需要解析HTML源碼了。這里,我們使用BeautifulSoup來搞定這件事渐尿。在使用之前醉途,你需要通過運行pip install beautifulsoup4來安裝BeautifulSoup。

使用BeautifulSoup解析網(wǎng)頁的大致過程如下:

1. from bs4 import BeautifulSoup2.3. def parse_html(html):4.5.? ? soup = BeautifulSoup(html)6.7.? ? movie_list_soup = soup.find('ol', attrs={'class': 'grid_view'})8.9.? ? for movie_li in movie_list_soup.find_all('li'):10.11.? ? ? ? detail = movie_li.find('div', attrs={'class': 'hd'})12.? ? ? ? movie_name = detail.find('span', attrs={'class': 'title'}).getText()13.14.? ? ? ? print movie_name

我將詳細解釋這段代碼:import用來導入BeautifulSoup涡戳,這很容易理解结蟋。接著我們定義了函數(shù)parse_html,它接受html源碼作為輸入渔彰,并將這個網(wǎng)頁中的電影名稱打印到控制臺嵌屎。第5行我們創(chuàng)建了一個BeautifulSoup對象(這樣的創(chuàng)建方式會產生一個warning,我們下一節(jié)再聊這個問題)恍涂,然后緊接著在第7行使用剛剛創(chuàng)建的對象搜索這篇html文檔中查找那個class為grid_view的ol標簽(上面分析的第2步)宝惰,接著通過find_all方法,我們得到了電影的集合再沧,通過對它迭代取出每一個電影的名字尼夺,打印出來。至于for循環(huán)之間的內容炒瘸,其實就是在解析每個li標簽淤堵。你可以很簡單的在剛才的瀏覽器窗口通過開發(fā)者工具查看li中的網(wǎng)頁結構。

到這一步顷扩,我們已經得到了電影名稱(由于只是演示BeautifulSoup的用法拐邪,這里不詳細取出每條電影的所有信息),剛才提到一共有10頁數(shù)據(jù)隘截,怎么處理翻頁的問題呢扎阶?一般在我們確定內容的前提下,可以直接在代碼中寫死如何跳轉頁面婶芭,但是為了讓我們的爬蟲更像爬蟲东臀,我們讓它找到頁碼導航中的下一頁的鏈接。

還是借助開發(fā)者工具犀农,我們找到了下一頁的鏈接放置在一個span標簽中惰赋,這個span標簽的class為next。具體鏈接則在這個span的a標簽中呵哨,到了最后一頁之后谤逼,這個span中的a標簽消失了,就不需要再翻頁了仇穗。于是流部,根據(jù)這段邏輯,我們將上面parse_html函數(shù)稍作修改:

defparse_html(html):soup=BeautifulSoup(html)movie_list_soup=soup.find('ol',attrs={'class':'grid_view'})movie_name_list=[]formovie_liinmovie_list_soup.find_all('li'):detail=movie_li.find('div',attrs={'class':'hd'})movie_name=detail.find('span',attrs={'class':'title'}).getText()movie_name_list.append(movie_name)next_page=soup.find('span',attrs={'class':'next'}).find('a')ifnext_page:returnmovie_name_list,DOWNLOAD_URL+next_page['href']returnmovie_name_list,None

我們需要在解析html之后取回我們需要的數(shù)據(jù)纹坐,于是將打印變成了返回一個包含電影名的list枝冀,以及下一頁的鏈接,如果到了最后一頁,則返回None果漾。

到這里球切,大部分代碼已經完成了,我們將其組裝成一個完整的程序即可:

importcodecsdefmain():url=DOWNLOAD_URLwithcodecs.open('movies','wb',encoding='utf-8')asfp:whileurl:html=download_page(url)movies,url=parse_html(html)fp.write(u'{movies}\n'.format(movies='\n'.join(movies)))

上面的代碼完成了對程序的拼裝绒障,并將結果輸出到一個文件中吨凑,其中使用了codecs這個包是為了更方便處理中文編碼。當程序運行結束之后户辱,所有的電影名稱就都寫入到了movies這個文件中鸵钝。

小結

這篇博客總結了最簡單的處理反爬蟲機制,以及簡單的BeautifulSoup的使用庐镐,最后完成了將結果寫入到文件中去恩商。麻雀雖小,五臟俱全必逆,這個程序雖然功能簡單,但卻算是一個完整的爬蟲程序了名眉。

接下來,我們將會面臨更加復雜的反爬蟲機制损拢,面對更加復雜的網(wǎng)頁結構,以及會使用數(shù)據(jù)庫來持久化存儲爬取結果。

完整的代碼如下:

#!/usr/bin/env python# encoding=utf-8"""爬取豆瓣電影TOP250 - 完整示例代碼"""importcodecsimportrequestsfrombs4importBeautifulSoupDOWNLOAD_URL='http://movie.douban.com/top250/'defdownload_page(url):returnrequests.get(url,headers={'User-Agent':'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/47.0.2526.80 Safari/537.36'}).contentdefparse_html(html):soup=BeautifulSoup(html)movie_list_soup=soup.find('ol',attrs={'class':'grid_view'})movie_name_list=[]formovie_liinmovie_list_soup.find_all('li'):detail=movie_li.find('div',attrs={'class':'hd'})movie_name=detail.find('span',attrs={'class':'title'}).getText()movie_name_list.append(movie_name)next_page=soup.find('span',attrs={'class':'next'}).find('a')ifnext_page:returnmovie_name_list,DOWNLOAD_URL+next_page['href']returnmovie_name_list,Nonedefmain():url=DOWNLOAD_URLwithcodecs.open('movies','wb',encoding='utf-8')asfp:whileurl:html=download_page(url)movies,url=parse_html(html)fp.write(u'{movies}\n'.format(movies='\n'.join(movies)))if__name__=='__main__':main()

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末隧膏,一起剝皮案震驚了整個濱河市嚷那,隨后出現(xiàn)的幾起案子胞枕,更是在濱河造成了極大的恐慌魏宽,老刑警劉巖,帶你破解...
    沈念sama閱讀 206,126評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件派桩,死亡現(xiàn)場離奇詭異,居然都是意外死亡铆惑,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,254評論 2 382
  • 文/潘曉璐 我一進店門员魏,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人受裹,你說我怎么就攤上這事∶奕模” “怎么了?”我有些...
    開封第一講書人閱讀 152,445評論 0 341
  • 文/不壞的土叔 我叫張陵砰盐,是天一觀的道長坑律。 經常有香客問我岩梳,道長晃择,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 55,185評論 1 278
  • 正文 為了忘掉前任列疗,我火速辦了婚禮,結果婚禮上抵栈,老公的妹妹穿的比我還像新娘。我一直安慰自己古劲,他們只是感情好,可當我...
    茶點故事閱讀 64,178評論 5 371
  • 文/花漫 我一把揭開白布产艾。 她就那樣靜靜地躺著滑绒,像睡著了一般。 火紅的嫁衣襯著肌膚如雪疑故。 梳的紋絲不亂的頭發(fā)上杠览,一...
    開封第一講書人閱讀 48,970評論 1 284
  • 那天纵势,我揣著相機與錄音误续,去河邊找鬼。 笑死蹋嵌,一個胖子當著我的面吹牛葫隙,可吹牛的內容都是我干的栽烂。 我是一名探鬼主播恋脚,決...
    沈念sama閱讀 38,276評論 3 399
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼怀喉!你這毒婦竟也來了?” 一聲冷哼從身側響起躬拢,我...
    開封第一講書人閱讀 36,927評論 0 259
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎聊闯,沒想到半個月后米诉,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體菱蔬,經...
    沈念sama閱讀 43,400評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡史侣,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 35,883評論 2 323
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了惊橱。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 37,997評論 1 333
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖宙枷,靈堂內的尸體忽然破棺而出掉房,到底是詐尸還是另有隱情慰丛,我是刑警寧澤,帶...
    沈念sama閱讀 33,646評論 4 322
  • 正文 年R本政府宣布诅病,位于F島的核電站粥烁,受9級特大地震影響蝇棉,放射性物質發(fā)生泄漏讨阻。R本人自食惡果不足惜篡殷,卻給世界環(huán)境...
    茶點故事閱讀 39,213評論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望板辽。 院中可真熱鬧,春花似錦劲弦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,204評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽贸毕。三九已至,卻和暖如春夜赵,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背寇僧。 一陣腳步聲響...
    開封第一講書人閱讀 31,423評論 1 260
  • 我被黑心中介騙來泰國打工嘁傀, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留兴蒸,地道東北人。 一個月前我還...
    沈念sama閱讀 45,423評論 2 352
  • 正文 我出身青樓细办,卻偏偏與公主長得像,于是被迫代替她去往敵國和親笑撞。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 42,722評論 2 345

推薦閱讀更多精彩內容