scrapy抓取學(xué)院新聞報告

接到上方任務(wù)安排,需要使用scrapy來抓取學(xué)院的新聞報告.于是乎,新官上任三把火,對剛學(xué)會爬數(shù)據(jù)的我迫不及待的上手起來.


任務(wù)

抓取四川大學(xué)公共管理學(xué)院官網(wǎng)(http://ggglxy.scu.edu.cn)所有的新聞咨詢.

實驗流程

1.確定抓取目標(biāo).
2.制定抓取規(guī)則.
3.'編寫/調(diào)試'抓取規(guī)則.
4.獲得抓取數(shù)據(jù)

1.確定抓取目標(biāo)

我們這次需要抓取的目標(biāo)為四川大學(xué)公共管理學(xué)院的所有新聞資訊.于是我們需要知道公管學(xué)院官網(wǎng)的布局結(jié)構(gòu).

微信截圖_20170515223045.png

這里我們發(fā)現(xiàn)想要抓到全部的新聞信息,不能直接在官網(wǎng)首頁進(jìn)行抓取,需要點擊"more"進(jìn)入到新聞總欄目里面.

Paste_Image.png

我們看到了具體的新聞欄目,但是這顯然不滿足我們的抓取需求: 當(dāng)前新聞動態(tài)網(wǎng)頁只能抓取新聞的時間,標(biāo)題和URL,但是并不能抓取新聞的內(nèi)容.所以我們想要需要進(jìn)入到新聞詳情頁抓取新聞的具體內(nèi)容.

2.制定抓取規(guī)則

通過第一部分的分析,我們會想到,如果我們要抓取一篇新聞的具體信息,需要從新聞動態(tài)頁面點擊進(jìn)入新聞詳情頁抓取到新聞的具體內(nèi)容.我們點擊一篇新聞嘗試一下

Paste_Image.png

我們發(fā)現(xiàn),我們能夠直接在新聞詳情頁面抓取到我們需要的數(shù)據(jù):標(biāo)題,時間,內(nèi)容.URL.

好,到現(xiàn)在我們清楚抓取一篇新聞的思路了.但是,如何抓取所有的新聞內(nèi)容呢?
這顯然難不到我們.


我們在新聞欄目的最下方能夠看到頁面跳轉(zhuǎn)的按鈕.那么我們可以通過"下一頁"按鈕實現(xiàn)抓取所有的新聞.

那么整理一下思路,我們能夠想到一個顯而易見的抓取規(guī)則:
通過抓取'新聞欄目下'所有的新聞鏈接,并且進(jìn)入到新聞詳情鏈接里面抓取所有的新聞內(nèi)容.

3.'編寫/調(diào)試'抓取規(guī)則

為了讓調(diào)試爬蟲的粒度盡量的小,我將編寫和調(diào)試模塊糅合在一起進(jìn)行.
在爬蟲中,我將實現(xiàn)以下幾個功能點:

1.爬出一頁新聞欄目下的所有新聞鏈接
2.通過爬到的一頁新聞鏈接進(jìn)入到新聞詳情爬取所需要數(shù)據(jù)(主要是新聞內(nèi)容)
3.通過循環(huán)爬取到所有的新聞.

分別對應(yīng)的知識點為:

1.爬出一個頁面下的基礎(chǔ)數(shù)據(jù).
2.通過爬到的數(shù)據(jù)進(jìn)行二次爬取.
3.通過循環(huán)對網(wǎng)頁進(jìn)行所有數(shù)據(jù)的爬取.

話不多說,現(xiàn)在開干.

3.1爬出一頁新聞欄目下的所有新聞鏈接

Paste_Image.png

通過對新聞欄目的源代碼分析,我們發(fā)現(xiàn)所抓數(shù)據(jù)的結(jié)構(gòu)為

Paste_Image.png

那么我們只需要將爬蟲的選擇器定位到(li:newsinfo_box_cf),再進(jìn)行for循環(huán)抓取即可.

編寫代碼
import scrapy

class News2Spider(scrapy.Spider):
    name = "news_info_2"
    start_urls = [
        "http://ggglxy.scu.edu.cn/index.php?c=special&sid=1&page=1",
    ]
        
    def parse(self, response):
        for href in response.xpath("http://div[@class='newsinfo_box cf']"):
            url = response.urljoin(href.xpath("div[@class='news_c fr']/h3/a/@href").extract_first())

測試,通過!

Paste_Image.png

3.2通過爬到的一頁新聞鏈接進(jìn)入到新聞詳情爬取所需要數(shù)據(jù)(主要是新聞內(nèi)容)

現(xiàn)在我獲得了一組URL,現(xiàn)在我需要進(jìn)入到每一個URL中抓取我所需要的標(biāo)題,時間和內(nèi)容,代碼實現(xiàn)也挺簡單,只需要在原有代碼抓到一個URL時進(jìn)入該URL并且抓取相應(yīng)的數(shù)據(jù)即可.所以,我只需要再寫一個進(jìn)入新聞詳情頁的抓取方法,并且使用scapy.request調(diào)用即可.

編寫代碼
#進(jìn)入新聞詳情頁的抓取方法
def parse_dir_contents(self, response):
        item = GgglxyItem()
        item['date'] = response.xpath("http://div[@class='detail_zy_title']/p/text()").extract_first()
        item['href'] = response
        item['title'] = response.xpath("http://div[@class='detail_zy_title']/h1/text()").extract_first()
        data = response.xpath("http://div[@class='detail_zy_c pb30 mb30']")
        item['content'] = data[0].xpath('string(.)').extract()[0]
        yield item

整合進(jìn)原有代碼后,有:

import scrapy
from ggglxy.items import GgglxyItem

class News2Spider(scrapy.Spider):
    name = "news_info_2"
    start_urls = [
        "http://ggglxy.scu.edu.cn/index.php?c=special&sid=1&page=1",
    ]
        
    def parse(self, response):
        for href in response.xpath("http://div[@class='newsinfo_box cf']"):
            url = response.urljoin(href.xpath("div[@class='news_c fr']/h3/a/@href").extract_first())
            #調(diào)用新聞抓取方法
            yield scrapy.Request(url, callback=self.parse_dir_contents)

        
    #進(jìn)入新聞詳情頁的抓取方法                
    def parse_dir_contents(self, response):
            item = GgglxyItem()
            item['date'] = response.xpath("http://div[@class='detail_zy_title']/p/text()").extract_first()
            item['href'] = response
            item['title'] = response.xpath("http://div[@class='detail_zy_title']/h1/text()").extract_first()
            data = response.xpath("http://div[@class='detail_zy_c pb30 mb30']")
            item['content'] = data[0].xpath('string(.)').extract()[0]
            yield item

測試,通過!

Paste_Image.png

這時我們加一個循環(huán):

NEXT_PAGE_NUM = 1 

NEXT_PAGE_NUM = NEXT_PAGE_NUM + 1
        if NEXT_PAGE_NUM<11:
            next_url = 'http://ggglxy.scu.edu.cn/index.php?c=special&sid=1&page=%s' % NEXT_PAGE_NUM
            yield scrapy.Request(next_url, callback=self.parse) 

加入到原本代碼:

import scrapy
from ggglxy.items import GgglxyItem

NEXT_PAGE_NUM = 1


class News2Spider(scrapy.Spider):
    name = "news_info_2"
    start_urls = [
        "http://ggglxy.scu.edu.cn/index.php?c=special&sid=1&page=1",
    ]

    def parse(self, response):
        for href in response.xpath("http://div[@class='newsinfo_box cf']"):
            URL = response.urljoin(href.xpath("div[@class='news_c fr']/h3/a/@href").extract_first())
            yield scrapy.Request(URL, callback=self.parse_dir_contents)
        global NEXT_PAGE_NUM
        NEXT_PAGE_NUM = NEXT_PAGE_NUM + 1
        if NEXT_PAGE_NUM<11:
            next_url = 'http://ggglxy.scu.edu.cn/index.php?c=special&sid=1&page=%s' % NEXT_PAGE_NUM
            yield scrapy.Request(next_url, callback=self.parse) 



    def parse_dir_contents(self, response):
            item = GgglxyItem() 
            item['date'] = response.xpath("http://div[@class='detail_zy_title']/p/text()").extract_first()
            item['href'] = response 
            item['title'] = response.xpath("http://div[@class='detail_zy_title']/h1/text()").extract_first()
            data = response.xpath("http://div[@class='detail_zy_c pb30 mb30']")
            item['content'] = data[0].xpath('string(.)').extract()[0] 
            yield item

測試:

Paste_Image.png

抓到的數(shù)量為191,但是我們看官網(wǎng)發(fā)現(xiàn)有193條新聞,少了兩條.
為啥呢?我們注意到log的error有兩條:
定位問題:原來發(fā)現(xiàn),學(xué)院的新聞欄目還有兩條隱藏的二級欄目:
比如:

Paste_Image.png

對應(yīng)的URL為

Paste_Image.png

URL都長的不一樣,難怪抓不到了!
那么我們還得為這兩條二級欄目的URL設(shè)定專門的規(guī)則,只需要加入判斷是否為二級欄目:

  if URL.find('type') != -1:
      yield scrapy.Request(URL, callback=self.parse)

組裝原函數(shù):

import scrapy
from ggglxy.items import GgglxyItem

NEXT_PAGE_NUM = 1


class News2Spider(scrapy.Spider):
    name = "news_info_2"
    start_urls = [
        "http://ggglxy.scu.edu.cn/index.php?c=special&sid=1&page=1",
    ]

    def parse(self, response):
        for href in response.xpath("http://div[@class='newsinfo_box cf']"):
            URL = response.urljoin(href.xpath("div[@class='news_c fr']/h3/a/@href").extract_first())
            if URL.find('type') != -1:
                yield scrapy.Request(URL, callback=self.parse)
            yield scrapy.Request(URL, callback=self.parse_dir_contents)
        global NEXT_PAGE_NUM
        NEXT_PAGE_NUM = NEXT_PAGE_NUM + 1
        if NEXT_PAGE_NUM<11:
            next_url = 'http://ggglxy.scu.edu.cn/index.php?c=special&sid=1&page=%s' % NEXT_PAGE_NUM
            yield scrapy.Request(next_url, callback=self.parse) 



    def parse_dir_contents(self, response):
            item = GgglxyItem() 
            item['date'] = response.xpath("http://div[@class='detail_zy_title']/p/text()").extract_first()
            item['href'] = response 
            item['title'] = response.xpath("http://div[@class='detail_zy_title']/h1/text()").extract_first()
            data = response.xpath("http://div[@class='detail_zy_c pb30 mb30']")
            item['content'] = data[0].xpath('string(.)').extract()[0] 
            yield item

測試:

Paste_Image.png

我們發(fā)現(xiàn),抓取的數(shù)據(jù)由以前的193條增加到了238條,log里面也沒有error了,說明我們的抓取規(guī)則OK!

4.獲得抓取數(shù)據(jù)

     scrapy crawl news_info_2 -o 0016.json

相關(guān)推薦
scrapy通過scrapyinghub實現(xiàn)24小時爬蟲托管爬取
scrapy抓取成都房價信息

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容