• Python Scrapy 爬虫框架实例


    之前有介绍 scrapy 的相关知识,但是没有介绍相关实例,在这里做个小例,供大家参考学习。

    注:后续不强调python 版本,默认即为python3.x。

    爬取目标

    这里简单找一个图片网站,获取图片的先关信息。

    该网站网址: http://www.58pic.com/c/

    创建项目

    终端命令行执行以下命令

    scrapy  startproject AdilCrawler

    命令执行后,会生成如下结构的项目。

    执行结果如下

    如上图提示,cd 到项目下,可以执行 scrapy genspider example example.com 命令,创建 名为example,域名为example.com 的 爬虫文件。

    编写items.py

    这里先简单抓取图片的作者名称、图片主题等信息。

    复制代码
    # -*- coding: utf-8 -*-
    
    # Define here the models for your scraped items
    #
    # See documentation in:
    # https://doc.scrapy.org/en/latest/topics/items.html
    
    import scrapy
    
    class AdilcrawlerItem(scrapy.Item):
        # define the fields for your item here like:
        # name = scrapy.Field()
    
        author = scrapy.Field()   # 作者
    
        theme = scrapy.Field()    # 主题
    
    复制代码

    编写spider文件 

    进入AdilCrawler目录,使用命令创建一个基础爬虫类:

     scrapy genspider  thousandPic www.58pic.com
    
    #  thousandPic为爬虫名,www.58pic.com为爬虫作用范围

    执行命令后会在spiders文件夹中创建一个thousandPic.py的文件,现在开始对其编写:

    复制代码
    # -*- coding: utf-8 -*-
    import scrapy
    # 爬虫 小试
    
    class ThousandpicSpider(scrapy.Spider):
        name = 'thousandPic'
        allowed_domains = ['www.58pic.com']
        start_urls = ['http://www.58pic.com/c/']
    
        def parse(self, response):
    
            '''
            查看页面元素
             /html/body/div[4]/div[3]/div/a/p[2]/span/span[2]/text()
              因为页面中 有多张图,而图是以 /html/body/div[4]/div[3]/div[i]  其中i  为变量 作为区分的 ,所以为了获取当前页面所有的图
              这里 不写 i 程序会遍历 该 路径下的所有 图片。
            '''# author 作者
            # theme  主题
            author = response.xpath('/html/body/div[4]/div[3]/div/a/p[2]/span/span[2]/text()').extract()
            theme = response.xpath('/html/body/div[4]/div[3]/div/a/p[1]/span[1]/text()').extract()
            # 使用 爬虫的log 方法在控制台输出爬取的内容。
            self.log(author)
            self.log(theme)
            # 使用遍历的方式 打印出 爬取的内容,因为当前一页有20张图片。
            for i in range(1, 21):
                print(i,' **** ',theme[i - 1], ': ',author[i - 1] )
    
    复制代码

     执行命令,查看打印结果

    scrapy crawl thousandPic

    结果如下,其中DEBUG为 log 输出。

    代码优化

    引入 item AdilcrawlerItem

    复制代码
    # -*- coding: utf-8 -*-
    import scrapy
    # 这里使用 import 或是 下面from 的方式都行,关键要看 当前项目在pycharm的打开方式,是否是作为一个项目打开的,建议使用这一种方式。
    import AdilCrawler.items as items
    
    # 使用from 这种方式,AdilCrawler 需要作为一个项目打开。
    # from AdilCrawler.items import AdilcrawlerItem
    
    
    class ThousandpicSpider(scrapy.Spider):
        name = 'thousandPic'
        allowed_domains = ['www.58pic.com']
        start_urls = ['http://www.58pic.com/c/']
    
        def parse(self, response):
    
            '''
            查看页面元素
             /html/body/div[4]/div[3]/div/a/p[2]/span/span[2]/text()
              因为页面中 有多张图,而图是以 /html/body/div[4]/div[3]/div[i]  其中i  为变量 作为区分的 ,所以为了获取当前页面所有的图
              这里 不写 i 程序会遍历 该 路径下的所有 图片。
            '''
    
            item = items.AdilcrawlerItem()
    
            # author 作者
            # theme  主题
    
            author = response.xpath('/html/body/div[4]/div[3]/div/a/p[2]/span/span[2]/text()').extract()
    
            theme = response.xpath('/html/body/div[4]/div[3]/div/a/p[1]/span[1]/text()').extract()
    
            item['author'] = author
            item['theme']  = theme
    
            return item
    复制代码
     
    再次运营爬虫,执行结果如下

    保存结果到文件

    执行命令如下
    scrapy crawl thousandPic -o items.json

    会生成如图的文件

    再次优化,使用 ItemLoader 功能类

    使用itemLoader ,以取代杂乱的extract()和xpath()。

    代码如下: 

    复制代码
    # -*- coding: utf-8 -*-
    import scrapy
    from AdilCrawler.items import AdilcrawlerItem
    
    # 导入 ItemLoader 功能类
    from scrapy.loader import ItemLoader
    
    # optimize  优化
    # 爬虫项目优化
    
    class ThousandpicoptimizeSpider(scrapy.Spider):
        name = 'thousandPicOptimize'
        allowed_domains = ['www.58pic.com']
        start_urls = ['http://www.58pic.com/c/']
    
        def parse(self, response):
    
            '''
            查看页面元素
             /html/body/div[4]/div[3]/div/a/p[2]/span/span[2]/text()
              因为页面中 有多张图,而图是以 /html/body/div[4]/div[3]/div[i]  其中i  为变量 作为区分的 ,所以为了获取当前页面所有的图
              这里 不写 i 程序会遍历 该 路径下的所有 图片。
            '''
    
            # 使用功能类 itemLoader,以取代 看起来杂乱的 extract() 和 xpath() ,优化如下
            i = ItemLoader(item = AdilcrawlerItem(),response = response )
            # author 作者
            # theme  主题
            i.add_xpath('author','/html/body/div[4]/div[3]/div/a/p[2]/span/span[2]/text()')
            i.add_xpath('theme','/html/body/div[4]/div[3]/div/a/p[1]/span[1]/text()')
            return i.load_item()
    复制代码

      

    编写pipelines文件 

     默认pipelines.py 文件

    复制代码
    # -*- coding: utf-8 -*-
    
    # Define your item pipelines here
    #
    # Don't forget to add your pipeline to the ITEM_PIPELINES setting
    # See: https://doc.scrapy.org/en/latest/topics/item-pipeline.html
    
    
    class Adilcrawler1Pipeline(object):
        def process_item(self, item, spider):
            return item
    复制代码

    优化后代码如下

    复制代码
    # -*- coding: utf-8 -*-
    
    # Define your item pipelines here
    #
    # Don't forget to add your pipeline to the ITEM_PIPELINES setting
    # See: https://doc.scrapy.org/en/latest/topics/item-pipeline.html
    
    import json
    
    class AdilcrawlerPipeline(object):
        '''
            保存item数据
        '''
    
        def __init__(self):
            self.filename = open('thousandPic.json','w')
    
        def process_item(self, item, spider):
    
            #  ensure_ascii=False 可以解决 json 文件中 乱码的问题。
            text = json.dumps(dict(item), ensure_ascii=False) + ',
    '   #  这里是一个字典一个字典存储的,后面加个 ',
    ' 以便分隔和换行。
            self.filename.write(text)
    
            return item
    
        def close_spider(self,spider):
            self.filename.close()
    复制代码

    settings文件设置

    修改settings.py配置文件

    找到pipelines 配置进行修改

    复制代码
    # Configure item pipelines
    # See https://doc.scrapy.org/en/latest/topics/item-pipeline.html
    # ITEM_PIPELINES = {
    #    'AdilCrawler.pipelines.AdilcrawlerPipeline': 300,
    # }
    
    # 启动pipeline 必须将其加入到“ITEM_PIPLINES”的配置中
    # 其中根目录是tutorial,pipelines是我的pipeline文件名,TutorialPipeline是类名
    ITEM_PIPELINES = {
        'AdilCrawler.pipelines.AdilcrawlerPipeline': 300,
    }
    
    # 加入后,相当于开启pipeline,此时在执行爬虫,会执行对应的pipelines下的类,并执行该类相关的方法,比如这里上面的保存数据功能。
    复制代码

    执行命令

    scrapy crawl thousandPicOptimize

    执行后生成如下图文件及保存的数据

    使用CrawlSpider类进行翻页抓取

    使用crawl 模板创建一个 CrawlSpider 
    执行命令如下
    scrapy genspider -t crawl thousandPicPaging www.58pic.com

    items.py 文件不变,查看 爬虫 thousandPicPaging.py 文件

    复制代码
    # -*- coding: utf-8 -*-
    import scrapy
    from scrapy.linkextractors import LinkExtractor
    from scrapy.spiders import CrawlSpider, Rule
    
    
    class ThousandpicpagingSpider(CrawlSpider):
        name = 'thousandPicPaging'
        allowed_domains = ['www.58pic.com']
        start_urls = ['http://www.58pic.com/']
    
        rules = (
            Rule(LinkExtractor(allow=r'Items/'), callback='parse_item', follow=True),
        )
    
        def parse_item(self, response):
            i = {}
            #i['domain_id'] = response.xpath('//input[@id="sid"]/@value').extract()
            #i['name'] = response.xpath('//div[@id="name"]').extract()
            #i['description'] = response.xpath('//div[@id="description"]').extract()
            return i
    复制代码

    修改后如下

    复制代码
    # -*- coding: utf-8 -*-
    import scrapy
    # 导入链接规则匹配类,用来提取符合规则的连接
    from scrapy.linkextractors import LinkExtractor
    # 导入CrawlSpider类和Rule
    from scrapy.spiders import CrawlSpider, Rule
    import AdilCrawler.items as items
    
    class ThousandpicpagingSpider(CrawlSpider):
        name = 'thousandPicPaging'
        allowed_domains = ['www.58pic.com']
        # 修改起始页地址
        start_urls = ['http://www.58pic.com/c/']
    
        # Response里链接的提取规则,返回的符合匹配规则的链接匹配对象的列表
        # http://www.58pic.com/c/1-0-0-03.html  根据翻页连接地址,找到 相应的 正则表达式   1-0-0-03  -> S-S-S-SS  而且 这里使用 allow
        # 不能使用 restrict_xpaths ,使用 他的话,正则将失效
        page_link = LinkExtractor(allow='http://www.58pic.com/c/S-S-S-SS.html', allow_domains='www.58pic.com')
    
        rules = (
            # 获取这个列表里的链接,依次发送请求,并且继续跟进,调用指定回调函数处理
            Rule(page_link, callback='parse_item', follow=True),  # 注意这里的 ',' 要不会报错
        )
    
    
        # 加上这个 方法是为了 解决 parse_item() 不能抓取第一页数据的问题 parse_start_url 是 CrawlSpider() 类下的方法,这里重写一下即可
        def parse_start_url(self, response):
            i = items.AdilcrawlerItem()
            author = response.xpath('/html/body/div[4]/div[3]/div/a/p[2]/span/span[2]/text()').extract()
            theme = response.xpath('/html/body/div[4]/div[3]/div/a/p[1]/span[1]/text()').extract()
            i['author'] = author
            i['theme'] = theme
    
            yield i
    
        # 指定的回调函数
        def parse_item(self, response):
            i = items.AdilcrawlerItem()
            author = response.xpath('/html/body/div[4]/div[3]/div/a/p[2]/span/span[2]/text()').extract()
            theme = response.xpath('/html/body/div[4]/div[3]/div/a/p[1]/span[1]/text()').extract()
            i['author'] = author
            i['theme'] = theme
            yield i
    复制代码

    再次执行 

    scrapy crawl thousandPicPaging

    查看执行结果,可以看到是有4页的内容

    再次优化引入 ItemLoader  类

    复制代码
    # -*- coding: utf-8 -*-
    import scrapy
    # 导入链接规则匹配类,用来提取符合规则的连接
    from scrapy.linkextractors import LinkExtractor
    # 导入CrawlSpider类和Rule
    from scrapy.loader import ItemLoader
    from scrapy.spiders import CrawlSpider, Rule
    import AdilCrawler.items as items
    
    class ThousandpicpagingopSpider(CrawlSpider):
        name = 'thousandPicPagingOp'
        allowed_domains = ['www.58pic.com']
        # 修改起始页地址
        start_urls = ['http://www.58pic.com/c/']
    
        # Response里链接的提取规则,返回的符合匹配规则的链接匹配对象的列表
        # http://www.58pic.com/c/1-0-0-03.html  根据翻页连接地址,找到 相应的 正则表达式   1-0-0-03  -> S-S-S-SS  而且 这里使用 allow
        # 不能使用 restrict_xpaths ,使用 他的话,正则将失效
        page_link = LinkExtractor(allow='http://www.58pic.com/c/S-S-S-SS.html', allow_domains='www.58pic.com')
    
        rules = (
            # 获取这个列表里的链接,依次发送请求,并且继续跟进,调用指定回调函数处理
            Rule(page_link, callback='parse_item', follow=True),  # 注意这里的 ',' 要不会报错
        )
    
        # 加上这个 方法是为了 解决 parse_item() 不能抓取第一页数据的问题 parse_start_url 是 CrawlSpider() 类下的方法,这里重写一下即可
        def parse_start_url(self, response):
    
            i = ItemLoader(item = items.AdilcrawlerItem(),response = response )
            i.add_xpath('author','/html/body/div[4]/div[3]/div/a/p[2]/span/span[2]/text()')
            i.add_xpath('theme','/html/body/div[4]/div[3]/div/a/p[1]/span[1]/text()')
    
            yield  i.load_item()
    
        # 指定的回调函数
        def parse_item(self, response):
            i = ItemLoader(item = items.AdilcrawlerItem(),response = response )
            i.add_xpath('author','/html/body/div[4]/div[3]/div/a/p[2]/span/span[2]/text()')
            i.add_xpath('theme','/html/body/div[4]/div[3]/div/a/p[1]/span[1]/text()')
    
            yield  i.load_item()
    复制代码

    执行结果是一样的。

    最后插播一条 在线正则表达式测试 工具的广告,地址: http://tool.oschina.net/regex/

    应用如下

    ————我们之所以要努力,不是为了改变世界,而是为了不让世界改变我们。无论你是谁,无论你正在经历什么,坚持住,你定会看见最坚强的自己。
  • 相关阅读:
    保存时出错jup
    Spyder默认页面布局调整
    根据所处位置提取单元格内容的函数(left、right、mid)和查找字符串位于单元格内容第几位的函数(find)
    excel打印出现多余空白页
    Excel的布尔值运算
    excel VBA一个fuction同时执行多个正则表达式,实现方法
    excel VBA把一个单元格内容按逗号拆分并依次替换到另一个单元格的括号里面(本题例子,把文本中的括号换成{答案}的格式,并按顺序填空)
    excel自动记录项目完成进度,是否逾期,逾期/提前完成天数,计算天数可以把now()改为today()
    jquery循环动画
    jquery动画(控制动画隐藏、显示时间轴)
  • 原文地址:https://www.cnblogs.com/longshao1239/p/12054164.html
Copyright © 2020-2023  润新知