python的Scrapy爬虫框架的使用方式

1.Scrapy框架的介绍

scrapy是使用python编写的为了爬取网站数据,提取结构性数据而编写的一个应用框架,用途十分广泛。它是基于Twisted的一个异步处理框架,拥有架构清晰,可扩展性强,可灵活完成各种需求,各模块之间的耦合程度低,只需简单的几个模块就可以实现一个爬虫,因此上手很快。

1.1 Scrapy工作机制

大体上可以将Scrapy中的模块分为下面几个:引擎(Scrapy Engine),调度器(Schedule),爬虫主件(Spider),下载器(Downloader),管道(ItemPipeline)。各模块之间相互配合,由此构成了一个框架的基本结构。
在这里插入图片描述
框架的部分功能如下:
引擎(Scrapy Engine),处理整个系统的数据流,出发事务,是整个框架的核心
调度器(Schedule),接受引擎发过来的请求,并将其加入队列中,在引擎再次请求时将请求提供给引擎。
爬虫主件(Spider),蜘蛛,在其内定义了爬取的逻辑以及网页的解析规则,主要是解析响应并提取数据和提供新的url
下载器(Downloader),只有一个功能,就是发送请求获得响应
管道(ItemPipeline),处理蜘蛛从网页中提取的数据,主要任务是清洗,验证与存储数据。可以选择将数据存在文件或数据库中。
中间件(MiddleWare),有下载中间件以及爬虫中间件,其中在下载中间件中,我们可以设置user-agent,IP代理,cookie等以获得信息。

1.2 Scrapy数据流向

在scrapy运行之后,它的数据流向大概是下面这个样子:

  1. Engine首先打开一个网站,找到处理该网站的Spider,并向该Spider请求第-个要爬取的URL。
  2. Engine从Spider中获取到第一个要爬取的URL,并通过Scheduler以Request的形式调度。
  3. Engine向Scheduler请求下一个要爬取的URL。
  4. Sceduler返回下一个要爬取的 URL给Engine, Engine 将URL通过Downloader Middlewares转发给Downloader下载。
  5. 一旦页面下载完毕,Downloader生成该页面的Response,并将其通过Downloader
    Middlewares发送给Engine。
  6. Engine从下载器中接收到Response,并将其通过Spider Middlewares发送给Spider处理。
  7. Spider处理Response,并返回爬取到的Item及新的Request给Engine。
  8. Engine将Spider返回的Item给Item Pipeline,将新的Request给Scheduler。
  9. 重复第(2)步到第(8)步,直到Scheduler中没有更多的Request, Engine 关闭该网站,爬取结束。

通过多个组件的相互协作、不同组件完成工作的不同、组件对异步处理的支持,Scrapy 最大限度地利用了网络带宽,大大提高了数据爬取和处理的效率。

1.3 scrapy制作步骤

制作一个scrapy爬虫一共需要4步,

  • 新建项目
  • 明确目标
  • 制作爬虫
  • 存储内容

1.4 scrapy安装介绍

Scrapy 框架官方网址: http://doc.scrapy.org/en/latest
Scrapy 中文维护站点: http://scrapy-chs.readthedocs.io/zh_CN/latest/index.html
Windows 安装方式:
通过 pip 安装 Scrapy 框架 pip install Scrapy
Ubuntu 需要 9.10 或以上版本安装方式:
安装非 Python 的依赖:

sudo apt-get install python-dev python-pip libxml2-dev libxslt1-dev
zlib1g-dev libffi-dev libssl-dev

通过 pip 安装 Scrapy 框架 sudo pip install scrapy
其他平台的安装可以见:scrapy各平台安装方法
判断是否安装成功,在终端下输入scrapy命令,如果出现下面这种结果,说明已经成功。
在这里插入图片描述
安装使用过程中的错误及解决办法:

  1. 使 用 Scrapy 时 遇 到 0: UserWarning: You do not have a working installation of the
    service_identity module: ‘cannot import name ‘opentype’’. Please install it from … 的 问 题 解 决网址:http://www.bubuko.com/infodetail-2467560.html

  2. 报错cannot import name “etree”
    原因是因为lxml版本过高,需卸载后重新安装3.8及以下的版本

  3. 报错:Microsoft Visual C++ 14.0 is required.Get it with “Microsoft
    Visual C++ Build Tools”…
    解决办法:前往http://www.lfd.uci.edu/~gohlke/pythonlibs/#twisted 下载 twisted 对应版本的 whl 文件( 如我的 Twisted-18.4.0-cp36-cp36m-win_amd64.whl),cp 后面是 python 版本, amd64 代表 64 位, 下载完毕后运行命令:pip install C:\Users\ibm\Downloads\Twisted-18.4.0-cp36-cp36m-win_amd64.whl

  4. 报错:No module named ‘win32api’
    解决办法:pip install pywin32

2.Scrapy框架的使用

在scrapy使用过程中,项目的创建,执行均在终端进行,IDE只是一个编写代码的地方,不再运行scrapy项目。
创建项目时,过程如下(以百度为例)
打开终端:

scrapy startproject baidu
cd demoname
scrapy genspider baidu baidu.com

在这里介绍一下各文件的功能:

  • scrapy.cfg:它是Scrapy项目的配置文件,其内定义了项目的配置文件路径、部署相关信息等内容。
  • items.py:它定义Item数据结构,所有的Item的定义都可以放这里。
  • pipelines.py:它定义Item Pipeline的实现,比如数据的处理与保存。
  • settings.py:它定义项目的全局配置。
  • middlewares.py:它定义Spider Middlewares和Downloader Middlewares的实现。
  • spiders包:其内包含一个个Spider的实现,每个Spider都有单独的一个文件。

打开项目中的settings文件,将是否遵守爬虫协议改为False
在这里插入图片描述

在修改过爬虫协议之后,已经可以从目标服务器获取关于网页的响应信息了。不信可以将response写入文件中试一试。获取响应内容要是用response.body或者response.text方式。
如:
在这里插入图片描述
可以看到start_urls为列表,在该列表中存储了需要爬取的网页的url,如果需要爬取的网页很少时可以选择直接将多个url存储在该列表。如果url规律可循可使用循环或者列表推导式来存储url。

拿到了网页的内容之后就是对网页内容的提取了,在scrapy中有自己的数据提取方法:Selector(选择器),它是基于lxml来构建的,支持xpath选择器以及css选择器,正则表达式,功能全面,解析速度很快,精确度也很高。当然在框架外也是可以使用Selector选择器的,这样提取数据的方法又多了一种。

由于selector支持xpath,所以在拿到响应后,不需要做其他的处理就可以直接用xpath中的方法来提取结构化数据。而且在上面也讲过,在提取数据的时候有两部分结果,一个是需要交给管道进行下一步处理的数据,另一个是需要进一步爬取的网站的url。因为只有一个蜘蛛在进行工作,所以在这里就用到了生成器的相关知识,如果不熟悉,可以去找基础知识翻看。一般情况下,对这种情况我们是这样处理的,使用多个yield,一步一步的完成网页的爬取与数据提取。而对于数据的存储,则需要创建一个item对象,由它将数据携带给管道进行处理。

比如下面这个例子(爬取golang贴吧):

extract_first()是将匹配的第一个结果取出来,如果没有取到,也不会报错;
extract()是将匹配的全部结果以列表形式返回,仍需索引值来取出数据;
response.urljoin()可以将相对路径转为绝对路径,很好用,不用费劲的去拼接url,一个不小心还会拼错;
response.url返回的是当前的url。

spider包中的spider.py文件的代码:

class GolangSpider(scrapy.Spider):
    name = 'golang'
    allowed_domains = ['baidu.com']
    start_urls = ['https://tieba.baidu.com/f?kw=golang&ie=utf-8&pn=0']
    def parse(self, response):
        print('*****************************'*100,response.url)
        li_list = response.xpath(r'.//li[@class=" j_thread_list clearfix"]')
        for li in li_list:
            item = GolangSpiderItem()
            title = li.xpath(r'.//a[@class="j_th_tit "]/text()').extract_first()
            item['title']=title
            author = li.xpath(r'.//span[@class="frs-author-name-wrap"]/a/text()').extract_first()
            item['author'] = author
            time = li.xpath(r'.//span[@class="pull-right is_show_create_time"]/text()').extract_first().strip()
            item['time'] = time
            # href = 'https://tieba.baidu.com'+li.xpath(r'.//a[@class="j_th_tit "]/@href').extract_first()
            href = response.urljoin(li.xpath(r'.//a[@class="j_th_tit "]/@href').extract_first())
            yield scrapy.Request(url=href,callback=self.parser2,meta={'data':item})
        next_page = response.xpath('.//div[@id="frs_list_pager"]/a[@class="next pagination-item "]/@href')
        if next_page:
            next_page = response.urljoin(next_page.extract_first())
            yield  scrapy.Request(url=next_page,callback=self.parse)
    def parser2(self,contents):
        print('进入了:',contents.url,'页面')
        item = contents.meta.get('data')
        content = contents.xpath('.//div[@class="d_post_content j_d_post_content "]/text()').extract()
        i = ''
        n = 1
        for l in content:
            floor = '第{}楼:'.format(n)
            i = i + floor+l.strip()
            n += 1
        item['content'] = i
        print(contents.url)
        yield item

在items.py文件中,items.py中定义了各爬虫相对应的Item类,继承scrapy.Item类,每一个字段都是scrapy.Field()的对象。
在这里插入图片描述
在pipelines.py文件中定义了关于数据的处理方式。到底是丢弃还是去重还是保存。
在使用之前先要在settings.py文件中将有关item pipeline的设置打开。
在这里插入图片描述注意在这里key值由三个部分组成,包名,文件名,类名。不要写错,value值为数字,在1-1000之间取值,值越小优先级越高。
pipelines.py文件中对数据的处理可以见下面的代码:

如果是写入文件中有下面两种写法

第一种方法:
class GolangSpiderPipeline(object):
    def __init__(self):
        os.remove('baidu.json')
        self.file = open('baidu.json','a',encoding='utf-8')
    def process_item(self,item,spider):
        str = json.dumps(dict(item),ensure_ascii=False)+'\n'
        self.file.write(str)
        # json.dump(dict(item),open('tieba.json','a',encoding='utf-8'),ensure_ascii=False)
        return item
    def close_spider(self,spider):
        self.file.close()
第二种方法:
class GolangSpiderPipeline(object):
    def process_item(self,item,spider):
        fp = open('tieba.json', 'a', encoding='utf-8')
        json.dump(dict(item),fp,ensure_ascii=False)
        fp.write('\n')
        return item

如果是存入数据库可以见下面的代码(以MongoDB为例):

class GolangSpiderPipeline(object):
    def __init__(self):
        # 连接数据库,库和表如果没有会自动创建
        self.client = pymongo.MongoClient('localhost', 27017)
        # 选择库名
        self.db = self.client['Golang']
        #  查询数据db.baidu.find()
        # 使用数据库use dbname
    def process_item(self,item,spider):
        # baidu为库中的表名
        self.db.baidu.insert(dict(item))
        return item
    def close_spider(self,spider):
        self.client.close()

到此,一个完整的爬虫框架已经结束了,在没有反爬措施的网站中,是完全可以提取到我们想要的各种信息的。

3.Logging

Scrapy 提供了 log 功能, 可以通过 logging 模块使用。
可以修改配置文件 settings.py, 任意位置添加下面两行, 效果会清爽很多。

LOG_FILE = "baidu.log"
LOG_LEVEL = "INFO"

Log levels
Scrapy 提供 5 层 logging 级别:
CRITICAL - 严重错误(critical)
ERROR - 一般错误(regular errors)
WARNING - 警告信息(warning messages)
INFO - 一般信息(informational messages)
DEBUG - 调试信息(debugging messages)
设置了级别之后,该日志文件便只会记录此等级及以上的错误日志。

logging 设置
通过在 setting.py 中进行以下设置可以被用来配置 logging:
LOG_ENABLED 默认: True, 启用 logging
LOG_ENCODING 默认: ‘utf-8’, logging 使用的编码
LOG_FILE 默认: None, 在当前目录里创建 logging 输出文件的文件名
LOG_LEVEL 默认: ‘DEBUG’, log 的最低级别
LOG_STDOUT 默认: False 如果为 True, 进程所有的标准输出(及错误)将会被重定向到
log 中。 例如, 执行 print “hello” , 其将会在 Scrapy log 中显示。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值