公众号:uncle39py

V1

2022/01/05阅读:49主题:默认主题

scrapy框架

此处缺图,请移步公众号 uncle39py 观看

scrapy初识

scrapy是一个爬虫框架。它是一个异步框架,即请求发出去后程序并不阻塞着,而是继续往下运行(高效)。

对框架二字的理解,就像一个大的中央帝国,有各个部门应对不同类型的日常事务,保证大一统国家的正常运转。

而requests+bs4这样的是一个个模块,只能处理和应对某一个专门的领域,当一个个模块能够无缝衔接,应对一个个不同类型的问题时,整体上就成了一个框架。

一、scrapy运行流程

看图中的序号和主件。

  • SPIDER:爬虫,用于发出各个请求;用于解析数据。是开发人员自定义的类

  • ENGINE:引擎,理解成调度机制(大总管),当序号1来的请求进入到ENGINE,就会被识别为请求并经过序号2被放到调度器中。

  • SCHEDULER:调度器,涉及爬取顺序:队列(广度优先)、堆栈(深度优先),将准备好的请求一个个丢给ENGINE(序号3)

  • DOWNLOADER:下载器,下载网页内容。途径4和5是下载中间件,对请求和响应做拦截,比如对请求统一的加头、加代理或者集成selenium自己爬取。经过序号5回到ENGINE中,被ENGINE识别为响应,就又回到SPIDERS中做解析。当解析出来的是请求则沿着1继续循环,当解析出来的是数据则沿着7、8将数据写到文件或者数据库中。

  • ITEM PIPELINES:管道,负责数据的清洗和入库

二、安装

pip3 install scrapy

windows上会有少部分人安装不上,可以按照下面的步骤处理

1、pip3 install wheel #安装后,就支持通过wheel文件安装软件,wheel文件官网:https://www.lfd.uci.edu/~gohlke/pythonlibs
2、pip3 install lxml
3、pip3 install pyopenssl
4、下载并安装pywin32:https://sourceforge.net/projects/pywin32/files/pywin32/
5、下载twisted的wheel文件:http://www.lfd.uci.edu/~gohlke/pythonlibs/#twisted
6、执行pip3 install 下载目录\Twisted-17.9.0-cp36-cp36m-win_amd64.whl
7、pip3 install scrapy

三、创建

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

2、创建爬虫:scrapy genspider 爬虫名 要爬取的地址

爬虫隶属于项目,一个项目下可以有多个爬虫,这就类似于Django项目和其下app的关系。

3、运行爬虫:

scrapy crawl 爬虫名 带运行日志

scrapy crawl 爬虫名 --nolog 不带运行日志

crawl的英语翻译:爬行

4、支持鼠标右键执行爬虫程序

在项目的目录下新建一个run.py(名字自取),这样就可以鼠标右键执行这个py文件

from scrapy.cmdline import execute
execute(['scrapy','crawl','chouti'])
# chouti是爬虫名

四、目录介绍

如图:

五、SPAIDER

在来看这流程张图,通过上面写的三>2创建爬虫后,会自动在spiders目录里面新建一个爬虫(py文件),爬虫的默认代码是这样的:

其中,parse函数对应流程图的序号6,在parse函数里面对取回的响应数据做解析。

在这里面一般有两类型的操作,一是用自带的解析器或第三方解析器对响应数据response.text做解析;二是yield一个新的请求地址,ENGINE会根据这个请求自动走完序号1-5的步骤,同样会再次把响应数据带回parse里面做解析。

1、两种自动的解析器:css和xpath。

title_list = response.css('.link-title')
title_list = response.xpath('//a[contains(@class,"link-title")]')

之后还需要掌握:取文本、取属性

#xpath:
response.xpath('//a[contains(@class,"link-title")]/text()').extract()  # 取文本
response.xpath('//a[contains(@class,"link-title")]/@href').extract()  #取属性

#css
response.css('.link-title::text').extract()  # 取文本
response.css('.link-title::attr(href)').extract_first()  # 取属性

#extract英语翻译:提取、提炼。extract()取出来的是列表,哪怕只有一个值也是列表

六、settings.py

先看这三个参数

#是否遵循爬虫协议。每个网站url加上/robots.txt就可以查看该网站官方允许爬取的内容。
#下面这个参数设置为False代表不遵循这个协议。
ROBOTSTXT_OBEY = False

USER_AGENT = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36'

#配置日志级别,这样只有错误信息能打出来,其他info信息不需要打印出来。这个参数是自己添加的
LOG_LEVEL = 'ERROR'

七、持久化的两种方案

方案一:parser函数必须返回列表套字典的形式(少用,了解)

通过命令保存为csvscrapy crawl chouti -o chouti.csv

import scrapy
from myscrapy.items import ChoutiItem

class ChoutiSpider(scrapy.Spider):
    name = 'chouti'
    allowed_domains = ['dig.chouti.com']
    start_urls = ['https://dig.chouti.com/']
    
    def parse(self, response):
        ll = []
        div_list=response.xpath('//div[contains(@class,"link-item")]')
        for div in div_list:
            title=div.css('.link-title::text').extract_first()
            url=div.css('.link-title::attr(href)').extract_first()
            photo_url=div.css('.image-scale::attr(src)').extract_first()
            # 持久化:方案一(用的少)parser必须返回列表套字典的形式
            ll.append({'title':title,'url':url,'photo_url':photo_url})
        return ll

方案二:使用piplines与items存储(mysql,redis,文件)

1、items类(类似与django中的models角色,承接数据)

class ChoutiItem(scrapy.Item):
    #三个都是一样的
    title = scrapy.Field()
    url = scrapy.Field()
    photo_url = scrapy.Field()

2、spider类,对start_urls发出请求,在parse中做数据解析

class ChoutiSpider(scrapy.Spider):
    name = 'chouti'
    allowed_domains = ['dig.chouti.com']
    start_urls = ['https://dig.chouti.com/']

    def parse(self, response):

        div_list=response.xpath('//div[contains(@class,"link-item")]')
        for div in div_list:
            item = ChoutiItem()
            title=div.css('.link-title::text').extract_first()
            url=div.css('.link-title::attr(href)').extract_first()
            photo_url=div.css('.image-scale::attr(src)').extract_first()
            # 注意:这里只能使用中括号这种方式,不能用.
            item['url'] = url
            item['title'] = title
            item['photo_url'] = photo_url
            # 只能使用yield,每次返回一个item
            yield item 

3、setting中配置ITEM管道(数字越小,级别越高)

ITEM_PIPELINES = {
   'myscrapy.pipelines.ChoutiMysqlPipeline'300,
}

4、在pipelines.py中写3指定的管道类ChoutiMysqlPipeline

这里涉及三个方法

  • open_spider:开始持久化的时候执行一次,一般用于打开文件或者建立数据库连接
  • process_item:在这儿做持久化操作,步骤2 spider中yield一个item就持久化一次,直到全部持久化完
  • close_spider:持久化结束完后执行一次,一般用于关闭文件或者断开数据库连接
import pymysql
class ChoutiMysqlPipeline:
    def open_spider(self,spider):
        self.conn = pymysql.connect(user='root',
                               password="root",
                               host='127.0.0.1',
                               database='chouti',
                               port=3306,)

    def process_item(self, item, spider):
        cursor = self.conn.cursor()
        sql = 'insert into article (title,url,photo_url)values(%s,%s,%s) '
        cursor.execute(sql, [item['title'], item['url'], item['photo_url']])
        self.conn.commit()
        return item

    def close_spider(self,spider):
        self.conn.close()

分类:

后端

标签:

Python

作者介绍

公众号:uncle39py
V1