抓取四川大学公共管理学院官网(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!