本文希望達到以下目標:
- 簡要介紹Scarpy
- 使用Scarpy抓取豆瓣電影
我們正式講scrapy框架爬蟲,並用豆瓣來試試手,url:http://movie.douban.com/top250
首先先要回答一個問題。問:把網站裝進爬蟲裏,總共分幾步?
答案很簡單,四步:
- 新建項目 (Project):新建一個新的爬蟲項目
- 明確目標(Items):明確你想要抓取的目標
- 製作爬蟲(Spider):製作爬蟲開始爬取網頁
- 存儲內容(Pipeline):設計管道存儲爬取內容
好的,基本流程既然確定了,那接下來就一步一步的完成就可以了。
1.新建項目(Project)
在空目錄下按住Shift鍵右擊,選擇“在此處打開命令窗口”,輸入一下命令:
<span style="font-size:14px;">scrapy startproject douban</span>
其中,douban爲項目名稱。
可以看到將會創建一個douban文件夾,目錄結構如下:
douban/
scrapy.cfg
douban/
__init__.py
items.py
pipelines.py
settings.py
spiders/
__init__.py
...</span>
我們用pycharm打開該項目,具體看一下:
下面來簡單介紹一下各個文件的作用:
- scrapy.cfg:項目的配置文件
- douban/:項目的Python模塊,將會從這裏引用代碼
- douban/items.py:項目的items文件
- douban/pipelines.py:項目的pipelines文件
- douban/settings.py:項目的設置文件
- douban/spiders/:存儲爬蟲的目錄
2.明確目標(Item)
在Scrapy中,items是用來加載抓取內容的容器,提供了一些額外的保護減少錯誤。
一般來說,item可以用scrapy.item.Item類來創建,並且用scrapy.item.Field對象來定義屬性。
接下來,我們開始來構建item模型(model)。
首先,我們想要的內容有:
- 電影名稱(name)
- 電影描述(movieInfo)
- 電影評分(star)
- 格言(quote)
修改douban目錄下的items.py文件,在原本的class後面添加我們自己的class。
因爲要抓豆瓣網站的內容,所以我們可以將其命名爲DoubanItem:
# -*- coding: utf-8 -*-
# Define here the models for your scraped items
#
# See documentation in:
# http://doc.scrapy.org/en/latest/topics/items.html
from scrapy import Item, Field
class DoubanItem(Item):
# define the fields for your item here like:
# name = scrapy.Field()
title = Field()
movieInfo = Field()
star = Field()
quote = Field()
# -*- coding: utf-8 -*-
# Define here the models for your scraped items
#
# See documentation in:
# http://doc.scrapy.org/en/latest/topics/items.html
from scrapy import Item, Field
class DoubanItem(Item):
# define the fields for your item here like:
# name = scrapy.Field()
title = Field()
movieInfo = Field()
star = Field()
quote = Field()
3.製作爬蟲(Spider)
製作爬蟲,總體分兩步:先爬再取。
也就是說,首先你要獲取整個網頁的所有內容,然後再取出其中對你有用的部分。
3.1爬
Spider是用戶自己編寫的類,用來從一個域(或域組)中抓取信息。
他們定義了用於下載的URL列表、跟蹤鏈接的方案、解析網頁內容的方式,以此來提取items。
要建立一個Spider,你必須用scrapy.spider.BaseSpider創建一個子類,並確定三個強制的屬性:
- name:爬蟲的識別名稱,必須是唯一的,在不同的爬蟲中你必須定義不同的名字。
- start_urls:爬取的URL列表。爬蟲從這裏開始抓取數據,所以,第一次下載的數據將會從這些urls開始。其他子URL將會從這些起始URL中繼承性生成。
- parse():解析的方法,調用的時候傳入從每一個URL傳回的Response對象作爲唯一參數,負責解析並匹配抓取的數據(解析爲item),跟蹤更多的URL。
# -*- coding: utf-8 -*-
from scrapy.spiders import CrawlSpider
class Douban(CrawlSpider):
name = "douban"
start_urls = ['http://movie.douban.com/top250']
def parse(self,response):
print response.body
# -*- coding: utf-8 -*-
from scrapy.spiders import CrawlSpider
class Douban(CrawlSpider):
name = "douban"
start_urls = ['http://movie.douban.com/top250']
def parse(self,response):
print response.body
然後運行一下看看,在douban目錄下按住shift右擊,在此處打開命令窗口,輸入:
scrapy crawl douban
運行結果如圖:
from scrapy import cmdline
cmdline.execute("scrapy crawl douban".split())
from scrapy import cmdline
cmdline.execute("scrapy crawl douban".split())
在pycharm裏運行main.py,可以得到相同的結果。
USER_AGENT = 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_8_3) AppleWebKit/536.5 (KHTML, like Gecko) Chrome/19.0.1084.54 Safari/536.5'
運行看一下結果:
3.1取
selector = Selector(response)
Movies = selector.xpath('//div[@class="info"]')
for eachMoive in Movies:
title = eachMoive.xpath('div[@class="hd"]/a/span/text()').extract()
movieInfo = eachMoive.xpath('div[@class="bd"]/p/text()').extract()
star = eachMoive.xpath('div[@class="bd"]/div[@class="star"]/span[@class="rating_num"]/text()').extract()[0]
quote = eachMoive.xpath('div[@class="bd"]/p[@class="quote"]/span/text()').extract()
這裏面有兩個小問題,大家自己做時可以發現,title包括兩個,而quote有的電影沒有,所以我們調整一下,完整代碼如下:
# -*- coding: utf-8 -*-
from scrapy.spiders import CrawlSpider
from scrapy.selector import Selector
from douban.items import DoubanItem
class Douban(CrawlSpider):
name = "douban"
start_urls = ['http://movie.douban.com/top250']
def parse(self,response):
#print response.body
item = DoubanItem()
selector = Selector(response)
#print selector
Movies = selector.xpath('//div[@class="info"]')
#print Movies
for eachMoive in Movies:
title = eachMoive.xpath('div[@class="hd"]/a/span/text()').extract()
# 把兩個名稱合起來
fullTitle = ''
for each in title:
fullTitle += each
movieInfo = eachMoive.xpath('div[@class="bd"]/p/text()').extract()
star = eachMoive.xpath('div[@class="bd"]/div[@class="star"]/span[@class="rating_num"]/text()').extract()[0]
quote = eachMoive.xpath('div[@class="bd"]/p[@class="quote"]/span/text()').extract()
# quote可能爲空,因此需要先進行判斷
if quote:
quote = quote[0]
else:
quote = ''
print fullTitle
print movieInfo
print star
print quote
運行看一下結果:
這裏我們要引入Request, from scrapy.http import Request
代碼如下:nextLink = selector.xpath('//span[@class="next"]/link/@href').extract()
# 第10頁是最後一頁,沒有下一頁的鏈接
if nextLink:
nextLink = nextLink[0]
print nextLink
url = 'http://movie.douban.com/top250'
yield Request(self.url + nextLink, callback=self.parse)
# -*- coding: utf-8 -*-
from scrapy.spiders import CrawlSpider
from scrapy.selector import Selector
from douban.items import DoubanItem
from scrapy.http import Request
class Douban(CrawlSpider):
name = "douban"
start_urls = ['http://movie.douban.com/top250']
url = 'http://movie.douban.com/top250'
def parse(self,response):
#print response.body
item = DoubanItem()
selector = Selector(response)
#print selector
Movies = selector.xpath('//div[@class="info"]')
#print Movies
for eachMoive in Movies:
title = eachMoive.xpath('div[@class="hd"]/a/span/text()').extract()
# 把兩個名稱合起來
fullTitle = ''
for each in title:
fullTitle += each
movieInfo = eachMoive.xpath('div[@class="bd"]/p/text()').extract()
star = eachMoive.xpath('div[@class="bd"]/div[@class="star"]/span[@class="rating_num"]/text()').extract()[0]
quote = eachMoive.xpath('div[@class="bd"]/p[@class="quote"]/span/text()').extract()
# quote可能爲空,因此需要先進行判斷
if quote:
quote = quote[0]
else:
quote = ''
#print fullTitle
#print movieInfo
#print star
#print quote
item['title'] = fullTitle
item['movieInfo'] = ';'.join(movieInfo)
item['star'] = star
item['quote'] = quote
yield item
nextLink = selector.xpath('//span[@class="next"]/link/@href').extract()
# 第10頁是最後一頁,沒有下一頁的鏈接
if nextLink:
nextLink = nextLink[0]
print nextLink
yield Request(self.url + nextLink, callback=self.parse)
4.存儲內容(Pipeline)
保存信息的最簡單的方法是通過Feed exports,主要有四種:JSON,JSON lines,CSV,XML。
我們將結果用最常用的JSON導出,命令如下:
scrapy crawl douban -o items.json -t json
-o 後面是導出文件名,-t 後面是導出類型。
然後來看一下導出的結果,用文本編輯器打開json文件即可看的不是很舒服,要是能直接看到內容就好了,我們試試保存成CSV,然後用EXCEL打開即可。
scrapy crawl douban -o items.csv -t csv
FEED_URI = u'file:///E:/douban/douban.csv'
FEED_FORMAT = 'CSV'
如果你想用抓取的items做更復雜的事情,你可以寫一個 Item Pipeline(條目管道)。
後面我們也會有涉及的,敬請期待!
小夥伴們,自己動手試試吧!
相關學習文章:
1、簡書《Python爬蟲(六)--Scrapy框架學習》http://www.jianshu.com/p/078ad2067419
2、汪海實驗室http://blog.csdn.net/pleasecallmewhy/article/details/19642329
3、極客學院《scrapy初探》http://www.jikexueyuan.com/course/1287.html