好了,开始上课(好像并没有人,但是没关系,我就是这么自嗨。)

开始要说明我的操作环境,如果你和我的不一样,请阅读本文的时候注意代码的差别:

  1. python版本:3.6.1
  2. scrapy版本:1.3.2
  3. 编译器:pycharm 2017.1.1

首先要说的是,scrapy的原理我不讲,自己领会(其实我也讲不出什么,网上一堆一堆的,讲的都跟我想说的一样,笔芯。)

然后开始进入正题。你需要了解scrapy是一个第三方库,运行开始前,你需要在本机安装scrapy,现在scrapy对windows平台也十分友好了(也许是最新版更友好了),或者是因为我安装了virtual studio 2015的原因,因为有一些bat脚本是scrapy的依赖库比如twisted所需要的。

virtual studio 2015就是下图所示软体(当然,我没有激活,但是不影响对各种python第三方工具的安装,虽然它体积大的惊人):

你可以查看网上各种各样的scrapy安装教程以及各种填坑指南,但是因为我可能是安装了以上的编译器,安装异常顺利。

打开cmd,然后执行命令

pip install scrapy

安装完成,就这这么简单。

当然,其实我是更懒的。

我一般都是打开pycharm->File->Settings...->Project:xxx->Project Interpreter->"+"->搜索"scrapyt"进行安装。这个方法简单快捷,更主要的是,如果你有虚拟环境,对虚拟环境的切换也是如丝般顺滑。

安装成功之后,就是新建工程了。

在我学习python的过程中,只有scrapy和django是直接建立工程,通过工程进行程序的运行(如果你知道更多的,你可以私信告诉我,现在请配合我假装不知道这回事。)

新建工程这回事也没什么困难的,就是在cmd中敲一条命令。

scrapy startproject meitulu

注意:新建的工程在当前目录下,请确认想要保存的路径。

敲完命令的效果如下图所示(我是用的是pycharm中的终端,效果和CMD是一样的):

新建完成之后的目录结构如下图所示(还是pycharm中显示的结构):

建立完工程后,你可以看到终端中提示了你怎么建立一个简单的爬虫文件。

按照终端中提示的进行操作:

cd meitulu
scrapy genspider mtl meitulu.com

终端中显示如下图所示:

可以看到提示已经在spider目录下创建了一个文件,目录结构现在如下所示:

打开mtl.py,可以看到如所示:

其中,MtlSpider是类名,不用管,可以随便起没有影响(如果你不明白什么是类,请再巩固一下python基础知识)。name是爬虫唯一标识,需要唯一,不能重复(后期很多爬虫的时候,你可能会写很多名字,每个名字都不能重复),allow_domins是允许爬取的目标网站的域名,大概下一篇文章你就知道作用是什么了,这里先买一个关子(本来是想在这篇文章中写的,但是我还是太懒了,哈哈哈,ran)。start_urls是开始爬取的url网址。parse是爬取目标网站后的处理程序,parse中的response是目标网站回应的信息,包括头、状态、回应主体等等。

我们需要爬取的是美图录的一个类别,网址是:

http://www.meitulu.com/guochan/

修改mtl.py 将start_urls替换为以下方法:

def start_requests(self):
if os.path.exists(os.path.join(os.getcwd(), "meitulu/target.html")):
url = "file:///%s" % os.path.join(os.getcwd(), "meitulu/target.html")
else:
url = "http://www.meitulu.com/guochan/"
yield scrapy.Request(url=url, callback=self.parse)

start_urls和start_requests都是开始进行爬取的url,不同的是一个是变数一个是方法(废话)。

可以看到我上面使用了os模块,os模块是python自带的模块,不需要安装,只要进行导入就行。

import os

os.path.exists(dir)的含义是dir是否存在,存在则为True,不存在则为False,os.path.join()的含义是将内部的路径进行拼接,而os.getcwd()的意思是获取当前路径。

这句话(os.path.exists(os.path.join(os.getcwd(), "meitule/target.html")))整体的意思就是看scrapy路径下的meitule目录中是否含有target.html缓存。至于为什么需要缓存,请参考python爬虫之scrapy扫盲:搜集美图信息之先发一些牢骚(0) - 知乎专栏这篇文章。

可以看到,start_requests最后使用了回调函数parse(默认就使用这个函数进行回调,所以理论上来说并不需要进行填写)。

方法parse就是为了解析访问url后所返回数据的一个方法。

通过chrome打开网址,并打开"Developer Tools"之后,我们可以看到所有的图片的代码都如下所示:

所有的图片都放在了列表里面(如果你不明白我再说什么,你应该看看html前端页面的一些知识,html中ul是无序列表,每一项使用li标签包围。遍查整个知乎,爬虫的居然没有人详细的介绍一下chrome的开发者工具的使用方法的,难道工具的使用都不是重点么,我倒是觉得chrome的开发者工具用好了,写爬虫的时候才会事半功倍。)

好了,接下来拿取我们数据吧。

parse方法内容如下:

def parse(self, response):
# 如果没有缓存,保存缓存
if not os.path.exists(os.path.join(os.getcwd(), "meitulu/target.html")):
with open(os.path.join(os.getcwd(), "meitulu/target.html"), wb) as f:
f.write(response.body)

# 提取图片所在区域,因为只是教程,只选取前两个图片的信息
imgul = response.xpath("//ul[@class=img]/li[position()<3]")

# 进一步提取出相应的信息
for item in imgul:
yield {
# 图片url
"imgurl": item.xpath("./a/img/@src").extract_first(),
# 点攒数
"upvote": item.xpath("./p[1]/span/text()").extract_first(),
# "num": item.xpath("./p[1]/string(.)[2]").extract_first(),
# 浏览数
"num": item.xpath("./p[1]/text()").extract_first(),
# 组织名称
"organization_name": item.xpath(".//p[2]/a/text()").extract_first(),
# 组织url
"organization_url": item.xpath(".//p[2]/a/@href").extract_first(),
# 模特名称
"model_name": item.xpath("./p[3]/text()").extract_first(),
# 整体标签名称
"tag_name": item.xpath("./p[4]//a/text()").extract(),
# 标签url
"tag_url": item.xpath("./p[4]//a/@href").extract(),
# 主题
"title": item.xpath("./p[5]/a/text()").extract_first(),
}

每一句的内容就是上面注释所描写的内容。

好了整体的mtl.py都写好了(整体代码写在了最后。),接下来该运行程序了,scrapy该怎么运行呢?

还记得之前的cmd框吗?、对,就是那个,在里面输入以下命令就可以运行scrapy了。

scrapy crawl mtl -o mtl.jl

其中mtl就是我们在mtl.py中定义的name,如果你的name不一样,进行更改就可以了,-o mtl.jl是保留日志,马上你就会知道是什么意思了。

什么?你把cmd框关了,没关系,打开cmd框,进入scrapy目录,还是运行上面的命令就可以了。

什么?你说你运行不爽,只想用IDE运行?我只能说你想的真多,但是还真的能使用IDE进行运行。只不过方法与上面的有些不同。

在scrapy的目录下(和scrapy.cfg同一级目录),新建一个py文件,叫什么无所谓,然后输入以下代码:

from scrapy import cmdline

# 美图录图片下载
cmdline.execute("scrapy crawl mtl -o mtl.jl".split())

运行这个文件就可以了。

好了直接运行这个文件,结果如下:

可以看到,信息已经取出来了。

同时,在scrapy的工程目录下,生成了一个mtl.jl文件,打开看可以看到将信息存入了进去:

图上的并不是乱码,是因为将中文显示为了utf8编码显示(如果我说错了,会在改正)。

注意:mtl.jl不是覆盖式写入是追加式写入,每运行一次程序mtl.jl体积就会增长,你完全可以删除mtl.jl再运行程序,程序会重新生成这个文件,或者取消之前文件中的"-o mtl.jl"。(我这种洁癖总是会在这种方面注意-_-|||)

同时,你也将看到有缓存网页target.html生成。

最终结构如下所示:

这个entry_meitulu.py就是我要运行的入口函数。

好了,同学们,今天这一讲就讲到这里,下课,回家。

(如果你仔细的话就会发现,为什么图片外面的链接地址没有爬取下来呢?恭喜你,你已经会抢答了。这就是下一讲的内容,通过页面链接再爬取其他页面,其中就会包含了allow_domins的坑。)


推荐阅读:
相关文章