zoukankan      html  css  js  c++  java
  • scrapy 学习笔记1

    最近一段时间开始研究爬虫,后续陆续更新学习笔记

    爬虫,说白了就是获取一个网页的html页面,然后从里面获取你想要的东西,复杂一点的还有:

    • 反爬技术(人家网页不让你爬,爬虫对服务器负载很大)
    • 爬虫框架(你不可能逮到一个需求就从头写个爬虫把,框架已经有了)
    • 多线程

    当然这是我自己的理解,而scrapy框架算是比较流行的python爬虫框架,开始搞把

    目前的套路就是学到能爬你想爬的any网站,然后获取你想要的any数据,至于反爬什么的,网络限制什么的,再看吧,把基础的弄好.

    用的是1.4版本,默认已经安装好了.

    中文版教程(1.0)

    英文版教程(最新)

    创建项目:

    dahu@dahu-OptiPlex-3046:~/PycharmProjects/myscrapy$ scrapy startproject myfirstpro

    后面开可以再跟一个目录名称,如果没有就是同名的,你可以这样:   $ scrapy startproject myfirstpro  mydir

    我们可以看出文件结构:

    dahu@dahu-OptiPlex-3046:~/PycharmProjects/myscrapy$ tree
    .
    └── myfirstpro
        ├── myfirstpro
        │   ├── __init__.py
        │   ├── items.py
        │   ├── middlewares.py
        │   ├── pipelines.py
        │   ├── settings.py
        │   └── spiders
        │       └── __init__.py
        └── scrapy.cfg
    
    3 directories, 7 files

    第一个爬虫:  

    爬虫位置在spiders 里面,目录下的名为 quotes_spider.py 的文件中

    #!/usr/bin/python
    #coding=utf-8
    
    import scrapy
    
    class QuotesSpider(scrapy.Spider):
        name = "quotes"  #用于识别 Spider。 它在项目中必须是唯一的,也就是说,您不能为不同的 Spider 设置相同的名称。
    
        def start_requests(self):  #必须返回一个 Requests 的迭代(您可以返回一个 requests 列表或者写一个生成器函数),Spider 将从这里开始抓取。 随后的请求将从这些初始请求连续生成。没有也行,但是要有start_urls ,这是个列表,放初始的链接
            urls = [
                'http://quotes.toscrape.com/page/1/',
                'http://quotes.toscrape.com/page/2/',
            ]
            for url in urls:
                yield scrapy.Request(url=url, callback=self.parse)
    
        def parse(self, response):  #用来处理每个请求得到的响应的方法。 响应参数是 TextResponse 的一个实例,它保存页面内容,并且还有其他有用的方法来处理它。方法通常解析响应,将抓取的数据提取为字典,并且还可以查找新的 URL 来跟踪并从中创建新的请求(Request)。
            page = response.url.split("/")[-2]
            filename = 'quotes-%s.html' % page
            with open(filename, 'wb') as f:
                f.write(response.body)  #直接把服务器的响应全保存了
            self.log('Saved file %s' % filename)  #出现在日志里的一个方法

    运行:

    dahu@dahu-OptiPlex-3046:~/PycharmProjects/myscrapy/myfirstpro$ scrapy crawl quotes

    可以看到生成的文件:

    dahu@dahu-OptiPlex-3046:~/PycharmProjects/myscrapy/myfirstpro$ tree
    .
    ├── myfirstpro
    │   ├── __init__.py
    │   ├── __init__.pyc
    │   ├── items.py
    │   ├── middlewares.py
    │   ├── pipelines.py
    │   ├── settings.py
    │   ├── settings.pyc
    │   └── spiders
    │       ├── __init__.py
    │       ├── __init__.pyc
    │       ├──  quotes_spider.py
    │       └──  quotes_spider.pyc
    ├── quotes-1.html
    ├── quotes-2.html
    └── scrapy.cfg
    
    2 directories, 14 files

    在爬虫中提取数据

    到目前为止,它并没有提取任何数据,只将整个 HTML 页面保存到本地文件。这里用到了xpath语法来提取数据

    Scrapy 爬虫通常生成许多包含提取到的数据的字典。 为此,我们在回调方法中使用 yield Python 关键字,如下所示:

    #!/usr/bin/python
    #coding=utf-8
    # 
    import scrapy
    
    class QuotesSpider(scrapy.Spider):
        name = "quotes"
        start_urls = [
            'http://quotes.toscrape.com/page/1/',
            'http://quotes.toscrape.com/page/2/',
        ]
    
        def parse(self, response):
            for quote in response.css('div.quote'):
                yield {
                    'text': quote.xpath('./span[@class="text"]/text()').extract_first(),
                    'author': quote.xpath('.//small[@class="author"]/text()').extract_first(),
                    'tag': quote.xpath('.//div[@class="tags"]/a[@class="tag"]/text()').extract(),
                }

    运行爬虫,会有日志显示:

    2017-08-16 16:26:39 [scrapy.core.engine] DEBUG: Crawled (200) <GET http://quotes.toscrape.com/page/1/> (referer: None)
    2017-08-16 16:26:39 [scrapy.core.scraper] DEBUG: Scraped from <200 http://quotes.toscrape.com/page/1/>
    {'text': u'u201cThe world as we have created it is a process of our thinking. It cannot be changed without changing our thinking.u201d', 'tag': [u'change', u'deep-thoughts', u'thinking', u'world'], 'author': u'Albert Einstein'}
    2017-08-16 16:26:39 [scrapy.core.scraper] DEBUG: Scraped from <200 http://quotes.toscrape.com/page/1/>
    {'text': u'u201cIt is our choices, Harry, that show what we truly are, far more than our abilities.u201d', 'tag': [u'abilities', u'choices'], 'author': u'J.K. Rowling'}

    存储抓取的数据

    存储抓取数据的最简单的方法是使用 Feed exports,使用以下命令:

    scrapy crawl quotes -o quotes.json

    这将生成一个 quotes.json 文件,其中包含所有抓取到的 JSON 序列化的数据。

    由于历史原因,Scrapy 追加内容到给定的文件,而不是覆盖其内容。 如果您在第二次之前删除该文件两次运行此命令,那么最终会出现一个破坏的 JSON 文件。您还可以使用其他格式,如 JSON 行(JSON Lines):

    scrapy crawl quotes -o quotes.jl

    JSON 行格式很有用,因为它像流一样,您可以轻松地将新记录附加到文件。 当运行两次时,它不会发生 JSON 那样的问题。 另外,由于每条记录都是单独的行,所以您在处理大文件时无需将所有内容放到内存中,还有 JQ 等工具可以帮助您在命令行中执行此操作。

    在小项目(如本教程中的一个)中,这应该是足够的。 但是,如果要使用已抓取的项目执行更复杂的操作,则可以编写项目管道(Item Pipeline)。 在工程的创建过程中已经为您创建了项目管道的占位符文件pipelines.py, 虽然您只需要存储已抓取的项目,不需要任何项目管道。

    输出的文件格式,可以看出,有多种格式可以选择:

    dahu@dahu-OptiPlex-3046:~/PycharmProjects/myscrapy/myfirstpro$ scrapy crawl quotes -o -h
    Usage
    =====
      scrapy crawl [options] <spider>
    
    crawl: error: Unrecognized output format '', set one using the '-t' switch or as a file extension from the supported list ('xml', 'jsonlines', 'jl', 'json', 'csv', 'pickle', 'marshal')

    跟踪链接

    或许你希望获取网站所有页面的 quotes,而不是从 http://quotes.toscrape.com 的前两页抓取。

    现在您已经知道如何从页面中提取数据,我们来看看如何跟踪链接。

    # -*- coding: utf-8 -*-
    import scrapy
    
    
    class ToScrapeSpiderXPath(scrapy.Spider):
        name = 'quotes'
        start_urls = [
            'http://quotes.toscrape.com/',
        ]
    
        def parse(self, response):
            for quote in response.xpath('//div[@class="quote"]'):
                yield {
                    'text': quote.xpath('./span[@class="text"]/text()').extract_first(),
                    'author': quote.xpath('.//small[@class="author"]/text()').extract_first(),
                    'tag': quote.xpath('.//div[@class="tags"]/a[@class="tag"]/text()').extract()
                }
    
            next_page_url = response.xpath('//li[@class="next"]/a/@href').extract_first()
            if next_page_url is not None:
                yield scrapy.Request(response.urljoin(next_page_url),callback=self.parse)
            # if next_page_url is not None:  #相对链接
            #    yield response.follow(next_page_url, callback=self.parse)

    现在,在提取数据之后,parse() 方法查找到下一页的链接,使用 urljoin() 方法构建一个完整的绝对 URL(因为链接可以是相对的),并生成(yield)一个到下一页的新的请求, 其中包括回调方法(parse)。

    您在这里看到的是 Scrapy 的链接跟踪机制:当您在一个回调方法中生成(yield)请求(request)时,Scrapy 将安排发起该请求,并注册该请求完成时执行的回调方法。

    使用它,您可以根据您定义的规则构建复杂的跟踪链接机制,并根据访问页面提取不同类型的数据。

    在我们的示例中,它创建一个循环,跟踪所有到下一页的链接,直到它找不到要抓取的博客,论坛或其他站点分页。

    不像 scrapy.Request,response.follow 支持相对 URL - 不需要调用urljoin。请注意,response.follow 只是返回一个 Request 实例,您仍然需要生成请求(yield request)。

  • 相关阅读:
    Design a stack that supports getMin() in O(1) time and O(1) extra space
    Python的sys.argv用法
    数据库系统概论学习4-SQL 语句和关系代数(二)单表查询
    数据库系统概论学习3-SQL 语句和关系代数(一)SQL 入门
    数据库系统概论学习2-《关系数据库与 E/R 模型》
    MySQL实验1: 新建一个名为 library 的数据库,包含 book、reader 两张表,根据自己的理解安排表的内容并插入数据。
    如何在Eclipse环境下安装PyDev并成功运行Python3.6代码
    模型融合之blending和stacking
    Pandas基础用法-数据处理【全】-转
    各种排序算法-用Python实现
  • 原文地址:https://www.cnblogs.com/dahu-daqing/p/7374362.html
Copyright © 2011-2022 走看看