Scrapy笔记四 自动爬取网页之使用CrawlSpider

  • 2019 年 11 月 23 日
  • 笔记

学习自:http://blog.csdn.net/u012150179/article/details/34913315

原理部分放在后面,首先来实现一下:

原网站中只有写爬虫主要的代码,这里我把边缘代码也记录下来,

0.创建项目:

Python

scapy startproject CSDNBlogCrawlSpider

1

scapy startproject CSDNBlogCrawlSpider

1.item.py

Python

from scrapy.item import Item, Field class CsdnblogcrawlspiderItem(Item): blog_name = Field() blog_url = Field()

123456

from scrapy.item import Item, Field class CsdnblogcrawlspiderItem(Item):     blog_name = Field()    blog_url = Field()

2. pipelines.py

Python

import json import codecs class CsdnblogcrawlspiderPipeline(object): def __init__(self): self.file = codecs.open('log.json',mode='wb',encoding='utf-8') def process_item(self, item, spider): line = json.dumps(dict(item)) + 'n' self.file.write(line.decode("unicode_escape")) return item

1234567891011

import jsonimport codecs class CsdnblogcrawlspiderPipeline(object):    def __init__(self):        self.file = codecs.open('log.json',mode='wb',encoding='utf-8')     def process_item(self, item, spider):        line = json.dumps(dict(item)) + 'n'        self.file.write(line.decode("unicode_escape"))        return item

3. settings.py

Python

# -*- coding: utf-8 -*- BOT_NAME = 'CSDNBlogCrawlSpider' SPIDER_MODULES = ['CSDNBlogCrawlSpider.spiders'] NEWSPIDER_MODULE = 'CSDNBlogCrawlSpider.spiders' COOKIES_ENABLED = False ITEM_PIPELINES = { 'CSDNBlogCrawlSpider.pipelines.CsdnblogcrawlspiderPipeline':301 }

123456789101112

# -*- coding: utf-8 -*- BOT_NAME = 'CSDNBlogCrawlSpider' SPIDER_MODULES = ['CSDNBlogCrawlSpider.spiders']NEWSPIDER_MODULE = 'CSDNBlogCrawlSpider.spiders' COOKIES_ENABLED = False ITEM_PIPELINES = {    'CSDNBlogCrawlSpider.pipelines.CsdnblogcrawlspiderPipeline':301}

4.spiders/text.py

Python

#coding:utf-8 from scrapy.contrib.spiders import CrawlSpider, Rule from scrapy.contrib.linkextractors.sgml import SgmlLinkExtractor from scrapy.selector import Selector from CSDNBlogCrawlSpider.items import CsdnblogcrawlspiderItem class CSDNBlogCrawlSpider(CrawlSpider): """继承自CrawlSpider,实现自动爬取的爬虫。""" name = "CSDNBlogCrawlSpider" #设置下载延时 download_delay = 2 allowed_domains = ['blog.csdn.net'] #第一篇文章地址 start_urls = ['http://blog.csdn.net/u012150179/article/details/11749017'] #rules编写法一,官方文档方式 #rules = [ # #提取“下一篇”的链接并**跟进**,若不使用restrict_xpaths参数限制,会将页面中所有 # #符合allow链接全部抓取 # Rule(SgmlLinkExtractor(allow=('/u012150179/article/details'), # restrict_xpaths=('//li[@class="next_article"]')), # follow=True) # # #提取“下一篇”链接并执行**处理** # #Rule(SgmlLinkExtractor(allow=('/u012150179/article/details')), # # callback='parse_item', # # follow=False), #] #rules编写法二,更推荐的方式(自己测验,使用法一时经常出现爬到中间就finish情况,并且无错误码) rules = [ Rule(SgmlLinkExtractor(allow=('/u012150179/article/details'), restrict_xpaths=('//li[@class="next_article"]')), callback='parse_item', follow=True) ] def parse_item(self, response): print "parse_item>>>>>>" item = CsdnblogcrawlspiderItem() sel = Selector(response) blog_url = str(response.url) blog_name = sel.xpath('//div[@id="article_details"]/div/h1/span/a/text()').extract() item['blog_name'] = [n.encode('utf-8') for n in blog_name] item['blog_url'] = blog_url.encode('utf-8') yield item

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152

#coding:utf-8from scrapy.contrib.spiders import CrawlSpider, Rulefrom scrapy.contrib.linkextractors.sgml import SgmlLinkExtractorfrom scrapy.selector import Selectorfrom CSDNBlogCrawlSpider.items import CsdnblogcrawlspiderItem  class CSDNBlogCrawlSpider(CrawlSpider):     """继承自CrawlSpider,实现自动爬取的爬虫。"""     name = "CSDNBlogCrawlSpider"    #设置下载延时    download_delay = 2    allowed_domains = ['blog.csdn.net']    #第一篇文章地址    start_urls = ['http://blog.csdn.net/u012150179/article/details/11749017']     #rules编写法一,官方文档方式    #rules = [    #    #提取“下一篇”的链接并**跟进**,若不使用restrict_xpaths参数限制,会将页面中所有    #    #符合allow链接全部抓取    #    Rule(SgmlLinkExtractor(allow=('/u012150179/article/details'),    #                          restrict_xpaths=('//li[@class="next_article"]')),    #         follow=True)    #    #    #提取“下一篇”链接并执行**处理**    #    #Rule(SgmlLinkExtractor(allow=('/u012150179/article/details')),    #    #     callback='parse_item',    #    #     follow=False),    #]     #rules编写法二,更推荐的方式(自己测验,使用法一时经常出现爬到中间就finish情况,并且无错误码)    rules = [        Rule(SgmlLinkExtractor(allow=('/u012150179/article/details'),                              restrict_xpaths=('//li[@class="next_article"]')),             callback='parse_item',             follow=True)    ]     def parse_item(self, response):         print "parse_item>>>>>>"        item = CsdnblogcrawlspiderItem()        sel = Selector(response)        blog_url = str(response.url)        blog_name = sel.xpath('//div[@id="article_details"]/div/h1/span/a/text()').extract()         item['blog_name'] = [n.encode('utf-8') for n in blog_name]        item['blog_url'] = blog_url.encode('utf-8')         yield item

5.原理部分(以下部分,可以去原作者网站中学习)

1.CrawlSpider

(1)概念与作用:

它是Spider的派生类,首先在说下Spider,它是所有爬虫的基类,对于它的设计原则是只爬取start_url列表中的网页,而从爬取的网页中获取link并继续爬取的工作CrawlSpider类更适合。

(2)使用:

它与Spider类的最大不同是多了一个rules参数,其作用是定义提取动作。在rules中包含一个或多个Rule对象,Rule类与CrawlSpider类都位于scrapy.contrib.spiders模块中。

  1. class scrapy.contrib.spiders.Rule (
  2. link_extractor, callback=None,cb_kwargs=None,follow=None,process_links=None,process_request=None )

link_extractor为LinkExtractor,用于定义需要提取的链接。

callback参数:当link_extractor获取到链接时参数所指定的值作为回调函数。

 callback参数使用注意:

当编写爬虫规则时,请避免使用parse作为回调函数。于CrawlSpider使用parse方法来实现其逻辑,如果您覆盖了parse方法,crawlspider将会运行失败。

follow:指定了根据该规则从response提取的链接是否需要跟进。当callback为None,默认值为true。

process_links:主要用来过滤由link_extractor获取到的链接。

process_request:主要用来过滤在rule中提取到的request。

2.LinkExtractor

(1)概念:

顾名思义,链接提取器。

(2) 作用:

response对象中获取链接,并且该链接会被接下来爬取。

(3) 使用:

通过SmglLinkExtractor提取希望获取的链接。

  1. classscrapy.contrib.linkextractors.sgml.SgmlLinkExtractor(
  2. allow=(),deny=(),allow_domains=(),deny_domains=(),deny_extensions=None,restrict_xpaths=(),tags=(‘a’,‘area’),attrs=(‘href’),canonicalize=True,unique=True,process_value=None)

主要参数:

allow:满足括号中“正则表达式”的值会被提取,如果为空,则全部匹配。

deny:与这个正则表达式(或正则表达式列表)不匹配的URL一定不提取。

allow_domains:会被提取的链接的domains。

deny_domains:一定不会被提取链接的domains。

restrict_xpaths:使用xpath表达式,和allow共同作用过滤链接。

三.RUN!

shell中验证

  1. 开始编写代码之前,使用scrapyshell查看使用SmglLinkExtractor在网页中获取到的链接:
    1. scrapy shell http://blog.csdn.net/u012150179/article/details/11749017
  2. 继续import相关模块:fromscrapy.contrib.linkextractors.sgml import SgmlLinkExtractor现在使用SgmlLinkExtractor查看在当前网页中获得的链接:
    1. item=SgmlLinkExtractor(allow=(‘/u012150179/article/details’)).extract_links(response)

    其中item为包含Link()对象的列表,现在显示其中的text元素(就是获取到的文章链接对应的文章标题):

    1. for i in item:
    2. print i.text

    对照网页可以得到此时获取的是当前网页中所有满足allow条件的链接,不仅包含“下一篇”的链接,还有网页侧边栏“阅读排行“、”评论排行“中的文章链接。为了只获得”下一篇“文章链接,这就要进行所有链接的筛选,引入参数restrict_xpaths,继续:

    1. item= SgmlLinkExtractor(allow=(‘/u012150179/article/details’),restrict_xpaths=(‘//li[@class=”next_article”]’)).extract_links(response)

    这是在如上查看结果,便提取出了“下一篇”文章链接。注意:在shell中并不对提取到的link进行跟进。 在这里不得不提的就是scrapy shell是对调试、验证很有用的交互工具。应该掌握。 在shell中进行了验证后进入写代码阶段。

原创文章,转载请注明: 转载自URl-team

本文链接地址: Scrapy笔记四 自动爬取网页之使用CrawlSpider