系列文章列表:

scrapy爬虫学习系列一:scrapy爬虫环境的准备:       http://www.cnblogs.com/zhaojiedi1992/p/zhaojiedi_python_007_scrapy01.html

scrapy爬虫学习系列二:scrapy简单爬虫样例学习:  http://www.cnblogs.com/zhaojiedi1992/p/zhaojiedi_python_007_scrapy02.html

scrapy爬虫学习系列三:scrapy部署到scrapyhub上:   http://www.cnblogs.com/zhaojiedi1992/p/zhaojiedi_python_004_scrapyhub.html

scrapy爬虫学习系列四:portia的学习入门:      http://www.cnblogs.com/zhaojiedi1992/p/zhaojiedi_python_010_scrapy04.html

scrapy爬虫学习系列五:图片的抓取和下载:                 http://www.cnblogs.com/zhaojiedi1992/p/zhaojiedi_python_011_scrapy05.html

scrapyhub上有些视频简单介绍scrapy如何学习的(貌似要翻墙):https://helpdesk.scrapinghub.com/support/solutions/articles/22000201028-learn-scrapy-video-tutorials-

本博客的源码下载地址(github) :https://github.com/zhaojiedi1992/tutorial

在上一个学习系列一种, 我们简单了解了小scrapy的一些概念和基本环境的搭建,接下来就开始创建工程和爬虫吧。

1 创建工程

1.1先创建一个目录,用于我们后续的scrapy目录(e:\scrapytest)

  1. Win+R 快捷键 输入cmd 启动一个cmd创建,进行一下输入。
    C:\Users\Administrator>e:
  2.  
  3. E:\>cd e:\scrapytest
  4.  
  5. e:\scrapytest>scrapy startproject tutorial
  6. New Scrapy project 'tutorial', using template directory 'C:\\Program Files\\Anaconda3\\lib\\site-packages\\scrapy\\templates\\project', created in:
  7. e:\scrapytest\tutorial
  8.  
  9. You can start your first spider with:
  10. cd tutorial
  11. scrapy genspider example example.com
  12.  
  13. e:\scrapytest>

我们发现使用scrapy startproject tutorial 给我们创建了许多文件,文件树结构如下:

  1. e:\scrapytest>tree /f
  2. 新加卷 的文件夹 PATH 列表
  3. 卷序列号为 0000004B D20B:
  4. E:.
  5. └─tutorial
  6. scrapy.cfg #开发配置文件

  7. └─tutorial #工程模块
  8. items.py            
  9. middlewares.py       #定义数据条目的定义,可以理解为一行记录
  10. pipelines.py        #定义数据导出类,用于数据导出
  11. settings.py         #工程设置文件
  12. __init__.py        #空文件

  13. ├─spiders           #爬虫目录,用于放置各种爬虫类文件
  14. __init__.py      #空文件

  15. └─__pycache__       #这个文件不用管它
  16. └─__pycache__       #这个文件不用管它

通过上面的一条简单的命令,我们就创建了一个工程,有了工程,没有爬虫啊,接下里我们就创建一个爬虫吧。

2 创建爬虫

我们使用scrapy genspider quotes quotes.toscrape.com去创建一个爬虫。

scrapy genspider 使用方法: scrapy genspider [options] <name> <domain>

可以使用scrapy genspider -h 获取详细帮助 或者从官方获取shell帮助https://docs.scrapy.org/en/latest/topics/commands.html

  1. e:\scrapytest\tutorial>scrapy genspider quotes quotes.toscrape.com
  2. Created spider 'quotes' using template 'basic' in module:
  3. tutorial.spiders.quotes

注意:使用pycharm 打开tutorial项目,需要对python的环境进行设置(我机器上python环境太多了),使用File->Settings->Project:tutorial->Project Interpreter 选择我们特定的python.exe。如下图:

3 完善我们的爬虫

修改我们的爬虫文件(quotes.py)内容如下:

  1. # -*- coding: utf-8 -*-
  2. import scrapy
  3.  
  4. class QuotesSpider(scrapy.Spider):
  5. name = "quotes"
  6. allowed_domains = ["http://quotes.toscrape.com/"]
  7. start_urls = ['http://quotes.toscrape.com/page/1/']
  8.  
  9. def parse(self, response):
  10. filename="source.html"
  11. with open(filename,'wb') as f:
  12. f.write(response.body)

代码简单介绍下吧:

  • name:设定了爬虫的名字
  • allowed_domains :设定允许域,不是这些域内的网址就会被放弃。
  • start_urls:就是爬虫程序初始的url集合。
  • parse:默认处理response流的方法,通常会返回一个item或者dict 给pipeline。

现在,工程有了,爬虫也有了。 接下里开始让我们的爬虫进行工作吧。

4 运行爬虫

运行爬虫很简单,使用scrapy crawl quotes 命令就可以里

  1. e:\scrapytest\tutorial>scrapy crawl quotes
  2. 2017-08-25 22:50:25 [scrapy.utils.log] INFO: Scrapy 1.3.3 started (bot: tutorial)
  3. 2017-08-25 22:50:25 [scrapy.utils.log] INFO: Overridden settings: {'BOT_NAME': 'tutorial', 'NEWSPIDER_MODULE': 'tutorial.spiders', 'ROBOTSTXT_OBEY': True, 'SPIDER_MODULES': ['tutorial.spiders']}
  4. 2017-08-25 22:50:25 [scrapy.middleware] INFO: Enabled extensions:
  5. ['scrapy.extensions.corestats.CoreStats',
  6. 'scrapy.extensions.telnet.TelnetConsole',
  7. 'scrapy.extensions.logstats.LogStats']
  8. 2017-08-25 22:50:26 [scrapy.middleware] INFO: Enabled downloader middlewares:
  9. ['scrapy.downloadermiddlewares.robotstxt.RobotsTxtMiddleware',
  10. 'scrapy.downloadermiddlewares.httpauth.HttpAuthMiddleware',
  11. 'scrapy.downloadermiddlewares.downloadtimeout.DownloadTimeoutMiddleware',
  12. 'scrapy.downloadermiddlewares.defaultheaders.DefaultHeadersMiddleware',
  13. 'scrapy.downloadermiddlewares.useragent.UserAgentMiddleware',
  14. 'scrapy.downloadermiddlewares.retry.RetryMiddleware',
  15. 'scrapy.downloadermiddlewares.redirect.MetaRefreshMiddleware',
  16. 'scrapy.downloadermiddlewares.httpcompression.HttpCompressionMiddleware',
  17. 'scrapy.downloadermiddlewares.redirect.RedirectMiddleware',
  18. 'scrapy.downloadermiddlewares.cookies.CookiesMiddleware',
  19. 'scrapy.downloadermiddlewares.stats.DownloaderStats']
  20. 2017-08-25 22:50:26 [scrapy.middleware] INFO: Enabled spider middlewares:
  21. ['scrapy.spidermiddlewares.httperror.HttpErrorMiddleware',
  22. 'scrapy.spidermiddlewares.offsite.OffsiteMiddleware',
  23. 'scrapy.spidermiddlewares.referer.RefererMiddleware',
  24. 'scrapy.spidermiddlewares.urllength.UrlLengthMiddleware',
  25. 'scrapy.spidermiddlewares.depth.DepthMiddleware']
  26. 2017-08-25 22:50:26 [scrapy.middleware] INFO: Enabled item pipelines:
  27. []
  28. 2017-08-25 22:50:26 [scrapy.core.engine] INFO: Spider opened
  29. 2017-08-25 22:50:26 [scrapy.extensions.logstats] INFO: Crawled 0 pages (at 0 pages/min), scraped 0 items (at 0 items/min)
  30. 2017-08-25 22:50:26 [scrapy.extensions.telnet] DEBUG: Telnet console listening on 127.0.0.1:6023
  31. 2017-08-25 22:50:27 [scrapy.core.engine] DEBUG: Crawled (404) <GET http://quotes.toscrape.com/robots.txt> (referer: None)
  32. 2017-08-25 22:50:27 [scrapy.core.engine] DEBUG: Crawled (200) <GET http://quotes.toscrape.com/page/1/> (referer: None)
  33. 2017-08-25 22:50:28 [scrapy.core.engine] INFO: Closing spider (finished)
  34. 2017-08-25 22:50:28 [scrapy.statscollectors] INFO: Dumping Scrapy stats:
  35. {'downloader/request_bytes': 451,
  36. 'downloader/request_count': 2,
  37. 'downloader/request_method_count/GET': 2,
  38. 'downloader/response_bytes': 2701,
  39. 'downloader/response_count': 2,
  40. 'downloader/response_status_count/200': 1,
  41. 'downloader/response_status_count/404': 1,
  42. 'finish_reason': 'finished',
  43. 'finish_time': datetime.datetime(2017, 8, 25, 14, 50, 28, 49601),
  44. 'log_count/DEBUG': 3,
  45. 'log_count/INFO': 7,
  46. 'response_received_count': 2,
  47. 'scheduler/dequeued': 1,
  48. 'scheduler/dequeued/memory': 1,
  49. 'scheduler/enqueued': 1,
  50. 'scheduler/enqueued/memory': 1,
  51. 'start_time': datetime.datetime(2017, 8, 25, 14, 50, 26, 788397)}
  52. 2017-08-25 22:50:28 [scrapy.core.engine] INFO: Spider closed (finished)

运行爬虫后, 会提示一堆的信息,主要是完成以下几个部分工作:

  • 启动爬虫引擎
  • 加载设置文件
  • 启用扩展
  • 启用下载中间件
  • 启用爬虫中间件
  • 启动pipeline
  • 爬虫启动,开始工作
  • 爬虫结束, 引擎收集统计信息,清理工作

我们的爬虫代码是简单,就是打开一个sour.html文件,把获取的响应流(response)的页面内容写入进去。

到这这里,我们的爬虫只是获取了网址的源码,可能不是我们真正关心的,我们还需要写一写提取规则,提取网站的有用的信息(比如这个网址,我们只需要提取出作者,他的名言,他的标签),那我们就修改完善下爬虫吧。

5 完善爬虫

5.1 网址分析

我们自己用浏览器打开http://quotes.toscrape.com/page/1/ 这个网址,发现网页比较规整,核心的内容区域包含3个内容出作者,他的名言,他的标签。

5.2 使用浏览器调试功能(f12)获取元素的css样式。

5.3 在item,py 文件修改为如下的内容

  1. # -*- coding: utf-8 -*-
  2.  
  3. # Define here the models for your scraped items
  4. #
  5. # See documentation in:
  6. # http://doc.scrapy.org/en/latest/topics/items.html
  7.  
  8. import scrapy
  9.  
  10. class TutorialItem(scrapy.Item):
  11. # define the fields for your item here like:
  12. # name = scrapy.Field()
  13. author=scrapy.Field()
  14. text=scrapy.Field()
  15. tags=scrapy.Field()
  16. pass

代码简介:我们创建了3个字段,分别用于存储网址上的名言,作者和标记信息。

5.4 完善我们的爬虫

修改我们的爬虫为如下代码:

  1. # -*- coding: utf-8 -*-
  2. import scrapy
  3. from ..items import TutorialItem
  4.  
  5. class QuotesSpider(scrapy.Spider):
  6. name = "quotes"
  7. allowed_domains = ["http://quotes.toscrape.com/"]
  8. start_urls = ['http://quotes.toscrape.com/page/1/']
  9.  
  10. def parse(self, response):
  11. for quote in response.css('div.quote'):
  12. elem=TutorialItem()
  13. elem["text"]=quote.css('span.text::text').extract_first()
  14. elem["author"]=quote.css('small.author::text').extract_first()
  15. elem["tags"]=quote.css('div.tags a.tag::text').extract()
  16. yield elem

代码简介: 写一个for循环去遍历,每次提取一个elem,使用css选择器去定位元素。当然你也可以使用xpath去定位元素。

关于css选择器的如何使用:可以参考如下网址

w3cschool :http://www.w3school.com.cn/cssref/css_selectors.asp

官方文档:https://docs.scrapy.org/en/latest/topics/selectors.html

6 存储我们的数据

我们启动爬虫的时候,加入-o选项,可以指定输出, 它可以根据文件后缀判断出你要导出的格式。默认的导出目录是基于工程目录的,也就是说你设置-o quotes.json 会在你的工程目录下生成一个quotes.json文件。

  1. e:\scrapytest\tutorial>scrapy crawl quotes -o quotes.json
  2. e:\scrapytest\tutorial>scrapy crawl quotes -o quotes.xml
  3. e:\scrapytest\tutorial>scrapy crawl quotes -o quotes.csv
  4. e:\scrapytest\tutorial>scrapy crawl quotes -o quotes.jl

这里我是实在命令行指定-o选项,导出的,能不能不在命令行设置就可以导出呢,当然可以了,修改我们的pipeline吧。

7 修改pipeline

pipeline从其名字就知意,管道行用于对输入的数据(item)进行清洗和持久化处理。

修改pipeline.py内容如下:

  1. # -*- coding: utf-8 -*-
  2.  
  3. # Define your item pipelines here
  4. #
  5. # Don't forget to add your pipeline to the ITEM_PIPELINES setting
  6. # See: http://doc.scrapy.org/en/latest/topics/item-pipeline.html
  7.  
  8. class TutorialPipeline(object):
  9. def process_item(self, item, spider):
  10. return item
  11.  
  12. import json
  13.  
  14. class JsonWriterPipeline(object):
  15.  
  16. def open_spider(self, spider):
  17. self.file = open('items.jl', 'w')
  18.  
  19. def close_spider(self, spider):
  20. self.file.close()
  21.  
  22. def process_item(self, item, spider):
  23. line = json.dumps(dict(item)) + "\n"
  24. self.file.write(line)
  25. return item

设置好一个jsonline的pipline后,怎么让他生效呢, 需要在setting文件启用它的。

8 启用指定pipeline

打开setting.py文件

启用如下如下注释行,并稍作修改。

  1. ITEM_PIPELINES = {
  2. 'tutorial.pipelines.JsonWriterPipeline': 300,
  3. }

9 再次运行爬虫

这次在运行爬虫,我们发现生成了一个items.jl文件。当然了,我们这里是把items持久化到文件中去了,我们也是可以修改pipeline添加一个pipeline让item数据持久化到数据库中去。官方的一个样例:https://docs.scrapy.org/en/latest/topics/item-pipeline.html#write-items-to-mongodb

如果想生成各种格式的,处理feedback技术,可以参考我另一篇文章: http://www.cnblogs.com/zhaojiedi1992/p/zhaojiedi_python_005_scrapy.html

10 链接追踪

可以看到我们的爬虫只是爬取了page=1的内容,我要是想提取所有page的内容呢。如果你仔细分析下网页,可以看到page=1的页面最下面有个next的超链接指向下一页的。

那我们修改我们的爬虫代码为如下:

  1. # -*- coding: utf-8 -*-
  2. import scrapy
  3. from ..items import TutorialItem
  4.  
  5. class QuotesSpider(scrapy.Spider):
  6. name = "quotes"
  7. allowed_domains = ["http://quotes.toscrape.com/"]
  8. start_urls = ['http://quotes.toscrape.com/page/1/']
  9.  
  10. def parse(self, response):
  11. for quote in response.css('div.quote'):
  12. elem=TutorialItem()
  13. elem["text"]=quote.css('span.text::text').extract_first()
  14. elem["author"]=quote.css('small.author::text').extract_first()
  15. elem["tags"]=quote.css('div.tags a.tag::text').extract()
  16. yield elem
  17. next_page = response.css('li.next a::attr(href)').extract_first()
  18. if next_page is not None:
  19. next_page = response.urljoin(next_page)
  20. yield scrapy.Request(next_page, callback=self.parse,dont_filter=True)

代码简介:

next_page是我们从页面提取的下一页的网址,然后urljoin去拼接完整url,然后使用request去请求下一页,还是使用parse去解析响应流,当然我们可以在写一个parse的。

11 在次运行爬虫

我们可以发现page1,page2的页面的数据都提取出来,如下图

12 给爬虫添加参数

  我们想运行爬虫的时候,想给他指定一个参数,比如传递一个page号,让他动态去设置一个startul 可以吗?

  修改quotes.py文件为如下内容:

  1. # -*- coding: utf-8 -*-
  2. import scrapy
  3. from ..items import TutorialItem
  4.  
  5. class QuotesSpider(scrapy.Spider):
  6. name = "quotes"
  7. allowed_domains = ["http://quotes.toscrape.com/"]
  8. #start_urls = ['http://quotes.toscrape.com/page/1/']
  9. def __init__(self, page=None, *args, **kwargs):
  10. super(QuotesSpider, self).__init__(*args, **kwargs)
  11. if isinstance(page, str):
  12. self.start_urls = [
  13. 'http://quotes.toscrape.com/page/%s/' % page]
  14. self.page = page
  15.  
  16. def parse(self, response):
  17. for quote in response.css('div.quote'):
  18. elem=TutorialItem()
  19. elem["text"]=quote.css('span.text::text').extract_first()
  20. elem["author"]=quote.css('small.author::text').extract_first()
  21. elem["tags"]=quote.css('div.tags a.tag::text').extract()
  22. yield elem
  23. next_page = response.css('li.next a::attr(href)').extract_first()
  24. if next_page is not None:
  25. next_page = response.urljoin(next_page)
  26. yield scrapy.Request(next_page, callback=self.parse ,dont_filter=True)

代码简介: 添加一个init方法,完成了page参数的赋值接受,设置了startu_urls。这样就可以接受参数动态的生成start_urls了。

13 运行爬虫

  1. e:\scrapytest\tutorial>scrapy crawl quotes -a page=1

注: page=1,1就是参数,如果有空格使用双引号引起来。

通过本文的学习,你应该了解了。 scrapy框架的大概流程了吧,items,pipeline,spider.py,settings 这些文件是如何协同工作的。

14 相关的参考

css学习: http://www.w3school.com.cn/cssref/css_selectors.asp,https://www.w3.org/TR/selectors

xpath学习: http://www.w3school.com.cn/xpath/xpath_functions.asp   , https://www.w3.org/TR/xpath

浏览器调试: https://docs.scrapy.org/en/latest/topics/firefox.html

浏览器插件推荐: chrom下cssfinder,xpathfinder ,selectorGadget , firefox下xpathfinder。 强烈推荐selectorGadget。

注意: 有时候设置css或者xpath表达式的时候建议在scrapy shell环境中先测试。

scrapy爬虫学习系列二:scrapy简单爬虫样例学习的更多相关文章

  1. Android中关于JNI 的学习(零)简单的样例,简单地入门

    Android中JNI的作用,就是让Java可以去调用由C/C++实现的代码,为了实现这个功能.须要用到Anrdoid提供的NDK工具包,在这里不讲怎样配置了,好麻烦,配置了好久. . . 本质上,J ...

  2. Android中关于JNI 的学习(四)简单的样例,温故而知新

    在第零篇文章简单地介绍了JNI编程的模式之后.后面两三篇文章,我们又针对JNI中的一些概念做了一些简单的介绍,也不知道我究竟说的清楚没有.但相信非常多童鞋跟我一样.在刚開始学习一个东西的时候,入门最好 ...

  3. MyBatis学习系列二——增删改查

    目录 MyBatis学习系列一之环境搭建 MyBatis学习系列二——增删改查 MyBatis学习系列三——结合Spring 数据库的经典操作:增删改查. 在这一章我们主要说明一下简单的查询和增删改, ...

  4. RabbitMQ学习系列二-C#代码发送消息

    RabbitMQ学习系列二:.net 环境下 C#代码使用 RabbitMQ 消息队列 http://www.80iter.com/blog/1437455520862503 上一篇已经讲了Rabbi ...

  5. 图机器学习(GML)&图神经网络(GNN)原理和代码实现(前置学习系列二)

    项目链接:https://aistudio.baidu.com/aistudio/projectdetail/4990947?contributionType=1 欢迎fork欢迎三连!文章篇幅有限, ...

  6. Maven学习系列二(1-5)

    Maven学习系列二(1-5) 本文转自 QuantSeven 博客,讲解精炼易懂,适合入门,链接及截图如下 http://www.cnblogs.com/quanyongan/category/47 ...

  7. DocX开源WORD操作组件的学习系列二

    DocX学习系列 DocX开源WORD操作组件的学习系列一 : http://www.cnblogs.com/zhaojiedi1992/p/zhaojiedi_sharp_001_docx1.htm ...

  8. [转]ASP.NET MVC学习系列(二)-WebAPI请求 传参

    [转]ASP.NET MVC学习系列(二)-WebAPI请求 传参 本文转自:http://www.cnblogs.com/babycool/p/3922738.html ASP.NET MVC学习系 ...

  9. .net reactor 学习系列(二)---.net reactor界面各功能说明

    原文:.net reactor 学习系列(二)---.net reactor界面各功能说明         安装了.net reactor之后,可以在安装目录下找到帮助文档REACTOR_HELP.c ...

随机推荐

  1. 数据库和Content Provider

    SQLite提供了强大的SQL数据库的库文件,从而使应用程序拥有一个具备完全控制权的健壮的持久化层. Content Provider实现在应用程序内和应用程序之间存储.共享和使用结构化数据.通过将数 ...

  2. APM和PIX飞控日志分析入门贴

    我们在飞行中,经常会碰到各种各样的问题,经常有模友很纳闷,为什么我的飞机会这样那样的问题,为什么我的飞机会炸机,各种问题得不到答案是一件非常不爽的问题,在APM和PIX飞控中,都有记录我们整个飞行过程 ...

  3. mongodb4.0支持事务

    事务特性: 原子性:所有的改变都完成一致性:最终执行结果一致就行隔离性:一个事务的执行不能其它事务干扰.持久性:指一个事务一旦提交,数据不会改变,存在数据库中 exports.getSession = ...

  4. VMware Workstation安装Red hat7.0联网问题总结

    1.在red hat7当中iconfig命令是被取消了的,开发者用ip addr命令取代了ifconfig命令. 当然也是可以用ifconfig命令的 (前提是你安装的linux是可以联网的): 1) ...

  5. vue 实现图片上传与预览,以及清除图片

    vue写原生的上传图片并预览以及清除图片的效果,下面是demo,其中里面有vue获取input框value值的方法以及vue中函数之间的调用 <!DOCTYPE html> <htm ...

  6. MongoDB 用Robomong可视化工具操作的 一些简单语句

    一.数据更新 db.getCollection('表名').update({ "字段":{$in:["值"]} }, //更新条件 {$set:{ " ...

  7. poi导出Excel直接在浏览器下载

    需求:导出成Excel格式,要在浏览器看到类似于下载的效果. 导出的Excel和下载在同一个目录下. xxController.java // 导出 @RequestMapping(value = & ...

  8. js array 对象

    Javascript 对象: Array 对象:数组 创建方法: 1, var a = new Array() 2,var a = new Array(3) 3,var a = new Array(“ ...

  9. C语言面试题分类->字符串处理

    1.strlen:计算字符串长度(不包含'\0') 实现想法:遍历字符串,直到'\0'结束 #include<stdio.h> #include<stdlib.h> #incl ...

  10. 使用Sublime Text 或 vs2017开发Node.js程序

    在学习一门开发语言时,为了从简单的方式入手,有时候直接用Notepad开始敲代码.曾经我也这样干过,这样做简洁而不简单啊! 随着时间的流逝,人也变得懒惰起来,做事前总是想借助一些工具来搞事情.< ...