抓取四川大學公共管理學院官網(http://ggglxy.scu.edu.cn)全部的新聞諮詢.php
1.肯定抓取目標.
2.制定抓取規則.
3.'編寫/調試'抓取規則.
4.得到抓取數據python
咱們此次須要抓取的目標爲四川大學公共管理學院的全部新聞資訊.因而咱們須要知道公管學院官網的佈局結構.json
這裏咱們發現想要抓到所有的新聞信息,不能直接在官網首頁進行抓取,須要點擊"more"進入到新聞總欄目裏面.ruby
咱們看到了具體的新聞欄目,可是這顯然不知足咱們的抓取需求: 當前新聞動態網頁只能抓取新聞的時間,標題和URL,可是並不能抓取新聞的內容.因此咱們想要須要進入到新聞詳情頁抓取新聞的具體內容.微信
經過第一部分的分析,咱們會想到,若是咱們要抓取一篇新聞的具體信息,須要重新聞動態頁面點擊進入新聞詳情頁抓取到新聞的具體內容.咱們點擊一篇新聞嘗試一下scrapy
咱們發現,咱們可以直接在新聞詳情頁面抓取到咱們須要的數據:標題,時間,內容.URL.ide
好,到如今咱們清楚抓取一篇新聞的思路了.可是,如何抓取全部的新聞內容呢?
這顯然難不到咱們.函數
咱們在新聞欄目的最下方可以看到頁面跳轉的按鈕.那麼咱們能夠經過"下一頁"按鈕實現抓取全部的新聞.佈局
那麼整理一下思路,咱們可以想到一個顯而易見的抓取規則:
經過抓取'新聞欄目下'全部的新聞連接,而且進入到新聞詳情連接裏面抓取全部的新聞內容.學習
爲了讓調試爬蟲的粒度儘可能的小,我將編寫和調試模塊糅合在一塊兒進行.
在爬蟲中,我將實現如下幾個功能點:
1.爬出一頁新聞欄目下的全部新聞連接
2.經過爬到的一頁新聞連接進入到新聞詳情爬取所須要數據(主要是新聞內容)
3.經過循環爬取到全部的新聞.
分別對應的知識點爲:
1.爬出一個頁面下的基礎數據.
2.經過爬到的數據進行二次爬取.
3.經過循環對網頁進行全部數據的爬取.
話很少說,如今開幹.
經過對新聞欄目的源代碼分析,咱們發現所抓數據的結構爲
那麼咱們只須要將爬蟲的選擇器定位到(li:newsinfo_box_cf),再進行for循環抓取便可.
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("//div[@class='newsinfo_box cf']"): url = response.urljoin(href.xpath("div[@class='news_c fr']/h3/a/@href").extract_first())
測試,經過!
如今我得到了一組URL,如今我須要進入到每個URL中抓取我所須要的標題,時間和內容,代碼實現也挺簡單,只須要在原有代碼抓到一個URL時進入該URL而且抓取相應的數據便可.因此,我只須要再寫一個進入新聞詳情頁的抓取方法,而且使用scapy.request調用便可.
#進入新聞詳情頁的抓取方法 def parse_dir_contents(self, response): item = GgglxyItem() item['date'] = response.xpath("//div[@class='detail_zy_title']/p/text()").extract_first() item['href'] = response item['title'] = response.xpath("//div[@class='detail_zy_title']/h1/text()").extract_first() data = response.xpath("//div[@class='detail_zy_c pb30 mb30']") item['content'] = data[0].xpath('string(.)').extract()[0] yield item
整合進原有代碼後,有:
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("//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) #進入新聞詳情頁的抓取方法 def parse_dir_contents(self, response): item = GgglxyItem() item['date'] = response.xpath("//div[@class='detail_zy_title']/p/text()").extract_first() item['href'] = response item['title'] = response.xpath("//div[@class='detail_zy_title']/h1/text()").extract_first() data = response.xpath("//div[@class='detail_zy_c pb30 mb30']") item['content'] = data[0].xpath('string(.)').extract()[0] yield item
測試,經過!
這時咱們加一個循環:
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("//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("//div[@class='detail_zy_title']/p/text()").extract_first() item['href'] = response item['title'] = response.xpath("//div[@class='detail_zy_title']/h1/text()").extract_first() data = response.xpath("//div[@class='detail_zy_c pb30 mb30']") item['content'] = data[0].xpath('string(.)').extract()[0] yield item
測試:
抓到的數量爲191,可是咱們看官網發現有193條新聞,少了兩條.
爲啥呢?咱們注意到log的error有兩條:
定位問題:原來發現,學院的新聞欄目還有兩條隱藏的二級欄目:
好比:
對應的URL爲
URL都長的不同,難怪抓不到了!
那麼咱們還得爲這兩條二級欄目的URL設定專門的規則,只須要加入判斷是否爲二級欄目:
if URL.find('type') != -1: yield scrapy.Request(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("//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("//div[@class='detail_zy_title']/p/text()").extract_first() item['href'] = response item['title'] = response.xpath("//div[@class='detail_zy_title']/h1/text()").extract_first() data = response.xpath("//div[@class='detail_zy_c pb30 mb30']") item['content'] = data[0].xpath('string(.)').extract()[0] yield item
測試:
咱們發現,抓取的數據由之前的193條增長到了238條,log裏面也沒有error了,說明咱們的抓取規則OK!
scrapy crawl news_info_2 -o 0016.json
學習過程當中遇到什麼問題或者想獲取學習資源的話,歡迎加入學習交流羣626062078,咱們一塊兒學Python!