爬虫框架Scrapy体验

填坑计划:scrapy

scrapy简介

Scrapy是适用于Python的一个快速、高层次的屏幕抓取和web抓取框架,用于抓取web站点并从页面中提取结构化的数据。Scrapy用途广泛,可以用于数据挖掘、监测和自动化测试。

Scrapy吸引人的地方在于它是一个框架,任何人都可以根据需求方便的修改。它也提供了多种类型爬虫的基类,如BaseSpider、sitemap爬虫等,最新版本又提供了web2.0爬虫的支持。

ScrapyDemo

  1. 安装scrapy

    pip3 install scrapy
    
  2. 创建scrapy项目
    在项目目录下:

    scrapy startproject ScrapyDemo
    
  3. 使用PyCharm打开项目
    为了操作方便,在项目根目录下创建run.py,以用于后面的启动和调试项目

    # -*- coding: utf-8 -*-
    # 启动项目脚本
    
    from scrapy.cmdline import execute
    
    # 创建爬虫
    execute('scrapy genspider qidian_bookinfo "book.qidian.com"'.split())
    

    可以看到:使用scrapy.cmdline.execute方法执行命令行指令,需要使用split函数将指令分隔开

  4. 创建爬虫
    在项目目录下执行指令

    scrapy genspider qidian_bookinfo "book.qidian.com"
    

    创建一个爬虫,爬取的范围是起点小说网的book目录,本次就先拿这个作为实验对象

  5. 创建item对象
    在Items.py文件中,按照提示创建内容
    我们计划爬取某小说的题目、作者、宣传语、简介内容四个部分,因此要创建4个Item

    import scrapy
    class ScrapydemoItem(scrapy.Item):
        # define the fields for your item here like:
        # name = scrapy.Field()
        title = scrapy.Field()
        author = scrapy.Field()
        intro = scrapy.Field()
        entry = scrapy.Field()
    
  6. 编写爬虫文件qidian_bookinfo.py

    # -*- coding: utf-8 -*-
    import scrapy
    from ScrapyDemo.items import ScrapydemoItem
    # 具体爬虫文件
    
    class QidianBookinfoSpider(scrapy.Spider):
        name = 'qidian_bookinfo'
        # 允许爬取的域名范围
        allowed_domains = ['book.qidian.com'] 
        # 开始爬取url
        start_urls = ['https://book.qidian.com/info/1004990267/']
    
        def parse(self, response):
            title = response.xpath('//div[@class="book-info "]//h1//em/text()').get()
            author = response.xpath('//div[@class="book-info "]//h1//span//a/text()').get()
            intro = response.xpath('//div[@class="book-info "]//p[@class="intro"]/text()').get()
            entry = response.xpath('//div[@class="book-intro"]//p/text()').get().strip()
            # 返回对象
            item = ScrapydemoItem(title=title, author=author, intro=intro, entry=entry)
            # 生成item
            yield item
    

    可以看到,这里使用的xpath作为选择器,因此需要先了解xpath语法
    xpath语法参考
    其实理解起来比较容易,比如下面的xpath解析式:

    //div[@class="book-info "]//h1//em/text()
    

    解析的对象是class="book-info "的div的下面的h1,h1下面的em标签中的文本内容,这个内容就是作品题目

    注意: 这里作者遇到了一个坑点(和程序无关),这个网站的info页面book-info类的div标签类是带一个空格的,笔者一开始去掉了空格,结果什么都爬不到、

    [@class="book-info "] #字符串最后有个空格是故意加上的,不加空格爬取不到
    
  7. 使用pipline处理内容
    在pipline.py文件中处理爬虫返回的内容,这里将获得的四种信息转换成json格式并且存储到本地文件
    使用了scrapy中专门输出Json格式数据的JsonLinesItemExporter来输出数据

from scrapy.exporters import JsonLinesItemExporter

class ScrapydemoPipeline:

    def __init__(self):
        self.fp = open("bookinfo.json", "wb")
        # json文件输出器
        self.exporter = JsonLinesItemExporter(self.fp, ensure_ascii=False, encoding='utf-8')

    def open_spider(self, spider):
        self.exporter.start_exporting()

    def process_item(self, item, spider):
        self.exporter.export_item(item)
        return item

    def close_spider(self, spider):
        self.fp.close()
        self.exporter.finish_exporting()
        print("结束")
  1. 配置settings.py
    在我们写好了所有内容之后,爬虫需要进行配置才能运行
    编辑settings.py,取消注释并且配置一下内容:
    # 1. 关闭遵守robots协议
    ROBOTSTXT_OBEY = False
    
    # 2. 伪装身份
    DEFAULT_REQUEST_HEADERS = {
        'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
        'Accept-Language': 'en',
        'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/66.0.3359.139 Safari/537.36'
    }
    
    # 3. 使用pipeline处理获取数据
    ITEM_PIPELINES = {
       'ScrapyDemo.pipelines.ScrapydemoPipeline': 300,
    }
    
  2. 在run.py中运行如下内容,即可启动爬虫
    #执行指令
    execute('scrapy crawl qidian_bookinfo'.split())
    
  3. 检查目录下的bookinfo.json结果
    {
    	"title": "穿越之皇帝成长计划",
    	"author": "奥特曼会写字",
    	"intro": "醒掌天下权,醉卧美人膝,五千年风华烟雨,是非成败转头空!",
    	"entry": "主角一朝穿越惊现成了即将登位的太子,治理自己的国家。寻找名妃,培养子女,尔虞我诈;发展国家,收录名臣,秣马厉兵。是后宫佳丽三千还是后宫佳丽三千;西楚霸王、蜀汉名将、水浒英雄,谁能助我一统天下;从三皇五帝到唐宗宋祖,雄霸天下亦或是儿女情长,收录不尽的名臣美人,挑战无限的激情国战。"
    }
    
    使用JsonLinesItemExporter输出的数据如果有多个会占多行,每行是独立的json数据
    如果使用JsonItemExporter输出数据,多行数据是装在一个json列表里的,只占一行
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章