scrapy的入门使用

学习目标:
  1. 掌握 scrapy的安装
  2. 应用 创建scrapy的项目
  3. 应用 创建scrapy爬虫
  4. 应用 运行scrapy爬虫
  5. 应用 解析并获取scrapy爬虫中的数据

1、scrapy项目实现流程

  1. 创建一个scrapy项目:scrapy startproject mySpider
  2. 生成一个爬虫:scrapy genspider myspider www.xxx.cn
  3. 提取数据:完善spider,使用xpath等方法
  4. 保存数据:pipeline中保存数据

2、安装

安装scrapy命令:

pip install scrapy==2.5.1
 pip install -i https://pypi.tuna.tsinghua.edu.cn/simple scrapy==2.5.1 
 pip install scrapy-redis==0.7.2

如果安装失败. 请先升级一下pip. 然后重新安装scrapy即可.

最新版本的pip升级完成后. 安装依然失败, 可以根据报错信息进行一点点的调整, 多试几次pip. 直至success.

注意:

如果上述过程还是无法正常安装scrapy, 可以考虑用下面的方案来安装:

  1. 安装wheel
pip install wheel
  1. 下载twisted安装包, https://www.lfd.uci.edu/~gohlke/pythonlibs/#twisted

Spider理论系列--Scrapy浅应用_scrapy

  1. 用wheel安装twisted.
pip install Twisted‑21.7.0‑py3‑none‑any.whl
  1. 安装pywin32
pip install pywin32
  1. 安装scrapy
pip install scrapy

总之, 最终你的控制台输入scrapy version能显示版本号. 就算成功了

3、创建scrapy项目

创建scrapy项目的命令:scrapy startproject +<项目名字>

示例:scrapy startproject myspider

生成的目录和文件结果如下:

Spider理论系列--Scrapy浅应用_scrapy_02

scrapy的核心组件

  • 引擎(Scrapy) 用来处理整个系统的数据流处理, 触发事务(框架核心)
  • 调度器(Scheduler) 用来接受引擎发过来的请求, 压入队列中, 并在引擎再次请求的时候返回. 可以想像成一个URL(抓取网页的网址或者说是链接)的优先队列, 由它来决定下一个要抓取的网址是什么, 同时去除重复的网址
  • 下载器(Downloader) 用于下载网页内容, 并将网页内容返回给蜘蛛(Scrapy下载器是建立在twisted这个高效的异步模型上的)
  • 爬虫(Spiders) 爬虫是主要干活的, 用于从特定的网页中提取自己需要的信息, 即所谓的实体(Item)。用户也可以从中提取出链接,让Scrapy继续抓取下一个页面
  • 项目管道(Pipeline) 负责处理爬虫从网页中抽取的实体,主要的功能是持久化实体、验证实体的有效性、清除不需要的信息。当页面被爬虫解析后,将被发送到项目管道,并经过几个特定的次序处理数据。

4、创建爬虫

命令:在项目路径下执行:scrapy genspider +<爬虫名字> + <允许爬取的域名>

示例:

  • scrapy startproject duanzi01
  • cd duanzi01/
  • scrapy genspider duanzi duanzixing.com

生成的目录和文件结果如下:

Spider理论系列--Scrapy浅应用_爬虫_03

5、完善spider

完善spider即通过方法进行数据的提取等操作

在duanzi.py中修改内容如下:

import scrapy
 
 # 自定义spider类,继承scrapy.spider
 class DuanziSpider(scrapy.Spider):
     # 爬虫名字
     name = 'duanzi'
     # 允许爬取的范围,防止爬虫爬到别的网站
     allowed_domains = ['duanzixing.com']
     # 开始爬取的url地址
     start_urls = ['http://duanzixing.com/']
 
     # 数据提取的方法,接受下载中间件传过来的response 是重写父类中的parse方法
     def parse(self, response, **kwargs):
         # 打印抓取到的页面源码
         # print(response.text)
         # xpath匹配每条段子的article列表
         article_list = response.xpath('//article[@class="excerpt"]')
         # print(article_list)
         # 循环获取每一个article
         for article in article_list:
             # 匹配标题
             # title = article.xpath('./header/h2/a/text()')
             # [<Selector xpath='./header/h2/a/text()' data='一个不小心就把2000块钱的包包设置成了50包邮'>]
             # title = article.xpath('./header/h2/a/text()')[0].extract()
             # 等同于
             title = article.xpath('./header/h2/a/text()').extract_first()
 
             # 获取段子内容
             con = article.xpath('./p[@class="note"]/text()').extract_first()
             print('title', title)
             print('con', con)

启动爬虫命令: scrapy crawl duanzi

response响应对象的常用属性

  • response.url:当前响应的url地址
  • response.request.url:当前响应对应的请求的url地址
  • response.headers:响应头
  • response.request.headers:当前响应的请求头
  • response.body:响应体,也就是html代码,byte类型
  • response.text 返回响应的内容 字符串
  • response.status:响应状态码
注意:
  1. response.xpath方法的返回结果是一个类似list的类型,其中包含的是selector对象,操作和列表一样,但是有一些额外的方法
  2. extract() 返回一个包含有字符串的列表
    如果使用列表调用extract()则表示,extract会将列表中每一个列表元素进行extract操作,返回列表
  3. extract_first() 返回列表中的第一个字符串,列表为空没有返回None
  4. spider中的parse方法必须有
  5. 需要抓取的url地址必须属于allowed_domains,但是start_urls中的url地址没有这个限制
  6. 启动爬虫的时候注意启动的位置,是在项目路径下启动

6、配置settings文件

  • ROBOTSTXT_OBEY = False
    robots是一种反爬协议。在协议中规定了哪些身份的爬虫无法爬取的资源有哪些。
    在配置文件中setting,取消robots的监测:
  • 在配置文件中配置全局的UA:USER_AGENT='xxxx'
  • 在配置文件中加入日志等级:LOG_LEVEL = 'ERROR' 只输出错误信息
    其它日志级别
  • CRITICAL 严重错误
  • ERROR 错误
  • WARNING 警告
  • INFO 消息
  • DEBUG 调试

代码实例

# Scrapy settings for mySpider project
 USER_AGENT = 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.4896.127 Safari/537.36'
 
 ROBOTSTXT_OBEY = False
 
 LOG_LEVEL = 'ERROR'

7、数据存储

7.1、使用终端命令行进行存储

  • 代码配置
    ITSpider.py
class ITSpider(scrapy.Spider):
     name = 'ITSpider'
     # allowed_domains = ['www.xxx.com']
     start_urls = ['https://duanzixing.com/page/2/']
 
     # 通过终端写入文件的方式
     def parse(self, response):
         article_list = response.xpath('/html/body/section/div/div/article')
         # 创建列表, 存储数据
         all_data = []
         for article in article_list:
             title = article.xpath('./header/h2/a/text()').extract_first()
             con = article.xpath('./p[2]/text()').extract_first()
             dic = {
                 'title': title,
                 'con': con
             }
             all_data.append(dic)
         return all_data
  • 终端命令
    scrapy crawl ITSpider -o ITSpider.csv
    将文件存储到ITSpider.csv 文件中

7.2、利用管道pipeline来处理(保存)数据(写入文件中)

先跟着配置 后面会单讲

代码配置

  • 打开items.py文件 添加如下代码
    items.py
import scrapy
 
 
 class MyspiderItem(scrapy.Item):
     # define the fields for your item here like:
     # name = scrapy.Field()
     title = scrapy.Field()
     con = scrapy.Field()
  • ITSpider.py
import scrapy
 from myspider.items import MyspiderItem
 
 class ITSpiderSpider(scrapy.Spider):
     name = 'ITSpider'
     # allowed_domains = ['www.xxx.com']
     start_urls = ['https://duanzixing.com/page/2/']
 
     # 写入管道 持久化存储
     def parse(self, response):
         article_list = response.xpath('/html/body/section/div/div/article')
         for article in article_list:
             title = article.xpath('./header/h2/a/text()').extract_first()
             con = article.xpath('./p[2]/text()').extract_first()
             item = DuanziproItem()
             item['title'] = title
             item['con'] = con
             yield item

在爬虫文件ITSpider.py中parse()函数中最后添加

yield item

思考:为什么要使用yield?

  1. 让整个函数变成一个生成器,有什么好处呢?
  2. 遍历这个函数的返回值的时候,挨个把数据读到内存,不会造成内存的瞬间占用过高
  3. python3中的range和python2中的xrange同理

注意:yield能够传递的对象只能是:BaseItem,Request,dict,None

  • 打开管道文件 pipelines.py 添加如下代码
    pipelines.py
class ITSpiderPipeline:
     f = None
     def open_spider(self, spider):
         print('爬虫开始时被调用一次')
         self.f = open('./duanzi.text', 'w')
         
     # 爬虫文件中提取数据的方法每yield一次item,就会运行一次
     # 该方法为固定名称函数
     def process_item(self, item, spider):
         print(item)
         self.f.write(item['title']+item['con']+'\n')
         return item
 
     def close_spider(self, spider):
         print('爬虫结束时被调用')
         self.f.close()
  • open_spider方法
    重写父类中open_spider方法 只有爬虫开始十被调用一次
  • close_spider 方法
    重写父类中lose_spider方法 爬虫结束时被调用一次
  • 在settings.py设置开启pipeline
    将默认被注释的管道打开
ITEM_PIPELINES = {
    'myspider.pipelines.MyspiderPipeline': 300,
 }

其中数值代表优先级 数值越小优先级越高

8、运行scrapy

命令:在项目目录下执行scrapy crawl +<爬虫名字>

示例:scrapy crawl ITSpider

9、总结

  1. srapy的安装:pip install scrapy
  2. 创建scrapy的项目: scrapy startproject myspider
  3. 创建scrapy爬虫:在项目目录下执行 scrapy genspider ITSpider www.xxx.cn
  4. 运行scrapy爬虫:在项目目录下执行 scrapy crawl ITSpider
  5. 解析并获取scrapy爬虫中的数据:
  1. response.xpath方法的返回结果是一个类似list的类型,其中包含的是selector对象,操作和列表一样,但是有一些额外的方法
  2. extract() 返回一个包含有字符串的列表
  3. extract_first() 返回列表中的第一个字符串,列表为空没有返回None
  1. scrapy管道的基本使用:
  1. 完善pipelines.py中的process_item函数
  2. 在settings.py中设置开启pipeline