Python抓取學院新聞報告
Python案例
scrapy抓取學院新聞報告
任務
抓取四川大學公共管理學院官網(http://ggglxy.scu.edu.cn)所有的新聞咨詢.
實驗流程
1.確定抓取目標.
2.制定抓取規則.
3.‘編寫/調試‘抓取規則.
4.獲得抓取數據
1.確定抓取目標
我們這次需要抓取的目標為四川大學公共管理學院的所有新聞資訊.於是我們需要知道公管學院官網的布局結構.
這裏我們發現想要抓到全部的新聞信息,不能直接在官網首頁進行抓取,需要點擊"more"進入到新聞總欄目裏面.
我們看到了具體的新聞欄目,但是這顯然不滿足我們的抓取需求: 當前新聞動態網頁只能抓取新聞的時間,標題和URL,但是並不能抓取新聞的內容.所以我們想要需要進入到新聞詳情頁抓取新聞的具體內容.
2.制定抓取規則
通過第一部分的分析,我們會想到,如果我們要抓取一篇新聞的具體信息,需要從新聞動態頁面點擊進入新聞詳情頁抓取到新聞的具體內容.我們點擊一篇新聞嘗試一下
們發現,我們能夠直接在新聞詳情頁面抓取到我們需要的數據:標題,時間,內容.URL.
好,到現在我們清楚抓取一篇新聞的思路了.但是,如何抓取所有的新聞內容呢?
這顯然難不到我們.
我們在新聞欄目的最下方能夠看到頁面跳轉的按鈕.那麽我們可以通過"下一頁"按鈕實現抓取所有的新聞.
那麽整理一下思路,我們能夠想到一個顯而易見的抓取規則:
通過抓取‘新聞欄目下‘所有的新聞鏈接,並且進入到新聞詳情鏈接裏面抓取所有的新聞內容.
3.‘編寫/調試‘抓取規則
為了讓調試爬蟲的粒度盡量的小,我將編寫和調試模塊糅合在一起進行.
在爬蟲中,我將實現以下幾個功能點:
1.爬出一頁新聞欄目下的所有新聞鏈接
2.通過爬到的一頁新聞鏈接進入到新聞詳情爬取所需要數據(主要是新聞內容)
3.通過循環爬取到所有的新聞.
分別對應的知識點為:
1.爬出一個頁面下的基礎數據.
2.通過爬到的數據進行二次爬取.
3.通過循環對網頁進行所有數據的爬取.
話不多說,現在開幹.
3.1爬出一頁新聞欄目下的所有新聞鏈接
通過對新聞欄目的源代碼分析,我們發現所抓數據的結構為
那麽我們只需要將爬蟲的選擇器定位到(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‘][email protected]").extract_first())
測試,通過!
3.2通過爬到的一頁新聞鏈接進入到新聞詳情爬取所需要數據(主要是新聞內容)
現在我獲得了一組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‘][email protected]").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‘][email protected]").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
測試:
Paste_Image.png
抓到的數量為191,但是我們看官網發現有193條新聞,少了兩條.
為啥呢?我們註意到log的error有兩條:
定位問題:原來發現,學院的新聞欄目還有兩條隱藏的二級欄目:
比如:
Paste_Image.png
對應的URL為
Paste_Image.png
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‘][email protected]").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
測試:
4.獲得抓取數據
scrapy crawl news_info_2 -o 0016.json
學習過程中遇到什麽問題或者想獲取學習資源的話,歡迎加入學習交流群
626062078,我們一起學Python!
Python抓取學院新聞報告