接到上方任務(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).

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

我們看到了具體的新聞欄目,但是這顯然不滿足我們的抓取需求: 當(dāng)前新聞動態(tài)網(wǎng)頁只能抓取新聞的時間,標(biāo)題和URL,但是并不能抓取新聞的內(nèi)容.所以我們想要需要進(jìn)入到新聞詳情頁抓取新聞的具體內(nèi)容.
2.制定抓取規(guī)則
通過第一部分的分析,我們會想到,如果我們要抓取一篇新聞的具體信息,需要從新聞動態(tài)頁面點擊進(jìn)入新聞詳情頁抓取到新聞的具體內(nèi)容.我們點擊一篇新聞嘗試一下

我們發(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爬出一頁新聞欄目下的所有新聞鏈接

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

那么我們只需要將爬蟲的選擇器定位到(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())
測試,通過!

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
測試,通過!

這時我們加一個循環(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
測試:

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

對應(yīng)的URL為

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
測試:

我們發(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抓取成都房價信息