scrapy框架

1. 安装scrapy模块

1.
pip install wheel
安装这个模块是为安装twisted做准备, 因为安装twisted需要用到wheel
2.
下载twisted, 因为scrapy是基于twisted的异步非阻塞框架
https://www.lfd.uci.edu/~gohlke/pythonlibs/#twisted
下载和python版本, 操作系统位数对应
3. 
安装twisted, 进入到下载的目录
pip install twisted
4.
pip install pywin32
5.
pip install scrapy

 

2. 创建一个scrapy项目

在终端中执行下面命令创建一个scrapy项目

D:\OneDrive - hk sar baomin inc\Python\project\Reptile\day06>scrapy startproject testDemo
New Scrapy project 'testDemo', using template directory 'c:\\python36\\lib\\site-packages\\scrapy\\templates\\project', created in:
    D:\OneDrive - hk sar baomin inc\Python\project\Reptile\day06\testDemo

You can start your first spider with:
    cd testDemo
    scrapy genspider example example.com

 

3. 创建一个scrapy爬虫

cd testDemo
D:\OneDrive - hk sar baomin inc\Python\project\Reptile\day06\testDemo>scrapy genspider test www.baidu.com Created spider 'test' using template 'basic' in module: testDemo.spiders.test

 

4. scrapy框架的目录结构

  scrapy.cfg
│
└─testDemo
    │  items.py    # item对象, 用于数据持久化数据传递
    │  middlewares.py    # 中间件文件
    │  pipelines.py    # 管道文件
    │  settings.py    # 配置文件__init__.py
    │
    ├─spiders    #具体的爬虫文件目录
    │  │  test.py    # 这是刚创建的爬虫文件
    │  │  __init__.py
    │  │
    │  └─__pycache____init__.cpython-36.pyc
    │
    └─__pycache__
            settings.cpython-36.pyc
            __init__.cpython-36.pyc

 

5. 爬虫文件

# -*- coding: utf-8 -*-
import scrapy


class TestSpider(scrapy.Spider):
    name = 'test'  # 爬虫文件名称
    allowed_domains = ['www.baidu.com']  # 允许爬取的域名
    start_urls = ['http://www.baidu.com/']  # 起始URL列表

    def parse(self, response):
        """
        用于解析请求后得到的数据
        :param response: 服务器响应的数据
        :return: item对象, 用于持久化存储
        """
        # response.text     # 获取响应的字符串
        # response.url  # 请求的URL
        # response.xpath()  # 使用xpath对数据进行解析
        # response.meta  # 用作请求传参, time_out, proxy等参数都会放在这里
        pass

 

6. scrapy数据持久化

 在scrapy中对数据进行持久化存储需要用到item, 因为管道中只能对item对象进行持久化存储, 所以要先创建item类

然后实例化item对象, 将要持久化的数据封装到item对象中, 然后将item返回出来

item类

import scrapy


class TestdemoItem(scrapy.Item):
    """
    这个类的作用有点类似于django的model模型类
    """
    content = scrapy.Field()  # 要在item对象中封装的数据

爬虫文件

import scrapy
from testDemo.items import TestdemoItem # 导入item类


class TestSpider(scrapy.Spider):
    name = 'test'  # 爬虫文件名称
    allowed_domains = ['www.baidu.com']  # 允许爬取的域名
    start_urls = ['http://www.baidu.com/']  # 起始URL列表

    def parse(self, response):
        content = response.xpath('//div[@class="content"]/text()').extract_first()
        item = TestdemoItem()   # 实例化item对象
        item["content"] = content   # 将数据封装到item对象中
        yield item  # 将item对象返回出去

管道文件

class TestdemoPipeline(object):
    def open_spider(self, spider):
        """
        在爬虫程序启动的时候会调用这个函数
        可以在这里进行数据库的连接等 
        :param spider: 
        :return: 
        """
        pass

    def process_item(self, item, spider):
        """
        这里由来处理item对象, 对数据进行持久化操作
        :param item: 爬虫文件yield的item对象
        :param spider: 爬虫类对象
        :return: 
        """
        with open("./text.log", mode="w", encoding="utf-8") as f:
            f.write(item["content"])
        return item  # 将item对象返回出去, 因为在配置文件中可能还有其他的管道类需要对数据进行持久化

    def close_spider(self, spider):
        """
        爬虫程序执行完毕后, 会调用这个函数
        可以在可以进行断开数据库连接等归还系统资源等操作
        :param spider: 
        :return: 
        """
        pass

关于数据持久化的配置

# 关于管道的配置
# 可以配置多个, 
# {管道类的路径: 该管道类的执行优先级}
ITEM_PIPELINES = {
   'testDemo.pipelines.TestdemoPipeline': 300,
}

 

7. 启动爬虫程序

scrapy crawl text --nolog     # --nolog: 不输出日志信息

 

8. scrapy手动发送请求

现在使用scrapy进行数据的爬取, 发现自己并没有发送get, post等请求, 只是指定了URL, 然后对数据进行解析, 然后将数据持久化

但是在有些时候是需要发送额外的请求才能获取到数据, 比如, 爬取图片的时候, get请求获取到图片列表, 但是这些图片都是一些小图

想要爬取到大图就需要再次发送请求, 才能获取到大图的连接

还有就是在处理分页的时候, 需要重新发送请求来获取下一页的数据

手动发送get请求

    def parse(self, response):
        scrapy.Request(url="http://www.baidu,com", callback=self.parse)  # 发送get请求

手动发送post请求

class PostSpider(scrapy.Spider):
    name = 'post'
    # allowed_domains = ['www.xxx.com']
    start_urls = ['https://fanyi.baidu.com/sug']

    def start_requests(self):
        """
        重写父类的方法, 原本这个方式是发送get请求的, 现在重写后就变成了发送post请求了
        :return:
        """
        for url in self.start_urls:
            yield scrapy.FormRequest(url=url, callback=self.parse, formdata=self.data())
            # 使用scrapy发送post请求, 注意使用yield

    def parse(self, response):
        print(json.loads(response.text))
        # response.text获取响应对象内容

    def data(self):
        form_data = {
            "kw": "cat"
        }
        return form_data

 

6. scrapy运行流程(核心组件)

 

7. scrapy请求传参的用途

scrapy日志相关配置

8. 如何提升scrapy的爬取效率

9. 基于UA池和ip代理池爬取数据

posted @ 2018-12-04 22:21  王剑威  阅读(451)  评论(0编辑  收藏  举报