爬虫知识点(scrapy框架)

Scrapy 框架

  • Scrapy是用纯Python实现一个为了爬取网站数据、提取结构性数据而编写的应用框架,用途非常广泛。

  • 框架的力量,用户只需要定制开发几个模块就可以轻松的实现一个爬虫,用来抓取网页内容以及各种图片,非常之方便。

  • Scrapy 使用了 Twisted['twɪstɪd](其主要对手是Tornado)异步网络框架来处理网络通讯,可以加快我们的下载速度,不用自己去实现异步框架,并且包含了各种中间件接口,可以灵活的完成各种需求。


Scrapy架构图(绿线是数据流向):

  • Scrapy Engine(引擎): 负责SpiderItemPipelineDownloaderScheduler中间的通讯,信号、数据传递等。

  • Scheduler(调度器): 它负责接受引擎发送过来的Request请求,并按照一定的方式进行整理排列,入队,当引擎需要时,交还给引擎

  • Downloader(下载器):负责下载Scrapy Engine(引擎)发送的所有Requests请求,并将其获取到的Responses交还给Scrapy Engine(引擎),由引擎交给Spider来处理,

  • Spider(爬虫):它负责处理所有Responses,从中分析提取数据,获取Item字段需要的数据,并将需要跟进的URL提交给引擎,再次进入Scheduler(调度器)

  • Item Pipeline(管道):它负责处理Spider中获取到的Item,并进行进行后期处理(详细分析、过滤、存储等)的地方.

  • Downloader Middlewares(下载中间件):你可以当作是一个可以自定义扩展下载功能的组件。

  • Spider Middlewares(Spider中间件):你可以理解为是一个可以自定扩展和操作引擎Spider中间通信的功能组件(比如进入Spider的Responses;和从Spider出去的Requests)


  • # json格式,默认为Unicode编码
    scrapy crawl itcast -o teachers.json
    
    # json lines格式,默认为Unicode编码
    scrapy crawl itcast -o teachers.jsonl
    
    # csv 逗号表达式,可用Excel打开
    scrapy crawl itcast -o teachers.csv
    
    # xml格式
    scrapy crawl itcast -o teachers.xml

  • 制作爬虫 (spiders/itcastSpider.py)

  • 爬虫功能要分两步:

    1. 爬数据

    • 在当前目录下输入命令,将在mySpider/spider目录下创建一个名为itcast的爬虫,并指定爬取域的范围:
    scrapy genspider itcast "itcast.cn"
    
    • 打开 mySpider/spider目录里的 itcast.py,默认增加了下列代码:
    import scrapy
    
    class ItcastSpider(scrapy.Spider):
        name = "itcast"
        allowed_domains = ["itcast.cn"]
        start_urls = (
            'http://www.itcast.cn/',
        )
    
        def parse(self, response):
            pass
    
    其实也可以由我们自行创建itcast.py并编写上面的代码,只不过使用命令可以免去编写固定代码的麻烦

    要建立一个Spider, 你必须用scrapy.Spider类创建一个子类,并确定了三个强制的属性 和 一个方法。

    • name = "" :这个爬虫的识别名称,必须是唯一的,在不同的爬虫必须定义不同的名字。

    • allow_domains = [] 是搜索的域名范围,也就是爬虫的约束区域,规定爬虫只爬取这个域名下的网页,不存在的URL会被忽略。

    • start_urls = () :爬取的URL元祖/列表。爬虫从这里开始抓取数据,所以,第一次下载的数据将会从这些urls开始。其他子URL将会从这些起始URL中继承性生成。

    • parse(self, response) :解析的方法,每个初始URL完成下载后将被调用,调用的时候传入从每一个URL传回的Response对象来作为唯一参数,主要作用如下:

      1. 负责解析返回的网页数据(response.body),提取结构化数据(生成item)
      2. 生成需要下一页的URL请求。
    将start_urls的值修改为需要爬取的第一个url
    start_urls = ("http://www.itcast.cn/channel/teacher.shtml",)
    
    修改parse()方法
    def parse(self, response):
        filename = "teacher.html"
        open(filename, 'w').write(response.body)
    

    然后运行一下看看,在mySpider目录下执行:

    scrapy crawl itcast
    

    是的,就是 itcast,看上面代码,它是 ItcastSpider 类的 name 属性,也就是使用 scrapy genspider命令的唯一爬虫名。

    运行之后,如果打印的日志出现 [scrapy] INFO: Spider closed (finished),代表执行完成。 之后当前文件夹中就出现了一个 teacher.html 文件,里面就是我们刚刚要爬取的网页的全部源代码信息。

    # 注意,Python2.x默认编码环境是ASCII,当和取回的数据编码格式不一致时,可能会造成乱码;
    # 我们可以指定保存内容的编码格式,一般情况下,我们可以在代码最上方添加:
    
        import sys
        reload(sys)
        sys.setdefaultencoding("utf-8")
    
    # 这三行代码是Python2.x里解决中文编码的万能钥匙,经过这么多年的吐槽后Python3学乖了,默认编码是Unicode了...(祝大家早日拥抱Python3)

    Scrapy Shell

    Scrapy终端是一个交互终端,我们可以在未启动spider的情况下尝试及调试代码,也可以用来测试XPath或CSS表达式,查看他们的工作方式,方便我们爬取的网页中提取的数据。

    如果安装了 IPython ,Scrapy终端将使用 IPython (替代标准Python终端)。 IPython 终端与其他相比更为强大,提供智能的自动补全,高亮输出,及其他特性。(推荐安装IPython)

    启动Scrapy Shell

    进入项目的根目录,执行下列命令来启动shell:

    scrapy shell "http://www.itcast.cn/channel/teacher.shtml"
    

    Scrapy Shell根据下载的页面会自动创建一些方便使用的对象,例如 Response 对象,以及 Selector 对象 (对HTML及XML内容)

    • 当shell载入后,将得到一个包含response数据的本地 response 变量,输入 response.body将输出response的包体,输出 response.headers 可以看到response的包头。

    • 输入 response.selector 时, 将获取到一个response 初始化的类 Selector 的对象,此时可以通过使用 response.selector.xpath()response.selector.css() 来对 response 进行查询。

    • Scrapy也提供了一些快捷方式, 例如 response.xpath()response.css()同样可以生效(如之前的案例)。

    Selectors选择器

    Scrapy Selectors 内置 XPath 和 CSS Selector 表达式机制

    Selector有四个基本的方法,最常用的还是xpath:

    • xpath(): 传入xpath表达式,返回该表达式所对应的所有节点的selector list列表
    • extract(): 序列化该节点为Unicode字符串并返回list
    • css(): 传入CSS表达式,返回该表达式所对应的所有节点的selector list列表,语法同 BeautifulSoup4
    • re(): 根据传入的正则表达式对数据进行提取,返回Unicode字符串list列表
    XPath表达式的例子及对应的含义:
    /html/head/title: 选择<HTML>文档中 <head> 标签内的 <title> 元素
    /html/head/title/text(): 选择上面提到的 <title> 元素的文字
    //td: 选择所有的 <td> 元素
    //div[@class="mine"]: 选择所有具有 class="mine" 属性的 div 元素
    
    尝试Selector

    我们用腾讯社招的网站http://hr.tencent.com/position.php?&start=0#a举例:

    # 启动
    scrapy shell "http://hr.tencent.com/position.php?&start=0#a"
    
    # 返回 xpath选择器对象列表
    response.xpath('//title')
    [<Selector xpath='//title' data=u'<title>\u804c\u4f4d\u641c\u7d22 | \u793e\u4f1a\u62db\u8058 | Tencent \u817e\u8baf\u62db\u8058</title'>]
    
    # 使用 extract()方法返回 Unicode字符串列表
    response.xpath('//title').extract()
    [u'<title>\u804c\u4f4d\u641c\u7d22 | \u793e\u4f1a\u62db\u8058 | Tencent \u817e\u8baf\u62db\u8058</title>']
    
    # 打印列表第一个元素,终端编码格式显示
    print response.xpath('//title').extract()[0]
    <title>职位搜索 | 社会招聘 | Tencent 腾讯招聘</title>
    
    # 返回 xpath选择器对象列表
    response.xpath('//title/text()')
    <Selector xpath='//title/text()' data=u'\u804c\u4f4d\u641c\u7d22 | \u793e\u4f1a\u62db\u8058 | Tencent \u817e\u8baf\u62db\u8058'>
    
    # 返回列表第一个元素的Unicode字符串
    response.xpath('//title/text()')[0].extract()
    u'\u804c\u4f4d\u641c\u7d22 | \u793e\u4f1a\u62db\u8058 | Tencent \u817e\u8baf\u62db\u8058'
    
    # 按终端编码格式显示
    print response.xpath('//title/text()')[0].extract()
    职位搜索 | 社会招聘 | Tencent 腾讯招聘
    
    response.xpath('//*[@class="even"]')
    职位名称:
    
    print site[0].xpath('./td[1]/a/text()').extract()[0]
    TEG15-运营开发工程师(深圳)
    职位名称详情页:
    
    print site[0].xpath('./td[1]/a/@href').extract()[0]
    position_detail.php?id=20744&keywords=&tid=0&lid=0
    职位类别:
    
    print site[0].xpath('./td[2]/text()').extract()[0]
    技术类
    

    以后做数据提取的时候,可以把现在Scrapy Shell中测试,测试通过后再应用到代码中


  • scrapy  crawl myspider -o myspider.csv

  • 执行myspider文件,输出.csv文件




三:编写item pipelines
第一步  在setting中设置ITEN_PIPELINNES—
'myspider.pipelines.Itcastpipelines':200   #0-1000之间越小 优先级越靠前

第二步  编写pipelines文档
import json

class ItcastPipeline(object):
    # __init__方法是可选的,做为类的初始化方法
    def __init__(self):
        # 创建了一个文件
        self.filename = open("teacher.json", "w")

    # process_item方法是必须写的,用来处理item数据
    def process_item(self, item, spider):
        jsontext = json.dumps(dict(item), ensure_ascii = False) + "\n"
        self.filename.write(jsontext.encode("utf-8"))
        return item

    # close_spider方法是可选的,结束时调用这个方法
    def close_spider(self, spider):
        self.filename.close()
利用pipelines下载图片
import scrapy
from scrapy.utils.project import get_project_settings
from scrapy.pipelines.images import ImagesPipeline
import os

class ImagesPipeline(ImagesPipeline):
    #def process_item(self, item, spider):
    #    return item
    # 获取settings文件里设置的变量值
    IMAGES_STORE = get_project_settings().get("IMAGES_STORE")   #在setting中设置文件的存储位置

    def get_media_requests(self, item, info):
        image_url = item["imagelink"]
        yield scrapy.Request(image_url)

    def item_completed(self, result, item, info):
        image_path = [x["path"] for ok, x in result if ok]

        os.rename(self.IMAGES_STORE + "/" + image_path[0], self.IMAGES_STORE + "/" + item["nickname"] + ".jpg")

        item["imagePath"] = self.IMAGES_STORE + "/" + item["nickname"]

        return item

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值