scrapy架构、目录结构与配置文件、持久化、动作链

scrapy架构、目录结构与配置文件、持久化、动作链

1. scrapy框架的安装与启动

Scrapy 是基于twisted框架开发而来,twisted是一个流行的事件驱动的python网络框架。因此Scrapy使用了一种非阻塞(又名异步)的代码来实现并发。号称爬虫界的Django

1. 安装

-mac,linux平台:pip3 install scrapy
-windows平台:pip3 install scrapy(大部分人可以)
  - 如果失败:
      1、pip3 install wheel #安装后,便支持通过wheel文件安装软件,wheel文件官网:https://www.lfd.uci.edu/~gohlke/pythonlibs
      3、pip3 install lxml
      4、pip3 install pyopenssl
      5、下载并安装pywin32:https://sourceforge.net/projects/pywin32/files/pywin32/
      6、下载twisted的wheel文件:http://www.lfd.uci.edu/~gohlke/pythonlibs/  #twisted
      7、执行pip3 install 下载目录\Twisted-17.9.0-cp36-cp36m-win_amd64.whl
      8、pip3 install scrapy

2. 创建项目

1、创建scrapy项目:scrapy startproject 项目名

2、创建爬虫:scrapy genspider 爬虫文件名 要爬的网址      # 可以创建多个爬虫

3. 启动爬虫

方式一:命令行启动

scrapy crawl 爬虫文件名

或者:scrapy crawl 爬虫文件名 --nolog       # 不打印日志启动

方式二:创建文件启动

在项目目录路径下创建一个main.py的文件,右键run即可

在文件中配置以下代码

from scrapy.cmdline import execute
# execute(['scrapy','crawl','爬虫文件名'])
# execute(['scrapy','crawl','chouti','--nolog'])
execute(['scrapy','crawl','chouti'])

2. scrapy配置文件与目录

1. 目录结构

-crawl_chouti   # 项目名
    -crawl_chouti # 跟项目一个名,文件夹
        -spiders    # spiders:放着爬虫  genspider生成的爬虫,都放在这下面
            -__init__.py
            -chouti.py # 抽屉爬虫
            -cnblogs.py # cnblogs 爬虫
        -items.py     # 对比django中的models.py文件 ,写一个个的模型类
        -middlewares.py  # 中间件(爬虫中间件,下载中间件),中间件写在这
        -pipelines.py   # 写持久化的地方(持久化到文件,mysql,redis,mongodb)
        -settings.py    # 配置文件
    -scrapy.cfg       # 不用关注,上线相关的
    -main.py    # 手动创建的启动文件

2. 配置文件

ROBOTSTXT_OBEY = False   # 是否遵循爬虫协议,强行运行
USER_AGENT = 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.149 Safari/537.36'    # 请求头中的ua
LOG_LEVEL='ERROR' # 这样配置,程序错误信息才会打印,
    #启动爬虫直接 scrapy crawl 爬虫名   就没有日志输出
  # scrapy crawl 爬虫名 --nolog

3. 爬虫文件

class ChoutiSpider(scrapy.Spider):
    name = 'chouti'   # 爬虫名字
    allowed_domains = ['https://dig.chouti.com/']  # 允许爬取的域,一般注释了
    start_urls = ['https://dig.chouti.com/']   # 起始爬取的位置,爬虫一启动,会先向它发请求

    def parse(self, response):  # 解析,请求回来,自动执行parser,在这个方法中做解析
        print('------返回的数据-----',response)

3. scrapy架构

1. 爬虫发起请求requests经过engine引擎

2. engine发送到调度器scheduler进行排队,去重

3. 将排好队的请求再次发给引擎engine

4. 引擎将请求经过下载中间件(加头,加代理,加cookie,集成selenium)给下载器,异步发请求

5. 将返回的数据经过中间件返回给引擎

6. 引擎将返回的数据经过爬虫中间件返回给解析

7. 解析后将数据再次经过爬虫中间件给引擎,如果解析的数据中还有请求requests对象会继续走2 3 4 5 6 7 8 

8. 引擎将items对象到项目管道做清理,持久化

# 引擎(ENGINE)(大总管)
引擎负责控制系统所有组件之间的数据流,并在某些动作发生时触发事件。
有关详细信息,请参见上面的数据流部分。
# 调度器(SCHEDULER) 用来接受引擎发过来的请求, 压入队列中, 并在引擎再次请求的时候返回.
可以想像成一个URL的优先级队列, 由它来决定下一个要抓取的网址是什么, 同时去除重复的网址
# 下载器(DOWLOADER) 用于下载网页内容, 并将网页内容返回给EGINE,下载器是建立在twisted这个高效的异步模型上的 # 爬虫(SPIDERS) SPIDERS是开发人员自定义的类,用来解析responses,并且提取items,或者发送新的请求 # 项目管道(ITEM PIPLINES) 在items被提取后负责处理它们,主要包括清理、验证、持久化(比如存到数据库)等操作 # 两个中间件 -爬虫中间件 位于EGINE和SPIDERS之间,主要工作是处理SPIDERS的输入(即responses)和输出(即requests -下载中间件 位于Scrapy引擎和下载器之间,主要用来处理从EGINE传到DOWLOADER的请求request,已经从DOWNLOADER传到EGINE的响应response
  (用的最多,加头,加代理,加cookie,集成selenium)

4. 解析数据

    def parse(self, response):  # 解析,请求回来,自动执行parser,在这个方法中做解析
        # 解析 方式一:使用bs4解析
        # from bs4 import BeautifulSoup
        # soup=BeautifulSoup(response.text,'lxml')
        # soup.find_all()

        # 方式二:使用内置的css解析器
        # css与xpath解析后的数据都放在列表中
        # 取第一个:extract_first()
        # 取出所有的extract()
        # css选择器取文本和属性:
            # .link-title::text
            # .link-title::attr(href)
        div_list = response.css('div.link-item')
        for div in div_list:
            title = div.css('.link-title::text').extract_first()
            url = div.css('.link-title::attr(href)').extract_first()
            if 'http' not in url:
                url = 'https://dig.chouti.com/'+url
            img_url = div.css('.image-scale::attr(src)').extract_first()
            if not img_url:
                img_url = div.css('.image-item::attr(src)').extract_first()
            print('''
            新闻标题:%s
            新闻连接:%s
            新闻图片:%s
            ''' % (title, url, img_url))

        # 方式三:使用内置的xpath解析
        # css与xpath解析后的数据都放在列表中
        # 取第一个:extract_first()
        # 取出所有的extract()
        # xpath选择器取文本和属性:
            # /text()
            # /@属性名
        div_list = response.xpath('//div[contains(@class,"link-item")]')
        for div in div_list:
            title = div.xpath('.//a[contains(@class,"link-title")]/text()').extract_first()
            url = div.xpath('.//a[contains(@class,"link-title")]/@href').extract_first()
            # if 'http' not in url:
            #     url = 'https://dig.chouti.com/' + url
            img_url = div.xpath('.//*[contains(@class,"image-scale")]/@src').extract_first()
            # if not img_url:
            #     img_url = div.xpath('.//*[contains(@class,"image-item")]/@src').extract_first()
            print('''
            新闻标题:%s
            新闻连接:%s
            新闻图片:%s
            ''' % (title, url, img_url))

5. 持久化

方式一(了解):

1 parser解析函数,return 列表,列表套字典
2 命令行持久化到文件中:scrapy crawl chouti -o aa.json   (支持:('json', 'jsonlines', 'jl', 'csv', 'xml', 'marshal', 'pickle')

方式二(重点):piplines的方式

1. 在items.py中创建模型类

class ChoutiItem(scrapy.Item):
    id = scrapy.Field()
    title = scrapy.Field()
    url = scrapy.Field()
    img_url = scrapy.Field()

2. 在爬虫文件中引入item对象,把数据放到item对象中(要用中括号)

            from day04.chouti.chouti.items import ChoutiItem
            item = ChoutiItem()

            item['id'] = id
            item['title'] = title
            item['url'] = url
            item['img_url'] = img_url
            yield item  # 注意要用yield

3. 在配置文件中配置管道

       ITEM_PIPELINES = {
        # 数字表示优先级(数字越小,优先级越大)
       'crawl_chouti.pipelines.CrawlChoutiPipeline': 300,
       'crawl_chouti.pipelines.CrawlChoutiRedisPipeline': 301,
        }

4. piplines.py中写持久化类

写 open_spider 与 close_spider 方法,在 process_item 中写保存到哪

class ChoutiRedisPipeline(object):
    def open_spider(self, spider):
        print('redis开始')
        self.conn = redis.Redis(password='2694')

    def process_item(self, item, spider):
        import json
        s = json.dumps({'title':item['title'], 'url':item['url'], 'img_url':item['img_url']})
        self.conn.hset('chouti_aritcle',item['id'], s)
        print('redis')
        return item  # 表示继续往下走

    def close_spider(self, spider):
        print('redis结束')
        self.conn.close()

6. 动作链

from selenium.webdriver import ActionChains
# 1 生成一个动作练对象
action=ActionChains(bro)
# 2 点击并夯住某个控件
action.click_and_hold(div)
# 3 移动方式(三种方式)
# action.move_by_offset(x, y) # 通过坐标偏移
# action.move_to_element(x, y) # 到另一个标签
# action.move_to_element_with_offset(x, y) # 到另一个标签,再偏移一部分

# 4 真正移动
action.perform()

# 5 释放控件(松开鼠标)
action.release()

 

posted @ 2020-04-10 21:15  Mr沈  阅读(680)  评论(0编辑  收藏  举报