开头来波小程序摇一摇:
最近皮爷读书,看到了一个很牛逼的理论:
注意力 > 时间 > 金钱复制代码
具体怎么理解,各位看官各有各的理解,我就不多说了。
近几篇文章,可以说的上是精品文章,而且是精品中的精品。请诸位看官仔细阅读。我准备给大家好好的说道说道Scrapy的爬虫具体应该怎么写,怎么用CrawSpider,这几篇文章,算是一个进阶内容,短时间暴力进阶?具体目标:读过文章之后,你就可以写一个通用的爬虫,超级灵活的爬虫。
现在看来,市面上大部分关于讲爬虫的文章,都可以算是入门级别。虽然有些文章说的很巧,比如有些场合适合用requests直接写啊,有些场合用NumPy就可以搞定,还有些场合没有必要用Scrapy这么厉害的框架来做之类的。可见,你学习爬虫如今面临这么几个问题和思考:
- 市面上的爬虫文章种类繁多,而且方法各异,对于萌新选择入门学习造成困扰,因为太多了。
- 种类繁多,百花争鸣是好事儿,而且丰富了大家的眼界,可是,你是否曾想过,你学习爬虫是为了干什么?
- 爬虫如果是为了自己玩,那么,学习百家戏,确实没有问题;但是如果为了面试找工作呢?
- 很多萌新是读大学的学生,他们基础比较差(不要嫌我说的重,现在大学生的基础,确实很差,不信你工作几年回头看当时的自己,当然,如果你工作也不进步的话,可以忽略我说的),所以,他们的目标很简单,就是为了求职找工作。
- 如果为了面试,那么你有没有想过用人单位最需要什么样的人啊?当然是面试通过之后就能直接来上班的人。什么样的人能上班?当然是会使用企业爬虫框架的人啊。
- 这就引出了一个新的问题:什么爬虫框架企业会使用?
- 目前来说,一般企业用的都是自己修改过的Scrapy框架,所以,你如果学好Scrapy框架的话,对于找工作很有优势。
- 再多一句,你如果有所研究Scrapy爬虫框架的话,那么对于其他的爬虫框架或者原理,你也可以做到触类旁通的层面。
综上所述,才有了这几篇爬虫进阶文章,专门为你拔高 Scrapy 的使用上限。等你读完,你就知道,之前你自己写的 Scrapy 爬虫,都是屎,相信我,你肯定会有,我自己就有这种感觉。
既然是干货公号,那么我们基本就是以实战为主。不知大家是否还看过我之前写的一篇文章『Python爬虫加速神器的牛刀小试,就问你怕不怕』,没有看过的,可以在公众号里面的历史文章里面查阅,这篇文章主要就是讲了一下用 aiohttp 来做爬虫。目标是爬取的美剧排行榜里面的信息。
目标网页是下面这个:
http://www.ttmeiju.me/index.php/summary/index/p/1.html复制代码
长这个样子:
那篇文章只是简单的介绍一下 aiohttp 的使用,其实并不能作为爬虫生产工具。所以,从这篇文章开始,我会系统的给你们讲解 Scrapy ,最后让你们可以产出一个可以实际生产的爬虫工具。
0x00_序
在此之前,皮爷写的爬虫,基本上都是选用的 scrapy.Spider 里面的最基本款,即 spider。其实 scrapy 的 spider 还有好多种:CrawlSpider, XMLFeedSpider, CSVFeedSpider, SitemapSpider。今天我们做通用爬虫的需要用到 CrawSpider。
0x01_需求分析
还是很简单,和上回一样,爬取所有排行榜网页(总共36页),然后将每一条的关键信息存到一个类里面,最后把所有信息存入到阿里云上的 MongoDB 里面。
这次,我们准备用 CrawlSpider 来做。
0x02_CrawlSpider
CrawlSpider 是 scrapy.Spider 的一个子类,他是在原有 spider 上面的扩展。他拥有父类所有的特性,同时也有自己独特的地方:通过 Rule 来提取网页信息。
通俗的说,就是爬虫通过开发者定义的爬取规则(Rule),来从网页信息里面提取 link,然后做相应的操作处理。
这其中,我们使用 xpath 来做提取器,当然也可以使用CSS selector,但是我们不再使用 BeautifulSoup。虽然 BeautifulSoup 写起来更加简单易懂,适合萌新使用,但是从速度方面考虑, xpath 要更胜一筹,而且如果运用熟练之后, xpath 的开发速度是要比 BeautifulSoup 快很多的。
0x03_创建项目
创建 Scrapy 项目很简单,我们只需要在终端里面输入指令就好。如果对 Scrapy 命令不是很熟悉的,可以选择百度,也可以选择输入 scrapy --help
来查看帮助文档。
当然,如果遇到哪个 scrapy 的指令不会,也可以用 --help
来查看文档。
创建项目,只需要挨个输入以下命令就可以了:
$ scrapy startproject HellProject$ cd HellProject/$ scrapy genspider -t crawl playranking www.ttmeiju.me复制代码
这一系列命令敲好之后,我们就成功的创建了我们的 Scrapy 工程。下面,我们用 PyCharm 打开,就长下面这个样子:
至此,创建项目的任务就告一段落,接下来就是我们的撸码环节。
0x05_编写CrawlSpider
这里我们是通过命令行 scrapy genspider -t crawl <spiderName> <hostAddress>
创建的CrawlSpider,并非之前的 scrapySpider,所以,代码的样子长得和之前有所区别。
其实,CrawlSpider最关键的部分就是红色框框里面的 rules 的编写。因为 CrawlSpider 每次会按照 rules 的规则来提取出来页面中的 link,再遍历访问所有提取出来的 link,处理爬取结果。
所以,针对我们这里的需求,我们可以预估出来我们只要写一个 Rule 就可以,即:
每一页面最下面的 页数 部分,而且,我们只要提取出来 下一页
的链接就可以,即图中蓝色圈圈对应的地方。我们检查
网页:
发现 >>
对应的是一个 ul
标签底下的 a
标签,并且这个 a
标签有明显的特征,就是 class=next
,这就简单了。
我们这里为了提取网页信息内容,不再采取之前的BeautifulSoup 方法,而且采取更加快捷的 xpath 方法来提取分析网页。
刚开始接触 xpath 的同学,可能对我这里的写法有一些跳跃,但是不要慌,等你看完我的这几篇文章之后,我在项目里面所用到的 xpath 的那几种写法,其实就已经完全能够覆盖到你 95% 以上的日常所需了。所以,别慌,静下心来细细读文章。
接着说,我们这里要编写 Rule, 看到项目例子里面给的是一个叫 LinkExtractor 的东西,这个从字面意思就能看出来是一个 Link提取器,我们这里就照猫画虎的来写我们第一个 LinkExtractor 。
由于我们是采用 xpath 来定位数据,这里多给大家说一个调试 xpath 的小技巧: 使用 scrapy shell
来进行调试!!!
在终端,直接输入 $ scrapy shell
命令,就进入了大名鼎鼎的 scrapy shell 里面了。退出scrapy shell直接输入 exit
然后按回车即可。
我们要在:
http://www.ttmeiju.me/index.php/summary/index/p/1.html复制代码
这个页面调用 xpath 来分析,所以,我们有两种方式来调试:
- 终端通过命令
$ scrapy shell
进入 shell 中,然后直接调用fetch()
函数即可,括号里面填写要访问的url地址。 - 或者直接在命令行输入后
$ scrapy shell http://www.ttmeiju.me/index.php/summary/index/p/1.html
,即在最后一个参数直接跟页面url即可。
我采用的是第二种方法,成功打开shell之后长下面这个样子:
其实到这里,shell 已经将我们的页面访问过了,并且放到了 response 里面,你直接输入 response
、 response.text
或者 response.body
是可以看到结果的。
在这个 shell 界面,我们就可以调试 xpath 了,怎么调试?这么调试,直接写代码:
response.xpath('//ul//a[@class="next"]')response.xpath('//ul//a[@class="next"]').extract()response.xpath('//ul//a[@class="next"]//text()').extract()复制代码
这三个对应的就是你要的在 ul
标签下的 a
标签,并且 a
标签的 class=next
:
你看,这里是不是提取出来的 text
是 >>
?
如果你要提取别的东西,直接输入 response.xpath()
括号里面填写选择条件即可:
这个就是选出来页面中所有的 li
标签。
接下来我们就返回来看我们的 LinkExtractor 怎么写:
rules = ( Rule(LinkExtractor(restrict_xpaths='//ul[@class="pagination"]//a[@class="next"]'), callback='parse_item', follow=True), )复制代码
看到这里我们就把之前的xpath的 (Items/)
改为 (//ul[@class="pagination"]//a[@class="next"])
。
同时,我们把 start_urls
改为:
start_urls = ['http://www.ttmeiju.me/']复制代码
稍微修改一下底下的 parse_item() 函数:
def parse_item(self, response): print(response.url)复制代码
我们的目的就是看我们的爬虫是否可以顺利的一页一页的按照 下一页
来爬取网页,然后我们通过命令 scrapy crawl playranking
运行一下爬虫,看一下结果:
这里可以看到,log里面顺利的打出了从 1 ~ 36 页的 URL,证明我们的程序没有问题。那么接下来的爬虫,我们将在之后的章节讲述。
这里说一下哈,所有的爬虫代码,我均已发布到网上了,获取方法很简单,关注公号『皮爷撸码』,回复『代码』即可找到,记住对应的代码编号是『CS001』,代码编号是『CS001』,代码编号是『CS001』。
『皮爷撸码』,一个很硬核的公号,如果你能从这里学到知识,皮爷很高兴,很希望你也能够将这份内容分享出去,让更多的人感受到编程的乐趣。