目录##
-
任务内容
-
爬取过程
-
总结
<b>任务内容</b>
此次抓取的内容为四川大学公共管理学院新闻专栏里的新闻,包括新闻的时间、标题、图片以及详情内容。
这是需要爬的新闻
这是新闻的详情
这是总新闻数(目前为止)
<b>爬取过程</b>
1.首先创建一个新闻工程,并修改其中的items.py文件
创建了一个名为“news”的项目
修改了items.py文件,其中的time、detail、title、picture是采集的时间、新闻详情、标题、图片。day是我采集过程中需要到的一个具体日期项(后有说明原因)。
2.一步一步渐进的抓取过程
秉乘着我一贯小心翼翼的态度,我的抓取过程是慢慢来的,首先是爬取一页新闻列表(不包括新闻详情里面的内容),然后开始加入多页爬取,再到爬取多页的新闻详情(虽然过程比较麻烦,但是这样的方法能够使错误发现得快,且思路较清晰,容易跟得上)。
<p>> 2.1爬取一页新闻列表
爬取一页新闻列表的代码就比较简单了,这也是最开始学习爬虫的时候学习的代码。
这一步只需要采集新闻的标题和时间。
import scrapy
from news.items import NewsItem
class newsspider(scrapy.Spider):import scrapy
name = "news"
start_urls = ['http://ggglxy.scu.edu.cn/index.php?c=special&sid=1']
def parse(self, response):
for new in response.xpath('//div[@class="newsinfo_box cf"]'):
item = NewsItem()
item['time'] = new.xpath('div[@class="date fl"]/span/text()').extract()
item['day'] = new.xpath('div[@class="date fl"]/p/text()').extract()
item['title'] = new.xpath('div[@class="news_c fr"]/h3[@class="mb10"]/a/text()').extract()
yield item
解析:这是在新闻列表页爬取的时间及标题数据,在列表页,可以看到时间的“年-月”和“日”是分开的,这是因为列表页将日期做成一个日历格式的原因,所以在源代码中,他们在不同的地方。所以我在时间上用了两个参数:time、day,一个爬年月,一个爬日
爬取结果显示
结果中的中文显示得是乱码,百度以后查到是编码问题,随后去修改了settings.py文件。增加一行代码:
FEED_EXPORT_ENCODING = 'utf-8'
<p>重新爬取以后,结果就对了。
<p>> 2.2爬取多页新闻列表
爬取多页需要加入循环爬取下一页的代码。
import scrapy
from news.items import NewsItem
class newsspider(scrapy.Spider):
name = "news"
start_urls = ['http://ggglxy.scu.edu.cn/index.php?c=special&sid=1']
def parse(self, response):
for new in response.xpath('//div[@class="newsinfo_box cf"]'):
item = NewsItem()
item['time'] = new.xpath('div[@class="date fl"]/span/text()').extract()
item['day'] = new.xpath('div[@class="date fl"]/p/text()').extract()
item['title'] = new.xpath('div[@class="news_c fr"]/h3[@class="mb10"]/a/text()').extract()
yield item
next_page = response.xpath('//div[@class="pager cf tr pt10 pb10 mt30 mobile_dn"]/li[last()-1]/a/@href').extract_first()
last_page = response.xpath('//div[@class="pager cf tr pt10 pb10 mt30 mobile_dn"]/li[last()]/a/@href').extract_first()
if last_page is not None:
next_page = response.urljoin(next_page)
yield scrapy.http.Request(next_page, callback=self.parse)
解析:在爬取下一页时,发现这个网站爬的下一页有些问题
从网站源代码的分页代码中可以看出,它的下一页是没有标志属性的,都是统一的li标签,如果在写路径的时候直接写li,爬虫是无法去按我们想的那样去爬下一页链接。这时候就需要写一些属性让爬虫识别。还好的是它的顺序都是最后一项是“尾页”,倒数第二项是“下一页”,这样只要li中增加[last()-1]的谓语,就能够顺利爬到下一页的链接。但是即使这样,还是出现一个问题。
图中可以看出,在新闻的最后一页,它没有尾页也没有下一页选项,它的倒数第二个选项是第九页。这就尴尬了,如果按照这个方法爬取,它分页循环爬取的时候,无法判断是否已经达到最后一页,最后会在第九页和第十页之间反复爬取。这时候,就需要设置一个判断,判断它是否是到了最后一页。仔细看最后一页的源代码,可以看到其最后一个li是没有链接的!!!这时候,我们可以利用这一点,判断其最后一个li是否有链接,如果没有了,它就是最后一页,停止继续爬行。
这是爬取所有新闻的列表,共191条。
<p>> 2.3爬取多页新闻列表详情
爬取多页的时候仍然遇到了问题,我们需要链接链到详情页里面爬取新闻的内容和图片,这样的话需要在当前页面爬时间,爬标题,再进入链接里面爬内容。这样的话要分两个函数(是应该称为函数吗?)进行爬取,中间还有点绕。但我发现详情页面有时间和标题,突然顿悟可以直接链接进去进行需要的全部数据爬取,于是,把之前的代码改动了一些,进行爬取。
import scrapy
from news.items import NewsItem
class newsspider(scrapy.Spider):
name = "news"
start_urls = ['http://ggglxy.scu.edu.cn/index.php?c=special&sid=1']
def parse(self, response):
for href in response.xpath('//div[@class="news_c fr"]/h3[@class="mb10"]/a/@href').extract():
yield scrapy.http.Request(response.urljoin(href), callback=self.parse_news)
next_page = response.xpath('//div[@class="pager cf tr pt10 pb10 mt30 mobile_dn"]/li[last()-1]/a/@href').extract_first()
last_page = response.xpath('//div[@class="pager cf tr pt10 pb10 mt30 mobile_dn"]/li[last()]/a/@href').extract_first()
if last_page is not None:
next_page = response.urljoin(next_page)
yield scrapy.http.Request(next_page, callback=self.parse)
def parse_news(self, response):
for new in response.xpath('//div[@class="right_info p20"]'):
item = NewsItem()
item['time'] = new.xpath('div[@class="detail_zy_title"]/p/text()').extract()
item['title'] = new.xpath('div[@class="detail_zy_title"]/h1/text()').extract()
item['detail'] = new.xpath('div[@class="detail_zy_c pb30 mb30"]/p/span/text()').extract()
item['picture'] = new.xpath('div[@class="detail_zy_c pb30 mb30"]/p/img/@src').extract()
yield item
前一个def是进入链接,然后返回到第二个def进行数据爬取。
这个是爬取的最终结果。其中还有几点其实应该进行完善。
第一,图片只是一个路径,无法显示。
第二,新闻详细内容中,有些存在较多的空格及/n、/r等乱七八糟的东西。
但是心累了,以后再慢慢研究吧。
<b>总结</b>
我觉得自己这种一点一点进行的想法挺好,至少我能懂它每一块代码在做什么,也能理清他们之间的关系。这个方法效率不高,也当真花了不少的时间,但其中的收获是满满的。
这次爬取过程懂得了分页和链接详情爬取,确实比在课堂上做的那个好得多。纠错的过程固然心累,但实践出真知,挺有道理的。
还需要学习同时爬取当前网页及链接网页内容的方法。再接再厉吧。