python之Srcapy框架浅谈

Scrapy介绍

Scrapy是⼀个为了爬取⽹站数据,提取结构性数据⽽编写的应⽤框架,让爬虫更快,更强大。用更少代码,实现更多灵活的功能。内部封装了Twisted(内部源码采用了闭包)异步网络框架。

框架和模块的区别

框架是软件框架是项目软件开发过程中提取特定领域软件的共性部分形成的体系结构,不同领域的软件项目有着不同的框架类型。框架不是现成可用的应用系统,而是一个半成品,是一个提供了诸多服务,供开发人员进行二次开发,实现具体功能的应用系统。
模块是指的一段能够实现某个有价值目标的的成员代码段,这样的东西,我们还有另一个称呼:例程,而例程有两种,即函数和过程。定义模块的原则应该是:高内聚和低耦合。

源安装

临时使用:

可以在使用pip的时候,加上参数-i和镜像地址(如
https://pypi.tuna.tsinghua.edu.cn/simple),
例如:pip install -i https://pypi.tuna.tsinghua.edu.cn/simple pandas,这样就会从清华镜像安装pandas库。

pip install 包名 -i http://pypi.douban.com/simple
比较常用的国内镜像包括:

名称地址
清华大学https://pypi.tuna.tsinghua.edu.cn/simple/
阿里云http://mirrors.aliyun.com/pypi/simple/
豆瓣http://pypi.douban.com/simple/
科学技术大学http://pypi.mirrors.ustc.edu.cn/simple/

永久修改:

  • Linux操作系统

修改 ~/.pip/pip.conf (没有就创建一个文件夹及文件。文件夹要加“.”,表示是隐藏文件夹)
内容如下:

[global]
index-url = https://pypi.tuna.tsinghua.edu.cn/simple
[install]
trusted-host = https://pypi.tuna.tsinghua.edu.cn

  • windows操作系统

直接在user目录中创建一个pip目录,如:C:\Users\xx\pip,然后新建文件pip.ini,即 %HOMEPATH%\pip\pip.ini,在pip.ini文件中输入以下内容(以豆瓣镜像为例):

[global]
index-url = http://pypi.douban.com/simple
[install]
trusted-host = pypi.douban.com

创建pip.ini文件可以用文本编辑器,例如 sublime text3。

srcapy的安装

pip install scrapy -i https://pypi.tuna.tsinghua.edu.cn/simple

srcapy的工作流程

  • 一般爬虫的工作流程
    markdown流程图使用
    TB - 顶部到底部
    BT - 底部到顶部
    RL - 由右至左
    LR - 由左至右
    TD - 与 TB 相同
开始
提取url 请求数据
提取数据
保存数据
结束

在这里插入图片描述

模块名称功能手码情况
Scrapy engine(引擎)总指挥:负责数据和信号的在不同模块间的传递scrapy已经实现
Scheduler(调度器)⼀个队列,存放引擎发过来的request请求scrapy已经实现
Downloader(下载器)下载把引擎发过来的requests请求,并返回给引擎scrapy已经实现
Spider(爬⾍)处理引擎发来的response,提取数据,提取url,并交给引擎需要⼿写
Item Pipline(管道)处理引擎传过来的数据,比如存储需要⼿写
Downloader可以⾃定义的下载扩展,比如设置代理⼀般不⽤⼿写
Spider Middlewares(中间件)可以⾃定义requests请求和进⾏response过滤⼀般不⽤⼿写

scrapy快速入门

创建scrapy项目

(venv) D:\Python_study\new_python\venv\scrapy_space>scrapy startproject my_first_scrapy
New Scrapy project 'my_first_scrapy', using template directory 'd:\python_study\new_python\venv\lib\site-packages\scrapy\templates\proje
ct', created in:
    D:\Python_study\new_python\venv\scrapy_space\my_first_scrapy

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

在这里插入图片描述

创建一个爬虫

(venv) D:\Python_study\new_python\venv\scrapy_space>scrapy genspider db douban.com

scrapy genspider 【爬虫名字】 [爬虫网站]

注意爬虫网站不要https://www

执行如下:

(venv) D:\Python_study\new_python\venv\scrapy_space\my_first_scrapy>scrapy genspider douban douban.com
Created spider 'douban' using template 'basic' in module:
  my_first_scrapy.spiders.douban

查看项目目录就会找到,为我们自动生成的爬虫文件douban,py

目录结构分析

my_first_scrapy
my_first_scrapy
scrapy.cfg
spiders
items.py--爬虫的数据封装--数据结构
middlewares.py--爬虫中间件和下载中间件
pipelines.py--保存数据

#Don’t forget to add your pipeline to the ITEM_PIPELINES setting
不要忘记把管道添加设置中

爬虫代码编写

如douban.py

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


class DoubanSpider(scrapy.Spider):
    name = 'douban'
    allowed_domains = ['douban.com']
    start_urls = ['http://douban.com/']

    def parse(self, response):
        #pass
        print('*'*40)
        print(response)
        print(type(response))
        print('='*40)

注意在运行代码前要把/spider/settings.py文件的头代理打开

#Override the default request headers:
#DEFAULT_REQUEST_HEADERS = {
#'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
#'Accept-Language': 'en',
#}

改为:

DEFAULT_REQUEST_HEADERS = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.26 Safari/537.36 Core/1.63.6788.400 QQBrowser/10.3.2816.400',
'Accept-Language': 'en'
}

注释掉ROBOTSTXT协议

# Obey robots.txt rules
#ROBOTSTXT_OBEY = True
2020-06-22 14:00:01 [scrapy.downloadermiddlewares.redirect] DEBUG: Redirecting (301) to <GET https://www.douban.com/> from <GET http://w
ww.douban.com/>
2020-06-22 14:00:02 [scrapy.core.engine] DEBUG: Crawled (200) <GET https://www.douban.com/> (referer: None)
****************************************
<200 https://www.douban.com/>
<class 'scrapy.http.response.html.HtmlResponse'>
========================================
2020-06-22 14:00:02 [scrapy.core.engine] INFO: Closing spider (finished)
2020-06-22 14:00:02 [scrapy.statscollectors] INFO: Dumping Scrapy stats:
{'downloader/request_bytes': 773,
 'downloader/request_count': 3,
 'downloader/request_method_count/GET': 3,
 'downloader/response_bytes': 18493,
 'downloader/response_count': 3,
 'downloader/response_status_count/200': 1,
 'downloader/response_status_count/301': 2,
 'elapsed_time_seconds': 0.584632,
 'finish_reason': 'finished',
 'finish_time': datetime.datetime(2020, 6, 22, 6, 0, 2, 294357),
 'log_count/DEBUG': 3,
 'log_count/INFO': 10,
 'response_received_count': 1,
 'scheduler/dequeued': 3,
 'scheduler/dequeued/memory': 3,
 'scheduler/enqueued': 3,
 'scheduler/enqueued/memory': 3,
 'start_time': datetime.datetime(2020, 6, 22, 6, 0, 1, 709725)}
2020-06-22 14:00:02 [scrapy.core.engine] INFO: Spider closed (finished)

在这里插入图片描述

settings.py设置日志级别屏蔽,冗余日志

LOG_LEVEL = 'WARNING'

获取这个列表的内容

douban.py

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


class DoubanSpider(scrapy.Spider):
    name = 'douban'
    allowed_domains = ['douban.com']
    start_urls = ['http://movie.douban.com/']

    # 从xpath中获取数据selector对象之后,要提取数据
    # 方法1: 用get()/getall()
    # 如<a>文字</a>
    # 方法2: extract_first() -》这是一个文字

        def parse(self, response):
        #pass
        # print('*'*40)
        # print(response)
        # print(type(response))
        print('*' * 40)
        list_koubei = response.xpath("//div[@class='billboard-bd']//tr")
        #print(list_koubei)
        item = {}
        for koubei in list_koubei:
            #print(koubei)

            #print(koubei.xpath('td[@class="title"]/a/text()'))
            item['name'] = koubei.xpath('td[@class="title"]/a/text()').extract_first()
            print(item)
            yield item

        print('=' * 40)

运行爬虫

方法一用命令运行

scrapy crawl [爬虫名称]

接着再用命令运行douban.py

(venv) D:\Python_study\new_python\venv\scrapy_space\my_first_scrapy>scrapy crawl douban

方法二建立py文件运行爬虫

#!/user/bin/env python
#-*-coding utf-8-*-
#@Time           : 2020/6/2215:46
#@Author         : GodSpeed
#@File           : start.py.py
#@Software       : PyCharm


from scrapy import cmdline
#cmdline.execute("scrapy crawl douban".split()) #方式1
cmdline.execute(['scrapy','crawl','douban']) #方式2

运行的结果:

D:\Python_study\new_python\venv\Scripts\python.exe D:/Python_study/new_python/venv/scrapy_space/my_first_scrapy/my_first_scrapy/spiders/start.py
****************************************
{'name': '默片解说员'}
{'name': '数电影的人'}
{'name': '马茹娜的非凡旅程'}
{'name': '二十世纪'}
{'name': '金色荣耀'}
{'name': '鲁邦三世 The First'}
{'name': '知晓天空之蓝的人啊'}
{'name': '上帝存在,她叫佩特鲁尼娅'}
{'name': '最后与最初的人类'}
{'name': '双郎'}
========================================

Process finished with exit code 0

爬虫数据保存

打开settings的管道设置

# Configure item pipelines
# See https://docs.scrapy.org/en/latest/topics/item-pipeline.html
#ITEM_PIPELINES = {
#    'my_first_scrapy.pipelines.MyFirstScrapyPipeline': 300,
#}

打开

# Configure item pipelines
# See https://docs.scrapy.org/en/latest/topics/item-pipeline.html
ITEM_PIPELINES = {
    #300表示优先级
   'my_first_scrapy.pipelines.MyFirstScrapyPipeline': 300,
}

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


class MyFirstScrapyPipeline:
    def process_item(self, item, spider):
        print('pipelines:MyFirstScrapyPipeline process_item start'+'-'*5)
        print(item)
        print('pipelines:MyFirstScrapyPipeline process_item end'+'='*5)
        return item

迭代器和生成器


# 迭代器是一个可以记住便利位置的对象 iter() next()
# 只能向前不能后退
# 迭代器对象从序列中第一个元素开始,直到元素全部访问完后结束

# lst = ['蜘蛛侠','钢铁侠','李小龙','灭霸','唐吉可德']
# myiter = iter(lst)
#
# # print(next(myiter))
# # print(next(myiter))
# # print(next(myiter))
# # print(next(myiter))
# # print(next(myiter))
#
# for it in myiter:
#     print(it)

# 生成器:在Python中使用了yield这个函数称为生成器
# 生成器是一个返回迭代器的函数
# 在调用生成器运行的过程中,每次约到yield函数会暂停,并保存
# 当前运行的信息并返回yield的值,并在下一次调用next()函数时,
# 从当前位置继续进行

def fn1():
    print(1)
    print(2)
    print(3)
    print(4)
    print(5)

def fn2():
    print(111)
    yield 1
    print(222)
    yield 2
    print(333)
    yield 3
    print(444)
    yield 4
    print(555)
    yield 5

if __name__ == '__main__':
    #print(type(fn1)) # <class 'function'>
    #print(type(fn2)) # <class 'function'>
    #f1 = fn1()
    #print(type(f1)) # <class 'NoneType'>
    f2 = fn2() # 没有打印任何东西
    #print(type(f2)) # <class 'generator'>
    #next(f2) #one by one的执行
    #next(f2)
    #next(f2)
    #next(f2)
    #next(f2)
    '''
    111
    222
    333
    444
    555
    '''
    print('return:',next(f2))
    print('return:', next(f2))
    print('return:', next(f2))
# 111
# return: 1
# 222
# return: 2
# 333
# return: 3

数据的处理

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

import json

class MyFirstScrapyPipeline:

    def __init__(self):
        # 写入保存的逻辑
        self.f = open('tudou.json','w',encoding='utf-8')


    # 爬虫打开函数
    def open_spider(self,item):
        print('爬虫开始了')

    def process_item(self, item, spider):
        print('pipelines:MyFirstScrapyPipeline process_item start'+'-'*5)
        print(item)
        # json.dumps()可以将自定义形式的数据转换为字符串
        # ensure_ascii=Flase 在转换的时候默认是ascii字符,防止出现乱码
        item_json = json.dumps(item,ensure_ascii=False)
        self.f.write(item_json)
        print('pipelines:MyFirstScrapyPipeline process_item end'+'='*5)
        return item

    def close_spider(self,item ):
        print('爬虫结束了')
        self.f.close()

小结:

  • scrapy模块的安装
    pip install scrapy -i https://pypi.douban.com/simple
  • 创建scrapy项目 scrapy startproject myspider
  • 生成一个爬虫 scrapy genspider demo xxx.com
    如:scrapy genspider douban douban.com
  • 用xpath提取数据
  • piplines中保存数据
  • 运行爬虫项目
    scrapy crawl 爬虫名字
  • pycharm中运行爬虫项目
    1.先创建一个py文件
    2.导入一个模块 from srcapy import cmdline
    3.cmdline.execute(“scrapy crawl douban”.split()) #方式1
    cmdline.execute([‘scrapy’,‘crawl’,‘douban’]) #方式2

Scrapy CrawlSpider说明

CrawlSpider是爬取那些具有一定规则网站的常用的爬虫,它基于Spider并有一些独特属性

rules: 是Rule对象的集合,用于匹配目标网站并排除干扰
parse_start_url: 用于爬取起始响应,必须要返回Item,Request中的一个。
因为rules是Rule对象的集合,所以这里也要介绍一下Rule。它有几个参数:link_extractor、callback=None、cb_kwargs=None、follow=None、process_links=None、process_request=None
其中的link_extractor既可以自己定义,也可以使用已有LinkExtractor类,主要参数为:

allow:满足括号中“正则表达式”的值会被提取,如果为空,则全部匹配。
deny:与这个正则表达式(或正则表达式列表)不匹配的URL一定不提取。
allow_domains:会被提取的链接的domains。
deny_domains:一定不会被提取链接的domains。
restrict_xpaths:使用xpath表达式,和allow共同作用过滤链接。还有一个类似的restrict_css

CrawlSpider创建

scrapy genspider -t crawl 爬⾍名字 域名

CrawlSpider实例

创建爬虫项目

cd crawspider_yg
scrapy genspider -t crawl craw_spider_yg wz.sun0769.com

自动生成了craw_spider_yg.py

# -*- coding: utf-8 -*-
import scrapy
from scrapy.linkextractors import LinkExtractor
from scrapy.spiders import CrawlSpider, Rule



class CrawSpiderYgSpider(CrawlSpider):
    name = 'craw_spider_yg'
    allowed_domains = ['wz.sun0769.com']
    start_urls = ['http://wz.sun0769.com/']

    rules = (
        Rule(LinkExtractor(allow=r'Items/'), callback='parse_item', follow=True),
    )

    def parse_item(self, response):
        item = {}
        #item['domain_id'] = response.xpath('//input[@id="sid"]/@value').get()
        #item['name'] = response.xpath('//div[@id="name"]').get()
        #item['description'] = response.xpath('//div[@id="description"]').get()
        return item

settings.py文件需要修改的地方

LOG_LEVEL = 'WARNING'

# Override the default request headers:
DEFAULT_REQUEST_HEADERS = {
  'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
  'Accept-Language': 'en',
}

# Obey robots.txt rules
#ROBOTSTXT_OBEY = True

craw_spider_yg.py文件

# -*- coding: utf-8 -*-
import scrapy
from scrapy.linkextractors import LinkExtractor
from scrapy.spiders import CrawlSpider, Rule



class CrawSpiderYgSpider(CrawlSpider):
    name = 'craw_spider_yg'
    allowed_domains = ['wz.sun0769.com']
    start_urls = ['http://wz.sun0769.com/political/index/politicsNewest?id=1&page=1']

    # 定义提前url地址的规则

    rules = (
        # LinkExtractor链接提取器
        # callback 提取url地址的response 会交给回调函数处理
        # follow 是否连续提取新的url地址
        #Rule(LinkExtractor(allow=r'Items/'), callback='parse_item', follow=True),

        # 列表页
        Rule(LinkExtractor(allow=r'http://wz.sun0769.com/political/index/politicsNewest\?id=1&page=\d+'), follow=True),

        # 详情页
        Rule(LinkExtractor(allow=r'http://wz.sun0769.com/political/politics/index\?id=\d+'), callback='parse_item', follow=False),
    )



    def parse_item(self, response):
        item = {}
        #item['domain_id'] = response.xpath('//input[@id="sid"]/@value').get()
        #item['name'] = response.xpath('//div[@id="name"]').get()
        #item['description'] = response.xpath('//div[@id="description"]').get()

        item['content'] = response.xpath('//div[@class="details-box"]/pre/text()').extract_first()
        print(item['content'])
        return item

start.py

from scrapy import cmdline
cmdline.execute(['scrapy','crawl','craw_spider_yg'])

Crawl spider小结

  • 使用条件:目标信息必须在网页源码上才可以使用CrawlSpider;
  • 创建CrawlSpider 创建方法 scrapy genspider -t crawl 爬虫的名字 域名;
  • CrawlSpider需要定义回调函数的到时候,不要以parse命名,以避免混淆;
  • 注意Rule对象中的follow callback的使用条件,什么时候用,什么时候不用;
  • 注意Rule中的allow的正则表达式必须要?等特殊字符前面要加\进行转义处理,否则会导致爬取不到数据。
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Narutolxy

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值