Python利用Scrapy框架爬取豆瓣電影示例
本文實例講述了Python利用Scrapy框架爬取豆瓣電影。分享給大家供大家參考,具體如下:
1、概念
Scrapy是一個為了爬取網站數據,提取結構性數據而編寫的應用框架。 可以應用在包括數據挖掘,信息處理或存儲歷史數據等一系列的程序中。
通過Python包管理工具可以很便捷地對scrapy進行安裝,如果在安裝中報錯提示缺少依賴的包,那就通過pip安裝所缺的包
pip install scrapy
scrapy的組成結構如下圖所示
引擎Scrapy Engine,用于中轉調度其他部分的信號和數據傳遞
調度器Scheduler,一個存儲Request的隊列,引擎將請求的連接發(fā)送給Scheduler,它將請求進行排隊,但引擎需要時再將隊列中的第一個請求發(fā)送給引擎
下載器Downloader,引擎將請求Request鏈接發(fā)送給Downloader之后它就從互聯網上下載相應的數據,并將返回的數據Responses交給引擎
爬蟲Spiders,引擎將下載的Responses數據交給Spiders進行解析,提取我們需要的網頁信息。如果在解析中發(fā)現有新的所需要的url連接,Spiders會將鏈接交給引擎存入調度器
管道Item Pipline,爬蟲會將頁面中的數據通過引擎交給管道做進一步處理,進行過濾、存儲等操作
下載中間件Downloader Middlewares,自定義擴展組件,用于在請求頁面時封裝代理、http請求頭等操作
爬蟲中間件Spider Middlewares,用于對進入Spiders的Responses和出去的Requests等數據作一些修改
scrapy的工作流程:首先我們將入口url交給spider爬蟲,爬蟲通過引擎將url放入調度器,經調度器排隊之后返回第一個請求Request,引擎再將請求轉交給下載器進行下載,下載好的數據交給爬蟲進行爬取,爬取的數據一部分是我們需要的數據交給管道進行數據清洗和存儲,還有一部分是新的url連接會再次交給調度器,之后再循環(huán)進行數據爬取
2、新建Scrapy項目
首先在存放項目的文件夾內打開命令行,在命令行下輸入scrapy startproject 項目名稱,就會在當前文件夾自動創(chuàng)建項目所需的python文件,例如創(chuàng)建一個爬取豆瓣電影的項目douban,其目錄結構如下:
Db_Project/ scrapy.cfg --項目的配置文件 douban/ --該項目的python模塊目錄,在其中編寫python代碼 __init__.py --python包的初始化文件 items.py --用于定義item數據結構 pipelines.py --項目中的pipelines文件 settings.py --定義項目的全局設置,例如下載延遲、并發(fā)量 spiders/ --存放爬蟲代碼的包目錄 __init__.py ...
之后進入spiders目錄下輸入scrapy genspider 爬蟲名 域名,就會生成爬蟲文件douban.py文件,用于之后定義爬蟲的爬取邏輯和正則表達式等內容
scrapy genspider douban movie.douban.com
3、定義數據
要爬取的豆瓣電影網址為 https://movie.douban.com/top250,其中的每個電影如下
我們要爬取其中的序號、名稱、介紹、星級、評論數、描述這幾個關鍵信息,因此需要在管道文件items.py中先定義這幾個對象,類似于ORM,通過scrapy.Field()方法為每個字段定義一個數據類型
import scrapy class DoubanItem(scrapy.Item): ranking = scrapy.Field() # 排名 name = scrapy.Field() # 電影名 introduce = scrapy.Field() # 簡介 star = scrapy.Field() # 星級 comments = scrapy.Field() # 評論數 describe = scrapy.Field() # 描述
4、數據爬取
打開之前在spiders文件夾下創(chuàng)建的爬蟲文件movie.py如下所示,以及自動創(chuàng)建了三個變量和一個方法,在parse方法中進行返回數據response的處理,我們需要在start_urls提供爬蟲的入口地址。注意爬蟲會自動過濾掉allowed_domains之外的域名,因此需要注意這個變量的賦值
# spiders/movie.py import scrapy class MovieSpider(scrapy.Spider): # 爬蟲名 name = 'movie' # 允許爬取的域名 allowed_domains = ['movie.douban.com'] # 入口url start_urls = ['https://movie.douban.com/top250'] def parse(self, response): pass
在進行數據爬取之前首先要設置一些網絡代理,在settings.py文件內找到USER_AGENT變量修改如下:
USER_AGENT = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:70.0) Gecko/20100101 Firefox/70.0'
可以在命令行通過如下命令啟動名為douban的爬蟲:scrapy crawl douban,也可以編寫一個啟動文件run.py文件如下,運行即可
from scrapy import cmdline cmdline.execute('scrapy crawl movie'.split())
接下來要對爬取到的數據進行過濾,通過Xpath規(guī)則可以使我們便捷地選中網頁中的指定元素,如下圖所示,每個電影條目都包裹在<ol class="grid_view">下的一個<li>標簽,因此通過xpath://ol[@class='grid_view']/li 就選中了本頁面所有的電影條目??梢酝ㄟ^谷歌瀏覽器的Xpath插件或者火狐瀏覽器的ChroPath獲得xpath值,在瀏覽器右鍵查看元素,彈出如下圖所示的開發(fā)者工具,其中最右邊就是ChroPath插件,它直觀地顯示了元素的Xpath值: //div[@id='wrapper']//li
爬蟲response對象的xpath()方法可以直接處理xpath規(guī)則字符串并返回對應的頁面內容,這些內容都是選擇器對象Selector,可以進一步作細化的內容選取,通過xpath選擇出其中的電影名字、簡介、評價、星級等內容,即之前在items.py文件中所定義的數據結構DoubanItem。循環(huán)遍歷每個電影列表從其中爬取到準確的電影信息,并保存為DoubanItem對象item,最后通過yield將item對象從Spiders返回到Item管道。
爬蟲除了從頁面提取Item數據之外還會爬取url鏈接從而形成下一頁的Request請求,如下圖所示為豆瓣頁面底部的下一頁信息,第二頁的參數為"?start=25&filter=",與網站地址https://movie.douban.com/top250拼接起來就可以得到下一頁面的地址。和上面一樣通過xpath提取該內容,如果不為空,則拼接得到的Request請求yield提交給調度器
最終的爬蟲movie.py文件如下
# -*- coding: utf-8 -*- import scrapy from items import DoubanItem class MovieSpider(scrapy.Spider): # 爬蟲名 name = 'movie' # 爬取網站的域名 allowed_domains = ['movie.douban.com'] # 入口url start_urls = ['https://movie.douban.com/top250'] def parse(self, response): # 首先抓取電影列表 movie_list = response.xpath("http://ol[@class='grid_view']/li") for selector in movie_list: # 遍歷每個電影列表,從其中精準抓取所需要的信息并保存為item對象 item = DoubanItem() item['ranking'] = selector.xpath(".//div[@class='pic']/em/text()").extract_first() item['name'] = selector.xpath(".//span[@class='title']/text()").extract_first() text = selector.xpath(".//div[@class='bd']/p[1]/text()").extract() intro = "" for s in text: # 將簡介放到一個字符串 intro += "".join(s.split()) # 去掉空格 item['introduce'] = intro item['star'] = selector.css('.rating_num::text').extract_first() item['comments'] = selector.xpath(".//div[@class='star']/span[4]/text()").extract_first() item['describe'] = selector.xpath(".//span[@class='inq']/text()").extract_first() # print(item) yield item # 將結果item對象返回給Item管道 # 爬取網頁中的下一個頁面url信息 next_link = response.xpath("http://span[@class='next']/a[1]/@href").extract_first() if next_link: next_link = "https://movie.douban.com/top250" + next_link print(next_link) # 將Request請求提交給調度器 yield scrapy.Request(next_link, callback=self.parse)
xpath選擇器
/表示從當前位置的下一級目錄進行尋找,//表示從當前位置的任意一級子目錄進行尋找,
默認從根目錄開始查找,. 代表從當前目錄開始查找,@后跟標簽屬性,text()函數代表取出文字內容
//div[@id='wrapper']//li 代表先從根目錄開始查找id為wrapper的div標簽,然后取出其下的所有l(wèi)i標簽
.//div[@class='pic']/em[1]/text() 代表從當前選擇器目錄開始查找所有class為pic的div之下的第一個em標簽,取出文字內容
string(//div[@id='endText']/p[position()>1]) 代表選取id為endText的div下第二個p標簽之后的所有文字內容
/bookstore/book[last()-2] 選取屬于 bookstore 子元素的倒數第3個 book 元素。
CSS選擇器
還可以使用css選擇器來選擇頁面內的元素,其通過CSS偽類的方式表達選擇的元素,使用如下
# 選擇類名為left的div下的p標簽中的文字 response.css('div.left p::text').extract_first() # 選取id為tag的元素下類名為star元素中的文字 response.css('#tag .star::text').extract_first()
5、數據保存
在運行爬蟲文件時通過參數-o指定文件保存的位置即可,可以根據文件后綴名選擇保存為json或者csv文件,例如
scrapy crawl movie -o data.csv
還可以piplines.py文件中對取得的Item數據作進一步操作從而通過python操作將其保存到數據庫中
6、中間件設置
有時為了應對網站的反爬蟲機制,需要對下載中間件進行一些偽裝設置,包括使用IP代理和代理user-agent方式,在middlewares.py文件中新建一個user_agent類用于為請求頭添加用戶列表,從網上查一些常用的用戶代理放入USER_AGENT_LIST列表,然后通過random函數從中隨機抽取一個作為代理,設置為reques請求頭的User_Agent字段
class user_agent(object): def process_request(self, request, spider): # user agent 列表 USER_AGENT_LIST = [ 'MSIE (MSIE 6.0; X11; Linux; i686) Opera 7.23', 'Opera/9.20 (Macintosh; Intel Mac OS X; U; en)', 'Opera/9.0 (Macintosh; PPC Mac OS X; U; en)', 'iTunes/9.0.3 (Macintosh; U; Intel Mac OS X 10_6_2; en-ca)', 'Mozilla/4.76 [en_jp] (X11; U; SunOS 5.8 sun4u)', 'iTunes/4.2 (Macintosh; U; PPC Mac OS X 10.2)', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv:5.0) Gecko/20100101 Firefox/5.0', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv:9.0) Gecko/20100101 Firefox/9.0', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10.8; rv:16.0) Gecko/20120813 Firefox/16.0', 'Mozilla/4.77 [en] (X11; I; IRIX;64 6.5 IP30)', 'Mozilla/4.8 [en] (X11; U; SunOS; 5.7 sun4u)' ] agent = random.choice(USER_AGENT_LIST) # 從上面列表中隨機抽取一個代理 request.headers['User_Agent'] = agent # 設置請求頭的用戶代理
在settings.py文件內設置開啟下載中間件即取消如下幾行的注釋,注冊代理類user_agent并設置優(yōu)先級,數字越小優(yōu)先級越高
更多關于Python相關內容可查看本站專題:《Python Socket編程技巧總結》、《Python正則表達式用法總結》、《Python數據結構與算法教程》、《Python函數使用技巧總結》、《Python字符串操作技巧匯總》、《Python入門與進階經典教程》及《Python文件與目錄操作技巧匯總》
希望本文所述對大家Python程序設計有所幫助。
相關文章
python爬蟲 基于requests模塊的get請求實現詳解
這篇文章主要介紹了python爬蟲 基于requests模塊的get請求實現詳解,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下2019-08-08利用python實現簡單的循環(huán)購物車功能示例代碼
購物車對我們每位開發(fā)者來說應該都不陌生,下面這篇文章主要給大家介紹了利用python實現簡單的循環(huán)購物車功能的相關資料,文中給出了詳細的示例代碼供大家參考學習,需要的朋友們下面來一起看看吧。2017-07-07局域網內python socket實現windows與linux間的消息傳送
這篇文章主要介紹了局域網內python socket實現windows與linux間的消息傳送的相關知識,非常不錯,具有一定的參考借鑒價值,需要的朋友可以參考下2019-04-04