• 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)。

  • 相关阅读:
    【LeetCode】Validate Binary Search Tree
    【LeetCode】Search in Rotated Sorted Array II(转)
    【LeetCode】Search in Rotated Sorted Array
    【LeetCode】Set Matrix Zeroes
    【LeetCode】Sqrt(x) (转载)
    【LeetCode】Integer to Roman
    贪心算法
    【LeetCode】Best Time to Buy and Sell Stock III
    【LeetCode】Best Time to Buy and Sell Stock II
    CentOS 6 上安装 pip、setuptools
  • 原文地址:https://www.cnblogs.com/dahu-daqing/p/7374362.html
Copyright © 2020-2023  润新知