小白进阶之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进入你需要放置项目的目录  输入:

	<div id="crayon-5dea590faff84858271558" class="crayon-syntax crayon-theme-github crayon-font-monaco crayon-os-pc print-yes notranslate crayon-wrapped" data-settings=" minimize scroll-mouseover wrap" style="margin-top: 12px; margin-bottom: 12px; float: left; font-size: 12px !important; line-height: 15px !important; height: auto;">
	
		<div class="crayon-toolbar" data-settings=" show" style="font-size: 12px !important;height: 18px !important; line-height: 18px !important;"><span class="crayon-title"></span>
		<div class="crayon-tools" style="font-size: 12px !important;height: 18px !important; line-height: 18px !important;"><div class="crayon-button crayon-nums-button crayon-pressed" title="Toggle Line Numbers"><div class="crayon-button-icon" style="background-size: 48px 128px; background-image: url(&quot;https://cuiqingcai.com/wp-content/plugins/crayon-syntax-highlighter/css/images/toolbar/buttons@2x.png&quot;);"></div></div><div class="crayon-button crayon-plain-button" title="Toggle Plain Code"><div class="crayon-button-icon" style="background-size: 48px 128px; background-image: url(&quot;https://cuiqingcai.com/wp-content/plugins/crayon-syntax-highlighter/css/images/toolbar/buttons@2x.png&quot;);"></div></div><div class="crayon-button crayon-wrap-button crayon-pressed" title="Toggle Line Wrap"><div class="crayon-button-icon" style="background-size: 48px 128px; background-image: url(&quot;https://cuiqingcai.com/wp-content/plugins/crayon-syntax-highlighter/css/images/toolbar/buttons@2x.png&quot;);"></div></div><div class="crayon-button crayon-expand-button" title="Expand Code" style="display: none;"><div class="crayon-button-icon" style="background-size: 48px 128px; background-image: url(&quot;https://cuiqingcai.com/wp-content/plugins/crayon-syntax-highlighter/css/images/toolbar/buttons@2x.png&quot;);"></div></div><div class="crayon-button crayon-copy-button" title="Copy"><div class="crayon-button-icon" style="background-size: 48px 128px; background-image: url(&quot;https://cuiqingcai.com/wp-content/plugins/crayon-syntax-highlighter/css/images/toolbar/buttons@2x.png&quot;);"></div></div><div class="crayon-button crayon-popup-button" title="Open Code In New Window"><div class="crayon-button-icon" style="background-size: 48px 128px; background-image: url(&quot;https://cuiqingcai.com/wp-content/plugins/crayon-syntax-highlighter/css/images/toolbar/buttons@2x.png&quot;);"></div></div></div></div>
		<div class="crayon-info" style="min-height: 16.8px !important; line-height: 16.8px !important;"></div>
		<div class="crayon-plain-wrap"><textarea class="crayon-plain print-no" data-settings="dblclick" readonly="" style="tab-size: 4; font-size: 12px !important; line-height: 15px !important; z-index: 0; opacity: 0; overflow: hidden;">scrapy startproject XXXXX             XXXXX代表你项目的名字</textarea></div>
		<div class="crayon-main" style="position: relative; z-index: 1; overflow: hidden;">
			<table class="crayon-table" style="">
				<tbody><tr class="crayon-row">
			<td class="crayon-nums " data-settings="show">
				<div class="crayon-nums-content" style="font-size: 12px !important; line-height: 15px !important;"><div class="crayon-num" data-line="crayon-5dea590faff84858271558-1" style="height: 14px;">1</div></div>
			</td>
					<td class="crayon-code"><div class="crayon-pre" style="font-size: 12px !important; line-height: 15px !important; -moz-tab-size:4; -o-tab-size:4; -webkit-tab-size:4; tab-size:4;"><div class="crayon-line" id="crayon-5dea590faff84858271558-1"><span class="crayon-e">scrapy </span><span class="crayon-e">startproject </span><span class="crayon-e">XXXXX&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span class="crayon-i">XXXXX</span>代表你项目的名字</div></div></td>
				</tr>
			</tbody></table>
		</div>
	</div>

创建项目

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

各个文件的作用

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

	<div id="crayon-5dea590faff8e354521762" class="crayon-syntax crayon-theme-github crayon-font-monaco crayon-os-pc print-yes notranslate crayon-wrapped" data-settings=" minimize scroll-mouseover wrap" style="margin-top: 12px; margin-bottom: 12px; float: left; font-size: 12px !important; line-height: 15px !important; height: auto;">
	
		<div class="crayon-toolbar" data-settings=" show" style="font-size: 12px !important;height: 18px !important; line-height: 18px !important;"><span class="crayon-title"></span>
		<div class="crayon-tools" style="font-size: 12px !important;height: 18px !important; line-height: 18px !important;"><div class="crayon-button crayon-nums-button crayon-pressed" title="Toggle Line Numbers"><div class="crayon-button-icon" style="background-size: 48px 128px; background-image: url(&quot;https://cuiqingcai.com/wp-content/plugins/crayon-syntax-highlighter/css/images/toolbar/buttons@2x.png&quot;);"></div></div><div class="crayon-button crayon-plain-button" title="Toggle Plain Code"><div class="crayon-button-icon" style="background-size: 48px 128px; background-image: url(&quot;https://cuiqingcai.com/wp-content/plugins/crayon-syntax-highlighter/css/images/toolbar/buttons@2x.png&quot;);"></div></div><div class="crayon-button crayon-wrap-button crayon-pressed" title="Toggle Line Wrap"><div class="crayon-button-icon" style="background-size: 48px 128px; background-image: url(&quot;https://cuiqingcai.com/wp-content/plugins/crayon-syntax-highlighter/css/images/toolbar/buttons@2x.png&quot;);"></div></div><div class="crayon-button crayon-expand-button" title="Expand Code" style="display: none;"><div class="crayon-button-icon" style="background-size: 48px 128px; background-image: url(&quot;https://cuiqingcai.com/wp-content/plugins/crayon-syntax-highlighter/css/images/toolbar/buttons@2x.png&quot;);"></div></div><div class="crayon-button crayon-copy-button" title="Copy"><div class="crayon-button-icon" style="background-size: 48px 128px; background-image: url(&quot;https://cuiqingcai.com/wp-content/plugins/crayon-syntax-highlighter/css/images/toolbar/buttons@2x.png&quot;);"></div></div><div class="crayon-button crayon-popup-button" title="Open Code In New Window"><div class="crayon-button-icon" style="background-size: 48px 128px; background-image: url(&quot;https://cuiqingcai.com/wp-content/plugins/crayon-syntax-highlighter/css/images/toolbar/buttons@2x.png&quot;);"></div></div><span class="crayon-language">Python</span></div></div>
		<div class="crayon-info" style="min-height: 16.8px !important; line-height: 16.8px !important;"></div>
		<div class="crayon-plain-wrap"><textarea class="crayon-plain print-no" data-settings="dblclick" readonly="" style="tab-size: 4; font-size: 12px !important; line-height: 15px !important; z-index: 0; opacity: 0; overflow: hidden;">from scrapy.cmdline import execute

execute([‘scrapy’, ‘crawl’, ‘dingdian’])








1
2

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这种列表全部请求,不过并不太美观,我需要把其中,有规律的部分,单独其他方式实现,比如字典之类的:

Scrapy22

第十行:首先我们创建一个类 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一个回调函数哦!)

	<div id="crayon-5dea590faff96208426263" class="crayon-syntax crayon-theme-github crayon-font-monaco crayon-os-pc print-yes notranslate crayon-wrapped" data-settings=" minimize scroll-mouseover wrap" style="margin-top: 12px; margin-bottom: 12px; float: left; font-size: 12px !important; line-height: 15px !important; height: auto;">
	
		<div class="crayon-toolbar" data-settings=" show" style="font-size: 12px !important;height: 18px !important; line-height: 18px !important;"><span class="crayon-title"></span>
		<div class="crayon-tools" style="font-size: 12px !important;height: 18px !important; line-height: 18px !important;"><div class="crayon-button crayon-nums-button crayon-pressed" title="Toggle Line Numbers"><div class="crayon-button-icon" style="background-size: 48px 128px; background-image: url(&quot;https://cuiqingcai.com/wp-content/plugins/crayon-syntax-highlighter/css/images/toolbar/buttons@2x.png&quot;);"></div></div><div class="crayon-button crayon-plain-button" title="Toggle Plain Code"><div class="crayon-button-icon" style="background-size: 48px 128px; background-image: url(&quot;https://cuiqingcai.com/wp-content/plugins/crayon-syntax-highlighter/css/images/toolbar/buttons@2x.png&quot;);"></div></div><div class="crayon-button crayon-wrap-button crayon-pressed" title="Toggle Line Wrap"><div class="crayon-button-icon" style="background-size: 48px 128px; background-image: url(&quot;https://cuiqingcai.com/wp-content/plugins/crayon-syntax-highlighter/css/images/toolbar/buttons@2x.png&quot;);"></div></div><div class="crayon-button crayon-expand-button" title="Expand Code" style="display: none;"><div class="crayon-button-icon" style="background-size: 48px 128px; background-image: url(&quot;https://cuiqingcai.com/wp-content/plugins/crayon-syntax-highlighter/css/images/toolbar/buttons@2x.png&quot;);"></div></div><div class="crayon-button crayon-copy-button" title="Copy"><div class="crayon-button-icon" style="background-size: 48px 128px; background-image: url(&quot;https://cuiqingcai.com/wp-content/plugins/crayon-syntax-highlighter/css/images/toolbar/buttons@2x.png&quot;);"></div></div><div class="crayon-button crayon-popup-button" title="Open Code In New Window"><div class="crayon-button-icon" style="background-size: 48px 128px; background-image: url(&quot;https://cuiqingcai.com/wp-content/plugins/crayon-syntax-highlighter/css/images/toolbar/buttons@2x.png&quot;);"></div></div><span class="crayon-language">Python</span></div></div>
		<div class="crayon-info" style="min-height: 16.8px !important; line-height: 16.8px !important;"></div>
		<div class="crayon-plain-wrap"><textarea class="crayon-plain print-no" data-settings="dblclick" readonly="" style="tab-size: 4; font-size: 12px !important; line-height: 15px !important; z-index: 0; opacity: 0; overflow: hidden;">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)</textarea></div>
		<div class="crayon-main" style="position: relative; z-index: 1; overflow: hidden;">
			<table class="crayon-table" style="">
				<tbody><tr class="crayon-row">
			<td class="crayon-nums " data-settings="show">
				<div class="crayon-nums-content" style="font-size: 12px !important; line-height: 15px !important;"><div class="crayon-num" data-line="crayon-5dea590faff96208426263-1" style="height: 14px;">1</div><div class="crayon-num crayon-striped-num" data-line="crayon-5dea590faff96208426263-2" style="height: 14px;">2</div><div class="crayon-num" data-line="crayon-5dea590faff96208426263-3" style="height: 14px;">3</div><div class="crayon-num crayon-striped-num" data-line="crayon-5dea590faff96208426263-4" style="height: 14px;">4</div><div class="crayon-num" data-line="crayon-5dea590faff96208426263-5" style="height: 29px;">5</div><div class="crayon-num crayon-striped-num" data-line="crayon-5dea590faff96208426263-6" style="height: 14px;">6</div><div class="crayon-num" data-line="crayon-5dea590faff96208426263-7" style="height: 14px;">7</div><div class="crayon-num crayon-striped-num" data-line="crayon-5dea590faff96208426263-8" style="height: 14px;">8</div><div class="crayon-num" data-line="crayon-5dea590faff96208426263-9" style="height: 14px;">9</div><div class="crayon-num crayon-striped-num" data-line="crayon-5dea590faff96208426263-10" style="height: 14px;">10</div><div class="crayon-num" data-line="crayon-5dea590faff96208426263-11" style="height: 14px;">11</div><div class="crayon-num crayon-striped-num" data-line="crayon-5dea590faff96208426263-12" style="height: 14px;">12</div><div class="crayon-num" data-line="crayon-5dea590faff96208426263-13" style="height: 14px;">13</div><div class="crayon-num crayon-striped-num" data-line="crayon-5dea590faff96208426263-14" style="height: 14px;">14</div><div class="crayon-num" data-line="crayon-5dea590faff96208426263-15" style="height: 14px;">15</div><div class="crayon-num crayon-striped-num" data-line="crayon-5dea590faff96208426263-16" style="height: 14px;">16</div><div class="crayon-num" data-line="crayon-5dea590faff96208426263-17" style="height: 14px;">17</div><div class="crayon-num crayon-striped-num" data-line="crayon-5dea590faff96208426263-18" style="height: 14px;">18</div><div class="crayon-num" data-line="crayon-5dea590faff96208426263-19" style="height: 14px;">19</div><div class="crayon-num crayon-striped-num" data-line="crayon-5dea590faff96208426263-20" style="height: 14px;">20</div><div class="crayon-num" data-line="crayon-5dea590faff96208426263-21" style="height: 14px;">21</div></div>
			</td>
					<td class="crayon-code"><div class="crayon-pre" style="font-size: 12px !important; line-height: 15px !important; -moz-tab-size:4; -o-tab-size:4; -webkit-tab-size:4; tab-size:4;"><div class="crayon-line" id="crayon-5dea590faff96208426263-1"><span class="crayon-r">import</span><span class="crayon-h"> </span><span class="crayon-k ">re</span></div><div class="crayon-line crayon-striped-line" id="crayon-5dea590faff96208426263-2"><span class="crayon-r">import</span><span class="crayon-h"> </span><span class="crayon-v">scrapy</span><span class="crayon-h"> </span><span class="crayon-c">#导入scrapy包</span></div><div class="crayon-line" id="crayon-5dea590faff96208426263-3"><span class="crayon-st">from</span><span class="crayon-h"> </span><span class="crayon-e">bs4 </span><span class="crayon-r">import</span><span class="crayon-h"> </span><span class="crayon-e">BeautifulSoup</span></div><div class="crayon-line crayon-striped-line" id="crayon-5dea590faff96208426263-4"><span class="crayon-st">from</span><span class="crayon-h"> </span><span class="crayon-v">scrapy</span><span class="crayon-sy">.</span><span class="crayon-e">http </span><span class="crayon-r">import</span><span class="crayon-h"> </span><span class="crayon-v">Request</span><span class="crayon-h"> </span><span class="crayon-c">##一个单独的request的模块,需要跟进URL的时候,需要用它</span></div><div class="crayon-line" id="crayon-5dea590faff96208426263-5"><span class="crayon-st">from</span><span class="crayon-h"> </span><span class="crayon-v">dingdian</span><span class="crayon-sy">.</span><span class="crayon-e">items </span><span class="crayon-r">import</span><span class="crayon-h"> </span><span class="crayon-v">DingdianItem</span><span class="crayon-h"> </span><span class="crayon-c">##这是我定义的需要保存的字段,(导入dingdian项目中,items文件中的DingdianItem类)</span></div><div class="crayon-line crayon-striped-line" id="crayon-5dea590faff96208426263-6">&nbsp;</div><div class="crayon-line" id="crayon-5dea590faff96208426263-7"><span class="crayon-t">class</span><span class="crayon-h"> </span><span class="crayon-e">Myspider</span><span class="crayon-sy">(</span><span class="crayon-v">scrapy</span><span class="crayon-sy">.</span><span class="crayon-v">Spider</span><span class="crayon-sy">)</span><span class="crayon-o">:</span></div><div class="crayon-line crayon-striped-line" id="crayon-5dea590faff96208426263-8">&nbsp;</div><div class="crayon-line" id="crayon-5dea590faff96208426263-9"><span class="crayon-h">&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="crayon-v">name</span><span class="crayon-h"> </span><span class="crayon-o">=</span><span class="crayon-h"> </span><span class="crayon-s">'dingdian'</span></div><div class="crayon-line crayon-striped-line" id="crayon-5dea590faff96208426263-10"><span class="crayon-h">&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="crayon-v">allowed_domains</span><span class="crayon-h"> </span><span class="crayon-o">=</span><span class="crayon-h"> </span><span class="crayon-sy">[</span><span class="crayon-s">'23wx.com'</span><span class="crayon-sy">]</span></div><div class="crayon-line" id="crayon-5dea590faff96208426263-11"><span class="crayon-h">&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="crayon-v">bash_url</span><span class="crayon-h"> </span><span class="crayon-o">=</span><span class="crayon-h"> </span><span class="crayon-s">'http://www.23wx.com/class/'</span></div><div class="crayon-line crayon-striped-line" id="crayon-5dea590faff96208426263-12"><span class="crayon-h">&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="crayon-v">bashurl</span><span class="crayon-h"> </span><span class="crayon-o">=</span><span class="crayon-h"> </span><span class="crayon-s">'.html'</span></div><div class="crayon-line" id="crayon-5dea590faff96208426263-13">&nbsp;</div><div class="crayon-line crayon-striped-line" id="crayon-5dea590faff96208426263-14"><span class="crayon-h">&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="crayon-r">def</span><span class="crayon-h"> </span><span class="crayon-e">start_requests</span><span class="crayon-sy">(</span><span class="crayon-r">self</span><span class="crayon-sy">)</span><span class="crayon-o">:</span></div><div class="crayon-line" id="crayon-5dea590faff96208426263-15"><span class="crayon-h">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="crayon-st">for</span><span class="crayon-h"> </span><span class="crayon-i">i</span><span class="crayon-h"> </span><span class="crayon-st">in</span><span class="crayon-h"> </span><span class="crayon-k ">range</span><span class="crayon-sy">(</span><span class="crayon-cn">1</span><span class="crayon-sy">,</span><span class="crayon-h"> </span><span class="crayon-cn">11</span><span class="crayon-sy">)</span><span class="crayon-o">:</span></div><div class="crayon-line crayon-striped-line" id="crayon-5dea590faff96208426263-16"><span class="crayon-h">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="crayon-v">url</span><span class="crayon-h"> </span><span class="crayon-o">=</span><span class="crayon-h"> </span><span class="crayon-r">self</span><span class="crayon-sy">.</span><span class="crayon-v">bash_url</span><span class="crayon-h"> </span><span class="crayon-o">+</span><span class="crayon-h"> </span><span class="crayon-k ">str</span><span class="crayon-sy">(</span><span class="crayon-v">i</span><span class="crayon-sy">)</span><span class="crayon-h"> </span><span class="crayon-o">+</span><span class="crayon-h"> </span><span class="crayon-s">'_1'</span><span class="crayon-h"> </span><span class="crayon-o">+</span><span class="crayon-h"> </span><span class="crayon-r">self</span><span class="crayon-sy">.</span><span class="crayon-e">bashurl</span></div><div class="crayon-line" id="crayon-5dea590faff96208426263-17"><span class="crayon-e">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="crayon-r">yield</span><span class="crayon-h"> </span><span class="crayon-e">Request</span><span class="crayon-sy">(</span><span class="crayon-v">url</span><span class="crayon-sy">,</span><span class="crayon-h"> </span><span class="crayon-r">self</span><span class="crayon-sy">.</span><span class="crayon-v">parse</span><span class="crayon-sy">)</span></div><div class="crayon-line crayon-striped-line" id="crayon-5dea590faff96208426263-18"><span class="crayon-h">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="crayon-r">yield</span><span class="crayon-h"> </span><span class="crayon-e">Request</span><span class="crayon-sy">(</span><span class="crayon-s">'http://www.23wx.com/quanben/1'</span><span class="crayon-sy">,</span><span class="crayon-h"> </span><span class="crayon-r">self</span><span class="crayon-sy">.</span><span class="crayon-v">parse</span><span class="crayon-sy">)</span></div><div class="crayon-line" id="crayon-5dea590faff96208426263-19">&nbsp;</div><div class="crayon-line crayon-striped-line" id="crayon-5dea590faff96208426263-20"><span class="crayon-h">&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="crayon-r">def</span><span class="crayon-h"> </span><span class="crayon-e">parse</span><span class="crayon-sy">(</span><span class="crayon-r">self</span><span class="crayon-sy">,</span><span class="crayon-h"> </span><span class="crayon-v">response</span><span class="crayon-sy">)</span><span class="crayon-o">:</span></div><div class="crayon-line" id="crayon-5dea590faff96208426263-21"><span class="crayon-h">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="crayon-k ">print</span><span class="crayon-sy">(</span><span class="crayon-v">response</span><span class="crayon-sy">.</span><span class="crayon-v">text</span><span class="crayon-sy">)</span></div></div></td>
				</tr>
			</tbody></table>
		</div>
	</div>

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

然后会像这样:

Spider编写03

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

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

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

继续 继续!

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

分析网页2

分析网页01

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

Go Go

Scrapy20

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

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

第二十五行至二十七行:我们照例拼接了一个完整的URL(response.url:就是这个response的URL地址)

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

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

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

 

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

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

Scrapy07

 

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

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

Scrapy09

前面三行不说了,

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

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

 

Scrapy10

这个页面就有很多我们需要的信息了:废话不说了代码上来:

Scrapy11

第四十行:将我们导入的item文件进行实例化,用来存储我们的数据。

后面全部:将需要的数据,复制给item[key] (注意这儿的Key就是我们前面在item文件中定义的那些字段。)

注意!response.meta[key]:这个是提取从上一个函数传递下来的值。

return item 就是返回我们的字典了,然后Pipelines就可以开始对这些数据进行处理了。比如 存储之类的。

好啦,Spiders我们先编写到这个地方。(是不是有小伙伴发现我还有几个字段没有取值?当然留着你们自己试试了,哈哈哈ヽ(=^・ω・^=)丿)后面再继续。

 

对于基本的Pipeline存储方式,网上有很多教程了,今天我们做一个自定义的MySQL的Pipeline:

首先为了能好区分框架自带的Pipeline,我们把MySQL的Pipeline单独放到一个目录里面。

Scrapy12

我们在项目中新建了一个mysqlpipelines的文件夹,我们所有的MySQL文件都放在这个目录。

init.py 这个文件不需要我说了吧,不知道做啥的小哥儿自己百度。

pipelines.py  这个是我们写存放数据的文件

sql.py 看名字就知道,需要的sql语句。

首先是需要的MySQL表,(MySQL都没有的小哥儿 自己百度装一个啊,我就不教了)

	<div id="crayon-5dea5a7635e31006764127" class="crayon-syntax crayon-theme-github crayon-font-monaco crayon-os-pc print-yes notranslate crayon-wrapped" data-settings=" minimize scroll-mouseover wrap" style="margin-top: 12px; margin-bottom: 12px; float: left; font-size: 12px !important; line-height: 15px !important; height: auto;">
	
		<div class="crayon-toolbar" data-settings=" show" style="font-size: 12px !important;height: 18px !important; line-height: 18px !important;"><span class="crayon-title"></span>
		<div class="crayon-tools" style="font-size: 12px !important;height: 18px !important; line-height: 18px !important;"><div class="crayon-button crayon-nums-button crayon-pressed" title="Toggle Line Numbers"><div class="crayon-button-icon" style="background-size: 48px 128px; background-image: url(&quot;https://cuiqingcai.com/wp-content/plugins/crayon-syntax-highlighter/css/images/toolbar/buttons@2x.png&quot;);"></div></div><div class="crayon-button crayon-plain-button" title="Toggle Plain Code"><div class="crayon-button-icon" style="background-size: 48px 128px; background-image: url(&quot;https://cuiqingcai.com/wp-content/plugins/crayon-syntax-highlighter/css/images/toolbar/buttons@2x.png&quot;);"></div></div><div class="crayon-button crayon-wrap-button crayon-pressed" title="Toggle Line Wrap"><div class="crayon-button-icon" style="background-size: 48px 128px; background-image: url(&quot;https://cuiqingcai.com/wp-content/plugins/crayon-syntax-highlighter/css/images/toolbar/buttons@2x.png&quot;);"></div></div><div class="crayon-button crayon-expand-button" title="Expand Code" style="display: none;"><div class="crayon-button-icon" style="background-size: 48px 128px; background-image: url(&quot;https://cuiqingcai.com/wp-content/plugins/crayon-syntax-highlighter/css/images/toolbar/buttons@2x.png&quot;);"></div></div><div class="crayon-button crayon-copy-button" title="Copy"><div class="crayon-button-icon" style="background-size: 48px 128px; background-image: url(&quot;https://cuiqingcai.com/wp-content/plugins/crayon-syntax-highlighter/css/images/toolbar/buttons@2x.png&quot;);"></div></div><div class="crayon-button crayon-popup-button" title="Open Code In New Window"><div class="crayon-button-icon" style="background-size: 48px 128px; background-image: url(&quot;https://cuiqingcai.com/wp-content/plugins/crayon-syntax-highlighter/css/images/toolbar/buttons@2x.png&quot;);"></div></div><span class="crayon-language">MySQL</span></div></div>
		<div class="crayon-info" style="min-height: 16.8px !important; line-height: 16.8px !important;"></div>
		<div class="crayon-plain-wrap"><textarea class="crayon-plain print-no" data-settings="dblclick" readonly="" style="tab-size: 4; font-size: 12px !important; line-height: 15px !important; z-index: 0; opacity: 0; overflow: hidden;">DROP TABLE IF EXISTS `dd_name`;

CREATE TABLE dd_name (
id int(11) NOT NULL AUTO_INCREMENT,
xs_name varchar(255) DEFAULT NULL,
xs_author varchar(255) DEFAULT NULL,
category varchar(255) DEFAULT NULL,
name_id varchar(255) DEFAULT NULL,
PRIMARY KEY (id)
) ENGINE=InnoDB AUTO_INCREMENT=38 DEFAULT CHARSET=utf8mb4;








1
2
3
4
5
6
7
8
9

DROP TABLE IF EXISTS dd_name;
CREATE TABLE dd_name (
   id int(11) NOT NULL AUTO_INCREMENT,
   xs_name varchar(255) DEFAULT NULL,
   xs_author varchar(255) DEFAULT NULL,
   category varchar(255) DEFAULT NULL,
   name_id varchar(255) DEFAULT NULL,
   PRIMARY KEY ( id)
) ENGINE = InnoDB AUTO_INCREMENT =38 DEFAULT CHARSET =utf8mb4;


首先我们再settings.py文件中定义好MySQL的配置文件(当然你也可以直接定义在sql.py文件中):

MySQL setting

PS :注意MySQL的默认端口是 3306;我自己的MySQL改成了3389。这儿各位酌情自己更改。

在开始写sql.py之前,我们需要安装一个Python操作MySQL的包,来自MySQL官方的一个包:点我下载

下载完成后解压出来,从CMD进入该目录的绝对路径,然后 Python  setup.py install ;即可完成安装

下面是我们的sql.py文件:

sql01

第一行至第二行分别导入了:我的MySQL操作包,settings配置文件

第四行至第八行 : 从settings配置文件中获取到了,我们的MySQL配置文件

第十行至第十一行: 初始化了一个MySQL的操作游标

第十三行: 定义了一个Sql的类

第十六行至第二十五行:定义了一个函数,将函数中的四个变量写入数据库(这四个变量就是我们后面传进来的需要存储的数据。)

关于@classmethod这个是一个修饰符;作用是我们不需要初始化类就可以直接调用类中的函数使用(具体说起来麻烦,知道作用就好啦)

好了第一部分写完了,我们还需要一个能够去重的:

sql01

这一段代码会查找name_id这个字段,如果存在则会返回 1 不存在则会返回0

 

 

Nice!sqi.py这一部分我们完成,来开始写pipeline吧:

pipeline02

第一行至第二行:我们导入了之前编写的sql.py中的Sql类,和我们建立的item

第六行:建立了一个DingdianPipeline的类(别忘了一定要继承object这个类啊,这是做啥的不用多了解,说多了你们头晕,我也懒)

第八行:我们定义了一个process_item函数并有,item和spider这两个参数(请注意啊!这两玩意儿 务必!!!要加上!!千万不能少!!!!务必!!!务必!!!)

第十行:你这样理解如果在 item中存在DingdianItem;就执行下面的。

第十一行:从item中取出 name_id的值。

第十二行:调用Sql中的select_name函数获得返回值

第十三行:判断ret是否等于1 ,是的话证明已经存了

第二十行:调用Sql中的 insert_dd_name函数,存储上面几个值。

搞完!下面我们启用这个Pipeline在settings中作如下设置:

setting02

PS: dingdian(项目目录).mysqlpipelines(自己建立的MySQL目录).pipelines(自己建立的pipelines文件).DingdianPipeline(其中定义的类) 后面的 1 是优先级程度(1-1000随意设置,数值越低,组件的优先级越高)

好!我们来运行一下试试!!Go Go Go!

scrapy15

Nice!!完美!!我之前运行过了 所以提示已经存在。

scrapy17

首先我们在item中新定义一些需要获取内容的字段:

scrapy16

代码不解释了哦!(懒癌来了,写不下去了)

继续编写Spider文件:

scrapy18

请注意我图中画红框的的地方,这个地方返回item是不能用return的哦!用了就结束了,程序就不会继续下去了,得用yield(你知道就行,这玩意儿说起来麻烦。)

第五十八行: num这个变量的作用是  因为Scrapy是异步的方式运作,你采集到的章节顺序都是混乱的,需要给它有序的序列,我们按照这个排序就能得到正确的章节顺序啦

请注意在顶部导入定义的第二个item类!

下面我们来写存储这部分spider的Pipeline:

数据表:

	<div id="crayon-5dea5ab83afe4853724687" class="crayon-syntax crayon-theme-github crayon-font-monaco crayon-os-pc print-yes notranslate crayon-wrapped" data-settings=" minimize scroll-mouseover wrap" style="margin-top: 12px; margin-bottom: 12px; float: left; font-size: 12px !important; line-height: 15px !important; height: auto;">
	
		<div class="crayon-toolbar" data-settings=" show" style="font-size: 12px !important;height: 18px !important; line-height: 18px !important;"><span class="crayon-title"></span>
		<div class="crayon-tools" style="font-size: 12px !important;height: 18px !important; line-height: 18px !important;"><div class="crayon-button crayon-nums-button crayon-pressed" title="Toggle Line Numbers"><div class="crayon-button-icon" style="background-size: 48px 128px; background-image: url(&quot;https://cuiqingcai.com/wp-content/plugins/crayon-syntax-highlighter/css/images/toolbar/buttons@2x.png&quot;);"></div></div><div class="crayon-button crayon-plain-button" title="Toggle Plain Code"><div class="crayon-button-icon" style="background-size: 48px 128px; background-image: url(&quot;https://cuiqingcai.com/wp-content/plugins/crayon-syntax-highlighter/css/images/toolbar/buttons@2x.png&quot;);"></div></div><div class="crayon-button crayon-wrap-button crayon-pressed" title="Toggle Line Wrap"><div class="crayon-button-icon" style="background-size: 48px 128px; background-image: url(&quot;https://cuiqingcai.com/wp-content/plugins/crayon-syntax-highlighter/css/images/toolbar/buttons@2x.png&quot;);"></div></div><div class="crayon-button crayon-expand-button" title="Expand Code" style="display: none;"><div class="crayon-button-icon" style="background-size: 48px 128px; background-image: url(&quot;https://cuiqingcai.com/wp-content/plugins/crayon-syntax-highlighter/css/images/toolbar/buttons@2x.png&quot;);"></div></div><div class="crayon-button crayon-copy-button" title="Copy"><div class="crayon-button-icon" style="background-size: 48px 128px; background-image: url(&quot;https://cuiqingcai.com/wp-content/plugins/crayon-syntax-highlighter/css/images/toolbar/buttons@2x.png&quot;);"></div></div><div class="crayon-button crayon-popup-button" title="Open Code In New Window"><div class="crayon-button-icon" style="background-size: 48px 128px; background-image: url(&quot;https://cuiqingcai.com/wp-content/plugins/crayon-syntax-highlighter/css/images/toolbar/buttons@2x.png&quot;);"></div></div><span class="crayon-language">MySQL</span></div></div>
		<div class="crayon-info" style="min-height: 16.8px !important; line-height: 16.8px !important;"></div>
		<div class="crayon-plain-wrap"><textarea class="crayon-plain print-no" data-settings="dblclick" readonly="" style="tab-size: 4; font-size: 12px !important; line-height: 15px !important; z-index: 0; opacity: 0; overflow: hidden;">DROP TABLE IF EXISTS `dd_chaptername`;

CREATE TABLE dd_chaptername (
id int(11) NOT NULL AUTO_INCREMENT,
xs_chaptername varchar(255) DEFAULT NULL,
xs_content text,
id_name int(11) DEFAULT NULL,
num_id int(11) DEFAULT NULL,
url varchar(255) DEFAULT NULL,
PRIMARY KEY (id)
) ENGINE=InnoDB AUTO_INCREMENT=2726 DEFAULT CHARSET=gb18030;
SET FOREIGN_KEY_CHECKS=1;








1
2
3
4
5
6
7
8
9
10
11

DROP TABLE IF EXISTS dd_chaptername;
CREATE TABLE dd_chaptername (
   id int(11) NOT NULL AUTO_INCREMENT,
   xs_chaptername varchar(255) DEFAULT NULL,
   xs_content text,
   id_name int(11) DEFAULT NULL,
   num_id int(11) DEFAULT NULL,
   url varchar(255) DEFAULT NULL,
   PRIMARY KEY ( id)
) ENGINE = InnoDB AUTO_INCREMENT =2726 DEFAULT CHARSET =gb18030;
SET FOREIGN_KEY_CHECKS =1;


 

Sql.py:

Scrapy13

Scrapy14

不解释了哦!

下面是Pipeline:

scrapy21

有小伙伴注意,这儿比上面一个Pipeline少一个判断,因为我把判断移动到Spider中去了,这样就可以减少一次Request,减轻服务器压力。

改变后的Spider长这样:

Scrapy16

别忘了在spider中导入Sql哦!ヾ(。 ̄□ ̄)ツ゜゜゜

 

到此收工!!!!

至于小说图片,因为Scrapy的图片下载管道,是自动以md5命名,而且感觉不爽··· 后面单独写一个异步下载的脚本···

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值