Python网络爬虫(十八)——Scrapy基本使用

因为 Scrapy 作为爬虫的一个工具来说功能比较强大,这里会分几篇文章来说明。

创建项目

Scrapy 的项目构建是通过终端完成的,在要放置项目的目录下执行:

scrapy startproject projectname

此时就在终端当前的目录下创建了名为 projectname 的项目。

项目结构

项目构建后,会自动生成一系列文件,这些文件共同构成了该爬虫项目,文件主要有:

  • items.py:用来存放爬虫获取的数据模型,也就是事先对数据结构进行定义
  • middlewares.py:用来存放 middlewares 的文件,包括 Downloader middlewares 和 Spider middlewares
  • pipelines.py:用来将 items.py 中的数据模型进行存储
  • settings.py:爬虫的配置信息(delay,pipeline,headers等)
  • scrapy.cfg:项目配置文件
  • spider 文件夹:爬虫文件夹

创建爬虫

虽然可以手动在 spider 下建立自己的爬虫,但是 Scrapy 中也提供了命令能够自动地生成爬虫文件:

scrapy genspider spiderfilename domainname
  • spiderfilename:说明了爬虫的文件名
  • domainname:则表示该爬虫要爬取的域名,也就是说要爬取位于该域名下的资源

执行上述命令之后,会生成与名为 spiderfilename 的 py 文件,文件中主要包含:

import scrapy

class spiderfilename(scrapy.Spider):
    name = 'spiderfilename'
    allowed_domains = ['domainname']
    start_urls = ['domainname']

    def parse(self, response):
        pass

上边的程序就定义了一个爬虫,Scrapy 中的爬虫使用类实现,该类继承自 scrapy.Spider,类中的数据成员和函数为:

  • name:爬虫名
  • allowed_domains:即创建爬虫的域名,该爬虫只会爬取该域名下的网页
  • start_urls:爬虫开始的 url,其实不一定是 domainname,但一定是 domainname 下的网页
  • parse:根据 Scrapy 的框架,Engine 会将 Downloader 返回的响应数据返回给 Spider 解析,而爬虫再将数据传递给 parse 方法。同样从 Scrapy 的框架来看,该函数的作用主要为:提取数据和生成下一个请求

爬虫构建完成之后,需要在终端执行命令来运行程序:

scrapy crawl spidername

通过上边的命令能够执行名为 spidername 的爬虫,但每次运行爬虫如果都需要在终端中执行命令的话,不断进行界面切换和代码调试都会显得比较麻烦,因此可以选择在项目目录下构建 py 文件,然后使用 cmdline 模块直接运行:

from scrapy import cmdline

cmdline.execute("scrapy crawl spidername".split())

这样就省掉了界面切换的步骤,也提高了代码调试的效率。

settings.py

该文件中包含了关于爬虫的一些设置,这里有几个选项需要进行设置:

  • ROBOTSTXT_OBEY:设置为 False,否则为 True。True 表示遵守机器协议,此时爬虫会首先找 robots.txt 文件,如果找不到则会停止
  • DEFAULT_REQUEST_HEADERS:默认请求头,可以在其中添加 User-Agent,表示该请求是从浏览器发出的,而不是爬虫
  • DOWNLOAD_DELAY:表示下载的延迟,防止过快
  • ITEM_PIPELINES:启用 pipelines.py

spiders

spiders 文件夹中的文件内容为:

# -*- coding: utf-8 -*-
import scrapy
from base.items import BaseItem


class QsbkSpider(scrapy.Spider):
    name = 'qsbk_spider'
    allowed_domains = ['www.qiushibaike.com']
    start_urls = ['http://www.qiushibaike.com/text/page/1/']
    base_url = 'http://www.qiushibaike.com'

    def parse(self, response):
        res_parse = response.xpath("//div[@class='col1 old-style-col1']/div")
        for res in res_parse:
            author = res.xpath("./div[@class='author clearfix']//img/@alt").get()
            content = res.xpath(".//div[@class='content']//text()").getall()
            content = ''.join(content).replace('\n','')
            item = BaseItem(author=author,content=content)
            yield item

        next_url = self.base_url+response.xpath("//ul[@class='pagination']/li[last()]/a/@href").get()
        if not next_url:
            return
        else:
            yield scrapy.Request(next_url,callback=self.parse)

上边的程序主要分为两部分:

  • for 循环内部为解析 response,该 response 来自 Downloader,然后将生成的 item 传递到 pipelines.py
  • for 循环后的内容为生成下一个请求,然后通过 scrapy.Request 继续回调到 parse

items.py

# -*- coding: utf-8 -*-

# Define here the models for your scraped items
#
# See documentation in:
# https://docs.scrapy.org/en/latest/topics/items.html

import scrapy


class BaseItem(scrapy.Item):
    # define the fields for your item here like:
    # name = scrapy.Field()
    author = scrapy.Field()
    content = scrapy.Field()

该文件中定义了数据模型,对应的是从 spider 中传回的 item。

pipelines.py

# -*- coding: utf-8 -*-

# Define your item pipelines here
#
# Don't forget to add your pipeline to the ITEM_PIPELINES setting
# See: https://docs.scrapy.org/en/latest/topics/item-pipeline.html
from scrapy.exporters import JsonLinesItemExporter


class BasePipeline(object):
    def __init__(self):
        self.fp = open('joke.json','wb')
        self.exporter = JsonLinesItemExporter(self.fp,ensure_ascii=False,encoding='utf-8')

    def open_spider(self,spider):
        print('Spider start.')

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

    def close_spider(self,spider):
        print('Spider end.')

上面的代码中存在三个固定含义的函数:

  • open_spider:在 spider 开始执行之前先被执行
  • process_item:spider 返回 item 后执行,可以进行数据的存储
  • close_spider:在 spider 执行完毕之后执行

数据的存储可以采用 JSON,或者是 Scrapy.exporters 中的 JsonItemExporter,JsonLinesItemExporter 等,在 Scrapy.exporters 中定义了很多种数据存储的格式。

然后该项目就能够直接运行,爬取指定的网页信息了。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章