scrapy學習筆記——Python網絡爬蟲利器(入門教程)

    因爲工作原因要到網絡上抓取一些新聞數據來分析,實在不想自己手動解析鏈接頁面,再重新requests,還要處理多頁的問題,一直聽說scrapy是個很不錯的工具,但一直都沒有花心思學一下,最近幾天看了一下,並自己動手編了個程序試了試,確實非常方便。

    順便說一句,網上很多人發的文章都是翻譯的官方的Tutorial,官方的Tutorial是挺不錯,但是用到的功能都很基本,抓單個網頁分析的話看一下還可以,抓多個網頁的功能根本學不到要,下面以從新浪新聞中抓取文章爲例說明,也是我本人學習的一個過程。

一、頁面分析

比如想要搜關於“國慶放假”的新聞,搜出來的結果如下圖所示:

我是想把所有搜出來的新聞打開後抓取其標題、新聞來源、發佈時間、新聞正文,然後把相關的內容存儲起來準備分析處理,當然不能只抓取搜出來的第一頁,而是要把所有的“下一頁”遍歷一遍,再抓取。

二、生成一個scrapy項目

scrapy startproject sinanews

會生成一個sinanews的目錄,然後其中會包含一些必須的文件,網上介紹這些文件幹什麼用的文章挺多,就不再重複了,只說實現上述功能我們要修改的文件。

三、定義Item

要存儲下來的數據都要存儲在Item中,其實它就是一個特殊的dict,在startproject的時候已經生成了一個基本的模板,你只需要類的定義中加入一些你想要存儲的數據結構並把它們定義爲Field()即可。修改items.py文件:

# Define here the models for your scraped items
#
# See documentation in:
# http://doc.scrapy.org/topics/items.html

from scrapy.item import Item, Field

class SinanewsScrapyItem(Item):
    # define the fields for your item here like:
    # name = Field()
    title = Field()
    source = Field()
    public_time = Field()
    text = Field()

四、定義Spider

Spider是抓取的主力軍,這個類最爲關鍵,這個類相關的文件並沒有自動生成,需要自己手動新建一個,取名爲sinanews_spider.py:

#  -*- coding=utf8 -*-
from scrapy.contrib.spiders import CrawlSpider, Rule
from scrapy.contrib.linkextractors import LinkExtractor

from sinanews_scrapy.items import SinanewsScrapyItem

class SinanewsSpider(CrawlSpider):
    name = 'sinanews'
    allowed_domains=['sina.com.cn']
    start_urls = ['http://search.sina.com.cn/?q=%B9%FA%C7%EC%B7%C5%BC%D9&c=news&from=index']

    rules = [Rule(LinkExtractor(allow = '/.+/\d+.shtml',
        deny = '/171826152112.shtml'),
        'parse_news'),
        Rule(LinkExtractor(restrict_xpaths = u"//a[@title='下一頁']"), 
            follow=True)]

    def parse_news(self, response):
        news = SinanewsScrapyItem()
        temp_dict = {}

        temp = response.xpath("//h1[@id='artibodyTitle']//text()").extract()
        news['title'] = temp[0] if temp else ''

        temp = response.xpath("//span[@id='media_name']//text()").extract()
        news['source'] = temp[0] if temp else ''
        
        
        temp =  response.xpath("//span[@id='pub_date']//text()").extract()
        news['public_time'] = temp[0] if temp else ''

        temp = response.xpath("//div[@id='artibody']//p//text()").extract()
        news['text'] = '\n'.join(temp) if temp else ''

        return news

  1. 第7行類的定義繼承自功能更強大的CrawlSpider,而不是Tutorial裏講的Spider。
  2. 第8行定義這個Spider的name,這個name作爲scrapy crawl XXX的參數在正式進行抓取的時候會用到。
  3. 第12行比較關鍵,這裏定義了一組規則,是作爲跟蹤鏈接的規則,符合規則的網頁鏈接會被跟蹤抓取。這裏定義了兩個規則組成一個list:一個是跟蹤新聞相關的網頁,找出這些網頁鏈接網址的規律並用正則表達式定義allow,那個deny是網頁底部有個反淫穢之類的不需要的頁面,第三個參數是處理這個頁面的回調函數名稱;另一個規則是模擬點擊“下一頁”然後再進行抓取,找到“下一頁”這個鏈接用xpath語句定義之,然後跟一個參數follow=True。
  4. 第16行這個follow=True讓人感覺設計得真是漂亮,開始我在看文檔一直想怎麼寫另外一個回調函數,然後又怎麼遞歸調用重新啓動一次呢,後來在github上找到了geekan抓取douban的一個例子,原來搞定“下一頁”如此簡單啊,不得不佩服設計者的用心。很多網上給的例子都是基本老版本scrapy的(我用0.24.4),還要寫一個回調函數單獨處理,儘管單獨處理語句也沒有幾句,但比起這種處理方式來講還是太麻煩了。
  5. 第18行往後已經沒有什麼技術含量了,無非是找到你想要抓取的東西在html文件中的位置,然後用合適的xpath表達式把它搜出來,然後逐一賦值給Item類的對應鍵值,然後將這個對象返回。

五、爬、爬、爬

scrapy crawl sinanews -o sinanews.json

輸出的sinanews.json是個標準的json格式的數據,可以用官方的json庫進行讀取。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章