IT博客汇
  • 首页
  • 精华
  • 技术
  • 设计
  • 资讯
  • 扯淡
  • 权利声明
  • 登录 注册

    小白进阶之Scrapy第一篇

    哎哟卧槽发表于 2016-12-07 08:44:48
    love 0

    这博文写得我懒癌犯了,最后的那个章节内容排序,我没有实验是否是正确的,不过这只是个教大家用Scrapy的教程,正确与否并不重要···  如果不正确,记得留言;等我懒癌过了,我再改改······

    还有其它的问题也是一样··· ,把问题留言下; 等我懒癌过了·· 我改回来!嗯!是等我懒癌结束了,再改。

     

    前面几篇博文,给大家从头到尾做了一个比较高效的爬虫,从这篇起来说说Python的爬虫框架Scrapy;

    至于为什么要说框架呢?因为啊,框架可以帮我们处理一部分事情,比如下载模块不用我们自己写了,我们只需专注于提取数据就好了;

    最重要的一点啊!框架使用了异步的模式;可以加快我们的下载速度,而不用自己去实现异步框架;毕竟实现异步爬虫是一件比较麻烦的事情。

    不过啊!反爬虫这个坎还是要我们自己迈过去啊!这是后话,以后再说。我们先来让Scrapy能跑起来,并提取出我们需要的数据,再解决其它问题。

    官方文档在这儿:点我

    9555112

    环境搭建:

    关于这一点,对在Windows环境下使用的小伙伴来说,请务必使用我之前提到的 Anaconda 这个Python的发行版本,不然光环境的各种报错就能消磨掉你所有的学习兴趣!

    下载地址在这儿:http://pan.baidu.com/s/1pLgySav

    安装完成之后,在cmd中执行:conda install Scrapy     (如果需要使用特定版本,请在Scrapy后面加上 ==XXXX    XXXX代表你需要的版本号)

    下面是安装示意图:

    安装Scrapy

    So Easy@@!环境搭建完成!是不是超简单?全程无痛啊!

    下面开始踏上新的征程!Go Go Go!!

    使用Scrapy第一步:创建项目;CMD进入你需要放置项目的目录  输入:

    scrapy startproject XXXXX             XXXXX代表你项目的名字

    创建项目

    OK项目创建完成。现在可以开始我们的爬取之旅了!      下面是目录中各个文件的作用

    各个文件的作用

    好了,目录我们认识完了,在开始之前给大家一个小技巧,Scrapy默认是不能在IDE中调试的,我们在根目录中新建一个py文件叫:entrypoint.py;在里面写入以下内容:

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

    注意!第二行中代码中的前两个参数是不变的,第三个参数请使用自己的spider的名字。稍后我会讲到!!

    现在整个目录看起来是这样:

    快捷启动

    基础工作准备完毕!我们来说说基本思路。

    上面的准备工作完成之后,我们先不要着急开始工作,毕竟作为一个框架,还是很复杂的;贸然上手 开整,很容易陷入懵逼状态啊!一团浆糊,理不清思路,后面的事情做起来很很麻烦啦!

    我们来看看下面这张图:

    scrapy_architecture

    这就是整个Scrapy的架构图了;

    Scrapy Engine: 这是引擎,负责Spiders、ItemPipeline、Downloader、Scheduler中间的通讯,信号、数据传递等等!(像不像人的身体?)

    Scheduler(调度器): 它负责接受引擎发送过来的requests请求,并按照一定的方式进行整理排列,入队、并等待Scrapy Engine(引擎)来请求时,交给引擎。

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

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

    Item Pipeline:它负责处理Spiders中获取到的Item,并进行处理,比如去重,持久化存储(存数据库,写入文件,总之就是保存数据用的)

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

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

     

    数据在整个Scrapy的流向:

    程序运行的时候,

    引擎:Hi!Spider, 你要处理哪一个网站?

    Spiders:我要处理23wx.com

    引擎:你把第一个需要的处理的URL给我吧。

    Spiders:给你第一个URL是XXXXXXX.com

    引擎:Hi!调度器,我这有request你帮我排序入队一下。

    调度器:好的,正在处理你等一下。

    引擎:Hi!调度器,把你处理好的request给我,

    调度器:给你,这是我处理好的request

    引擎:Hi!下载器,你按照下载中间件的设置帮我下载一下这个request

    下载器:好的!给你,这是下载好的东西。(如果失败:不好意思,这个request下载失败,然后引擎告诉调度器,这个request下载失败了,你记录一下,我们待会儿再下载。)

    引擎:Hi!Spiders,这是下载好的东西,并且已经按照Spider中间件处理过了,你处理一下(注意!这儿responses默认是交给def parse这个函数处理的)

    Spiders:(处理完毕数据之后对于需要跟进的URL),Hi!引擎,这是我需要跟进的URL,将它的responses交给函数 def  xxxx(self, responses)处理。还有这是我获取到的Item。

    引擎:Hi !Item Pipeline 我这儿有个item你帮我处理一下!调度器!这是我需要的URL你帮我处理下。然后从第四步开始循环,直到获取到你需要的信息,

    注意!只有当调度器中不存在任何request了,整个程序才会停止,(也就是说,对于下载失败的URL,Scrapy会重新下载。)

    以上就是Scrapy整个流程了。

    QQ图片20161022193315

    大家将就着看看。

    建立一个项目之后:

    第一件事情是在items.py文件中定义一些字段,这些字段用来临时存储你需要保存的数据。方便后面保存数据到其他地方,比如数据库 或者 本地文本之类的。

    第二件事情在spiders文件夹中编写自己的爬虫

    第三件事情在pipelines.py中存储自己的数据

    还有一件事情,不是非做不可的,就settings.py文件 并不是一定要编辑的,只有有需要的时候才会编辑。

    建议一点:在大家调试的时候建议大家在settings.py中取消下面几行的注释:

    设置setting01

    这几行注释的作用是,Scrapy会缓存你有的Requests!当你再次请求时,如果存在缓存文档则返回缓存文档,而不是去网站请求,这样既加快了本地调试速度,也减轻了 网站的压力。一举多得

    第一步定义字段:

    好了,我们来做 第一步 定义一些字段;那具体我们要定义那些字段呢?

    这个根据自己需要的提取的内容来定义。

    比如:我们爬取小说站点都需要提取些什么数据啊?

    小说名字、作者、小说地址、连载状态、连载字数、文章类别

    就像下面这样:

    Scrapy01

    这样我们第一步就完成啦!是不是So Easy?ヾ(´▽‘)ノ ; 下面开始重点了哦!编写spider(就是我们用来提取数据的爬虫了)

    第二步编写Spider:

    在spiders文件中新建一个dingdian.py文件

    并导入我们需用的模块

    Scrapy02

    PS:Scrapy中Response可以直接使用Xpath来解析数据;不过大家也可以使用自己习惯的包,比如我导入的BS4 、re ;当然也可以使其他比如pyquery之类的。这个并没有什么限制

    另外或许个别小伙伴会遇到 from dingdian.items import DingdianItem这个导入失败的情况;可以试试把项目文件移动到根目录。

    Request这个模块可以用来重写单独请求一个URL,用于我们后面跟进URL。

    好了开整;首先我们需要什么?

    我们需要从一个地址入手开始爬取,我在顶点小说上没有发现有全站小说地址,但是我找到每个分类地址全部小说:

    玄幻魔幻:http://www.23wx.com/class/1_1.html

    武侠修真:http://www.23wx.com/class/2_1.html

    都市言情:http://www.23wx.com/class/3_1.html

    历史军事:http://www.23wx.com/class/4_1.html

    侦探推理:http://www.23wx.com/class/5_1.html

    网游动漫:http://www.23wx.com/class/6_1.html

    科幻小说:http://www.23wx.com/class/7_1.html

    恐怖灵异:http://www.23wx.com/class/8_1.html

    散文诗词:http://www.23wx.com/class/9_1.html

    其他:http://www.23wx.com/class/10_1.html

    全本:http://www.23wx.com/quanben/1

    好啦!入口地址我们找到了,现在开始写第一部分代码:

    当然对于上面的地址,我们是可以直接全使用Start_urls这种列表全部请求,不过并不太美观,我需要把其中,有规律的部分,单独其他方式实现,比如字典之类的:

    Scrapy03

    第十行:首先我们创建一个类 Myspider;这个类继承自scrapy.Spider(当然还有一些其他父类,继承各个父类后能实现的功能不一样);

    第十二行:我们定义name:dingdian (请注意,这name就是我们在entrypoint.py文件中的第三个参数!)!!!!请务必注意:此Name的!名字!在整个项目中有且只能有一个、名字不可重复!!!!

    第十一行:我们定义了一个allowed_domains;这个不是必须的;但是在某写情况下需要用得到,比如使用爬取规则的时候就需要了;它的作用是只会跟进存在于allowed_domains中的URL。不存在的URL会被忽略。

    第十七行到第十九行:我们使用字符串拼接的方式实现了我们上面发现的全部URL。

    第二十行和二十一行:我们使用了导入的Request包,来跟进我们的URL(并将返回的response作为参数传递给self.parse, 嗯!这个叫回调函数!)

    第二十三行:使用parse函数接受上面request获取到的response。(请务必注意:不要轻易改写parse函数(意思就是不要把parse函数用作它用);因为这样request的回调函数被你用了,就没谁接受request返回的response啦!如果你非要用作它用,则需要自己给request一个回调函数哦!)

    import re
    import scrapy #导入scrapy包
    from bs4 import BeautifulSoup
    from scrapy.http import Request ##一个单独的request的模块,需要跟进URL的时候,需要用它
    from dingdian.items import DingdianItem ##这是我定义的需要保存的字段,(导入dingdian项目中,items文件中的DingdianItem类)
    
    class Myspider(scrapy.Spider):
    
        name = 'dingdian'
        allowed_domains = ['23wx.com']
        bash_url = 'http://www.23wx.com/class/'
        bashurl = '.html'
    
        def start_requests(self):
            for i in range(1, 11):
                url = self.bash_url + str(i) + '_1' + self.bashurl
                yield Request(url, self.parse)
            yield Request('http://www.23wx.com/quanben/1', self.parse)
    
        def parse(self, response):
            print(response.text)

    我们测试一下是否正常工作:在IDE中运行我们之前创建的entrypoint.py文件(如果没有这个文件是不能在IDE中运行的哦!ヽ(=^・ω・^=)丿)

    然后会像这样:

    Spider编写03

    你会发现在红色状态报告之后,所有页面几乎是一瞬间出现的;那是因为Scrapy使用了异步啦!ヽ(°◇° )ノ

    另外因为Scrapy遵循了robots规则,如果你想要获取的页面在robots中被禁止了,Scrapy是会忽略掉的哦!!ヾ(。 ̄□ ̄)ツ゜゜゜

    请求就这么轻而易举的实现了啊!简直So Easy!

    继续 继续!

    我们需要历遍所有页面才能取得所有的小说页面连接:

    分析网页2

    分析网页01

    每个页面的这个位置都是最后一个页面,我们提取出它,历遍就可以拼接出一个完整的URL了ヾ§  ̄▽)ゞ2333333

    Go Go

    Scrapy04

    第二十三行:def parse(self, response)这个函数接受来在二十一行返回的response,并处理。

    第二十四行:我们使用BS4从response中获取到了最大页码。

    第二十五行至二十七行:我们照例拼接了一个完整的URL

    第二十八行:功能和第二十行一样,callback=  是指定回调函数,不过不写callback=也没有什么影响! 注意我只是说的callback=这个几个;不是后面的self.get_name.

    看清楚了response是怎么用的没?ヾ§  ̄▽)ゞ2333333是不是So Easy?

    如果不清楚那个拼接URL的小伙伴可以打印出来,看看哦··· 再去观察一下网页,就很明白啦

     

    上面两个函数就彻底的把整个网站的所有小说的页面URL的提取出来了,并将每个页面的response交给了get_name函数处理哦!

    现在我们的爬虫就开始处理具体的小说了哦:

    Scrapy07

     

    瞅见没 我们需要的东西,快用F12工具看一下吧,在什么位置有什么标签,可以方便我们提取数据。还不知道怎么看的小伙伴,去看看妹子图那个教程,有教哦;实在不行百度一下也行!

    过程忽略了,直接上代码(主要是懒癌来了):

    Scrapy09

    前面三行不说了,

    第三十七和三十八行:是我们的小说名字和URL

    第三十九行和第四十行;大伙儿可能会发现,多了个一个meta这么一个字典,这是Scrapy中传递额外数据的方法。因我们还有一些其他内容需要在下一个页面中才能获取到。

     

    转载请注明:静觅 » 小白进阶之Scrapy第一篇



沪ICP备19023445号-2号
友情链接