专栏首页技术专栏Scrapy基础(二): 使用详解

Scrapy基础(二): 使用详解

scrapy的安装和基本介绍请看 http://www.jianshu.com/p/a71386fa317a

  • Spider

scrapy的网站爬取需要继承scrapy.Spider类,会根据配置的初始url自动下载网页信息,并调用parse方法,下载的网页信息会通过parse方法的response参数进行传递 例:

class JobboleSpider(scrapy.Spider):
    name = 'jobbole'  # spider名称
    allowed_domains = ['blog.jobbole.com']  # 域名
    start_urls = ['http://blog.jobbole.com/all-posts/'] # 其实url

    def parse(self, response): 

启动方式为

scrapy crawl jobbole  # jobbole为spider名称
  • MiddleWare

Spider产生的Request请求会在一系列调度后,流经一个个MiddleWare,最终到达Downloader进行真正的Http的请求并得到相应,我们可以自定义MiddleWare,并在settings文件进行顺序配置,定制化下载前的准备工作,比如加入User-Agent随机切换,Ip代理池的设置,Selenium代理下载等

自定义Middleware需要重载4个函数来做不同的处理

class CustomMiddleWare
    # 定义这个方法,Scrapy会把当前的爬虫传递到方法里来
    @classmethod
    def from_crawler(cls, crawler):
        return cls(crawler)

    # 处理request请求
    def process_request(self, request, spider):
            pass

    # 处理response请求
    def process_response(self, response, spider):
           pass

     # 处理异常情况
    def process_exception(self, response, spider):
           pass

settings 配置

# 下载服务管理器
DOWNLOADER_MIDDLEWARES = {
    'ArticleSpider.middlewares.RandomUserAgentMiddlware': 100,
    # 'ArticleSpider.middlewares.RandomProxyMiddleware': 200,
    # 'ArticleSpider.middlewares.JSPageMiddleware': 300,
    # 如果自定义了User-Agent的MiddleWare,需要将scrapy的默认Middleware置为None
    'ScrapyRedisTest.middlewares.MyCustomDownloaderMiddleware': None,
}
  • Item

使用scrapy.Spider爬取好相关数据后,需要将数据进行保存,数据在scrapy中流转是通过Item来实现,使用Item来定义scray的模型model,需要继承scrapy.Item类 例:

class JobBoleArticleItem(scrapy.Item):
    # 使用scrapy.Field进行数据的定义规则
    title = scrapy.Field(
        input_processor=MapCompose(lambda x:x+"-jobbole",add_jobbole)
    )
    create_date = scrapy.Field(
        input_processor=MapCompose(date_covert)
    )
    url = scrapy.Field()
    url_object_id = scrapy.Field()
    front_image_url = scrapy.Field(
        output_processor=MapCompose(return_value)
    )
    front_image_path = scrapy.Field()
    praise_nums = scrapy.Field(
        input_processor=MapCompose(get_nums)
    )
    common_nums = scrapy.Field(
        input_processor=MapCompose(get_nums)
    )
    fav_nums = scrapy.Field(
        input_processor=MapCompose(get_nums)
    )
    tags = scrapy.Field(
        input_processor=MapCompose(remove_comment_tags),
        output_processor=Join(",")
    )
    content = scrapy.Field()

scrapy.Field可以接收input_processor,output_processor等来定义数据的包装规则,MapCompose会依次调用参数方法(参数方法需要接收一个value参数,返回按照相应规则包装好的值) 例如将create_date(str类型)转换成(date类型)

def date_covert(value):
    try:
        create_date = datetime.datetime.strptime(value,"%Y/%m/%d").date()
    except Exception as e:
        create_date = datetime.datetime.now().date()

    return create_date
...
  create_date = scrapy.Field(
        input_processor=MapCompose(date_covert)
    )
...

可以通过继承ItemLoader类自定义默认的input_processor,output_processor

class ArticleItemLoader(ItemLoader):
    #自定义output_processor
    default_output_processor = TakeFirst()

Spider 提取相应数据后需要将数据包装成Item

    def parse(self, response): 
        article_item = JobBoleArticleItem()
...
...
        yield article_item
  • Pipeline

Spider 讲数据包装成Item以后,scrapy会按照在setting是中配置的顺序进行执行pipeline的类方法,进行数据的持久化或其他的下载操作 每一个Pipeline需要有一个process_item方法,接收一个item参数,做完相应处理后返回item,并在settings.py中配置执行顺序

settings.py

数字小的先执行

ITEM_PIPELINES = {
    # 'scrapy.pipelines.images.ImagesPipeline': 1,
     'ArticleSpider.pipelines.ArticleImagePipeline':1,
    # 'ArticleSpider.pipelines.JsonExporterPipeline': 2,
    'ArticleSpider.pipelines.MysqlTwistedPipeline': 2,
}

Pipeline

class ArticlespiderPipeline(object):
    def process_item(self, item, spider):
        # 做具体的执行逻辑 
        return item

上面讲的一些Settings的配置,是所有爬虫的统一配置,如果需要在每个爬虫里自定义配置,可以使用custom_settings变量覆盖统一配置

custom_settings = {
        "COOKIES_ENABLED": False,
        "DOWNLOAD_DELAY": 0
    }

具体实例地址 https://github.com/MarkGao11520/ArticleSpider

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • Scrapy基础(一): 安装和使用

    Meet相识
  • 2.1 Python实现区块链环境准备

    Meet相识
  • 2.6 共识机制

    共识机制的原理是,当一个节点通过工作量证明打包了区块添加到了区块链上,要和全网其他同时完成工作量证明的节点竞争最长链,如果发现比自己长的链,则替换掉自己的,基于...

    Meet相识
  • 在非Activity中使用startActivity:Calling startActivity() from outside of an Activity context requires the

    activity继承了context重载了startActivity方法,如果使用acitvity中的startActivity,不会有任何限制。

    一个会写诗的程序员
  • 基础知识 | 每日一练(1)

    士人有百折不回之真心,才有万变不穷之妙用。立业建功,事事要从实地着脚,若少慕声闻,便成伪果;讲道修德,念念要从虚处立基,若稍计功效,便落尘情。         ...

    闫小林
  • MySQL应用之CROSS JOIN用法简介教程

    MySQL cross join是mysql中的一种连接方式,区别于内连接和外连接,对于cross join连接来说,其实使用的就是笛卡尔连接。在MySQL中,...

    SmileNicky
  • 「Workshop」第二期:程序控制与数据操作流

    《R for Data Science》: http://r4ds.had.co.nz/

    王诗翔呀
  • 聊聊C10K问题及解决方案

    1 C10K问题 大家都知道互联网的基础就是网络通信,早期的互联网可以说是一个小群体的集合。互联网还不够普及,用户也不多。一台服务器同时在线100个用户估计在当...

    用户1263954
  • [译] 如何更新 package.json 中的依赖项

    原文:https://medium.com/better-programming/how-to-upgrade-dependencies-in-package-...

    江米小枣
  • 通过 PHP 代码发送 HTTP 响应与文件下载

    一个完整的 HTTP 响应报文包含状态行、响应头和响应实体,关于 HTTP 响应底层结构你可以参考 HTTP 报文简介及组成结构这篇教程

    学院君

扫码关注云+社区

领取腾讯云代金券