python scrapy 爬虫实例_Python 爬虫:Scrapy 实例(一)

原标题:Python 爬虫:Scrapy 实例(一)

1、创建Scrapy项目

似乎所有的框架,开始的第一步都是从创建项目开始的,Scrapy也不例外。在这之前要说明的是Scrapy项目的创建、配置、运行……默认都是在终端下操作的。不要觉得很难,其实它真的非常简单,做填空题而已。如果实在是无法接受,也可以花点心思配置好Eclipse,在这个万能IDE下操作。推荐还是在终端操作比较好,虽然开始可能因为不熟悉而出现很多错误,错多了,通过排错印象深刻了,也就自然学会了。打开Putty连接到Linux,开始创建Scrapy项目。执行命令:

cd

cd code/scrapy/

scrapy startproject todayMovie

tree todayMovie

执行结果如图1所示。

图1 创建todayMovie项目

tree命令将以树形结构显示文件目录结构。tree命令默认情况下是没有安装的,可以执行命令apt-get install tree来安装这个命令。

这里可以很清楚地看到todayMovie目录下的所有子文件和子目录。至此Scrapy项目todayMovie基本上完成了。按照Scrapy的提示信息,可以通过Scrapy的Spider基础模版顺便建立一个基础的。相当于把填空题打印到试卷上,等待填空了。当然,也可以不用Scrapy命令建立基础,如果非要体验一下DIY也是可以的。这里我们还是怎么简单怎么来吧,按照提示信息,在该终端中执行命令:

cd todayMovie

scrapy genspider wuHanMovieSpider mtime.com

执行结果如图2所示。

图2 创建基础爬虫

至此,一个最基本的项目已经建立完毕了,它包含了一个Scrapy所需的基础文件。到这一步可以说填空题已准备完毕,后面的工作就纯粹是填空了。图2中第一行文字scrapy genspider是一个命令,也是Scrapy最常用的几个命令之一,它的使用方法如图3所示。

图3 scrapy genspider命令帮助

因此,刚才的命令意思是使用scrapy genspider命令创建一个名字为wuHanMovieSpider的爬虫脚本。这个脚本搜索的域为mtime.com。

2、Scrapy文件介绍

Scrapy项目的所有文件都已经到位了,如图2所示,下面来看看各个文件的作用。首先最顶层的那个todayMovie文件夹是项目名,这个没什么好说的。

在第二层中是一个与项目同名的文件夹todayMovie和一个文件scrapy.cfg,这里与项目同名的文件夹todayMovie是模块(也可以叫做包的),所有的项目代码都在这个模块(文件夹或者叫包)内添加。而scrapy.cfg文件,顾名思义它是整个Scrapy项目的配置文件。来看看这个文件里有些什么。Scrapy.cfg文件内容如下:

1 # Automatically created by: scrapy startproject

2 #

3 # For more information about the [deploy] section see:

4 # http://doc.scrapy.org/en/latest/topics/scrapyd.html

5

6 [settings]

7 default = todayMovie.settings

8

9 [deploy]

10 #url = http://localhost:6800/

11 project = todayMovie

除去以“#”为开头的注释行,整个文件只声明了两件事:一是定义默认设置文件的位置为todayMovie模块下的settings文件,二是定义项目名称为todayMovie。

在第三层中有6个文件和一个文件夹(实际上这也是个模块)。看起来很多。实际上有用的也就3个文件,分别是items.py、pipelines.py、settings.py。其他的3个文件中,以pyc结尾的是同名程序编译得到的字节码文件,settings.pyc是settings.py的字节码文件,__init__.pyc是__init__.py的字节码文件。据说用来加快程序的运行速度,可以忽视。至于__init__.py文件,它是个空文件,里面什么都没有。在此处唯一的作用就是将它的上级目录变成了一个模块。也就是说第二层的todayMovie模块下,如果没有__init__.py文件。那么todayMovie就只是一个单纯的文件夹。在任何一个目录下添加一个空的__init__.py文件,就会将该文件夹模块化,可以供导入使用。

有用的这3个文件中。settings.py是上层目录中scrapy.cfg定义的设置文件。settings.py的内容如下:

1 # -*- coding: utf-8 -*-

2

3 # Scrapy settings for todayMovie project

4 #

5 # For simplicity, this file contains only settings considered importantor

6 # commonly used. You can find more settings consulting thedocumentation:

7 #

8 # https://doc.scrapy.org/en/latest/topics/settings.html

9 # https://doc.scrapy.org/en/latest/topics/downloader-middleware.html

10 # https://doc.scrapy.org/en/latest/topics/spider-middleware.html

11

12 BOT_NAME = 'todayMovie'

13

14 SPIDER_MODULES = ['todayMovie.spiders']

15 NEWSPIDER_MODULE = 'todayMovie.spiders'

16

17

18 # Crawl responsibly by identifying yourself (and your website) on the

user-agent

19 #USER_AGENT = 'todayMovie (+http://www.yourdomain.com)'

20

21 # Obey robots.txt rules

22 ROBOTSTXT_OBEY = True

items.py文件的作用是定义爬虫最终需要哪些项,items.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

11 class TodaymovieItem(scrapy.Item):

12 # define the fields for your item here like:

13 # name = scrapy.Field

14 pass

pipelines.py文件的作用是扫尾。Scrapy爬虫爬取了网页中的内容后,这些内容怎么处理就取决于pipelines.py如何设置了。pipeliens.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

9 class TodaymoviePipeline(object):

10 def process_item(self, item, spider):

11 return item

第二层中还有一个spiders的文件夹。仔细看一下,在该目录下也有个__init__.py文件,说明这个文件夹也是一个模块。在该模块下是本项目中所有的爬虫文件。

第三层中有3个文件,__init__.py、__init__.pyc、wuHanMovieSpider.py。前两个文件刚才已经介绍过了,基本不起作用。wuHanMovieSpider.py文件是刚才用scrapy genspider命令创建的爬虫文件。wuHanMovieSpider.py文件内容如下:

1 # -*- coding: utf-8 -*-

2 import scrapy

3

4

5 class WuhanmoviespiderSpider(scrapy.Spider):

6 name = "wuHanMovieSpider"

7 allowed_domains = ["mtime.com"]

8 start_urls = (

9 'http://www.mtime.com/',

10 )

11

12 def parse(self, response):

13 pass

在本次的爬虫项目示例中,需要修改、填空的只有4个文件,它们分别是items.py、settings.py、pipelines.py、wuHanMovieSpider.py。其中items.py决定爬取哪些项目,wuHanMovieSpider.py决定怎么爬,settings.py决定由谁去处理爬取的内容,pipelines.py决定爬取后的内容怎样处理。

3、Scrapy爬虫编写

My first scrapy crawl怎么简单,怎么清楚就怎么来。这个爬虫只爬取当日电影名字,那我们只需要在网页中采集这一项即可。

(1)选择爬取的项目items.py

修改items.py文件如下:

1 # -*- coding: untf-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

11 class TodaymovieItem(scrapy.Item):

12 # define the fields for your item here like:

13 # name = scrapy.Field

14 #pass

15 movieTitleCn = scrapy.Field #影片中文名

16 movieTitleEn = scrapy.Field #影片英文名

17 director = scrapy.Field #导演

18 runtime = scrapy.Field #电影时长

由于中严格的格式检查。中最常见的异常Indentati会经常出现。如果使用的编辑器是vi或者vim,强烈建议修改vi的全局配置文件/etc/vim/vimrc,将所有的4个空格变成tab。

与最初的items.py比较一下,修改后的文件只是按照原文的提示添加了需要爬取的项目,然后将类结尾的pass去掉了。这个类是继承与Scrapy的Iteam类,它没有重载类的__init__的解析,没有定义新的类,只定义了类成员。

(2)定义怎样爬取wuHanMovieSpider.py

修改spiders/wuHanMovieSpider.py,内容如下:

1 # -*- coding: utf-8 -*-

2 import scrapy

3 from todayMovie.items import TodaymovieItem

4 import re

5

6

7 class WuhanmoviespiderSpider(scrapy.Spider):

8 name = "wuHanMovieSpider"

9 allowed_domains = ["mtime.com"]

10 start_urls = [

11 'http://theater.mtime.com/China_Hubei_Province_Wuhan_Wuchang/4316/',

12 ] #这个是武汉汉街万达影院的主页

13

14

15 def parse(self, response):

16 selector =response.xpath('/html/body/[3]/text')[0].extract

17 moviesStr = re.search('"movies":[.*?]', selector).group

18 moviesList = re.findall('{.*?}', moviesStr)

19 items = []

20 for movie in moviesList:

21 mDic = eval(movie)

22 item = TodaymovieItem

23 item['movieTitleCn'] = mDic.get('movieTitleCn')

24 item['movieTitleEn'] = mDic.get('movieTitleEn')

25 item['director'] = mDic.get('director')

26 item['runtime'] = mDic.get('runtime')

27 items.append(item)

28 return items

在这个文件中,首先导入了scrapy模块,然后从模块(包)todayMovie中的items文件中导入了TodaymovieItem类,也就是刚才定义需要爬行内容的那个类。WuhanmovieSpider是一个自定义的类,它是由scrapy genspider命令自动生成的。这个自定义类继承于scrapy.Spider类。第8行的name定义的是名。第9行的allowed_domains定义的是域范围,也就是说该只能在这个域内爬行。第11行的start_urls定义的是爬行的网页,这个只需要爬行一个网页,所以在这里start_urls可以是一个元组类型。如果需要爬行多个网页,最好使用列表类型,以便于随时在后面添加需要爬行的网页。

类中的parse函数需要参数response,这个response就是请求网页后返回的数据。至于怎么从response中选取所需的内容,一般采取两种方法,一是直接在网页上查看网页源代码,二是自己写个Python 3程序使用urllib.request将网页返回的内容写入到文本文件中,再慢慢地查询。

打开Chrome浏览器,在地址栏输入爬取网页的地址,打开网页。

同一网页内的同一项目格式基本上都是相同的,即使略有不同,也可以通过增加挑选条件将所需的数据全部放入选择器。在网页中右击空白处,在弹出菜单中选择“查看网页源代码”。

打开源代码网页,按Ctrl+F组合键,在查找框中输入“寻梦环游记”后按回车键,查找结果如图4所示。

图4 查找关键词

整个源代码网页只有一个查询结果,那就是它了。而且很幸运的是,所有的电影信息都在一起,是以json格式返回的。这种格式可以很容易地转换成字典格式获取数据(也可以直接json模块获取数据)。

仔细看看怎样才能得到这个“字典”(json格式的字符串)呢?如果嵌套的标签比较多,可以用XPath嵌套搜索的方式来逐步。这个页面的源码不算复杂,直接Tag标签后一个一个的数标签就可以了。Json字符串包含在标签内,数一下标签的位置,在脚本中执行语句:

16 selector = response.xpath('/html/body/[3]/text')[0].extract( )

意思是选择页面代码中html标签下的body标签下的第4个标签。然后获取这个标签的所有文本,并释放出来。选择器的选择到底对不对呢?可以验证一下,在该项目的任意一级目录下,执行命令:

scrapy shell

http://theater.mtime.com/China_Hubei_Province_Wuhan_Wuchang/4316/

执行结果如图5所示。

图5 scrapy shell

response后面的200是网页返回代码,200代表获取数据正常返回,如果出现其他的数字,那就得仔细检查代码了。现在可以放心地验证了,执行命令:

selector =

response.xpath('/html/body/[3]/text')

[0].extract

print(selector)

执行结果如图6所示。

图6 验证选择器

看来选择器的选择没问题。再回头看看wuHanMovieSpider.py中的parse就很容易理解了。代码第17、18行先用re模块将json字符串从选择器的结果中过滤出来。第19行定义了一个items的空列表,这里定义items的列表是因为返回的item不止一个,所以只能让item以列表的形式返回。第22行item初始化为一个TodaymoizeItem的类,这个类是从todayMovie.items中初始化过来的。第21行将json字符串转换成了一个字典格式。第23~26行将已经初始化类item中的movieName项赋值。第27行将item追加到items列表中去。最后return items,注意这里返回的是items,不是item。

(3)保存爬取的结果pipelines.py

修改pipelines.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 import codecs

9 import time

10

11 class TodaymoviePipeline(object):

12 def process_item(self, item, spider):

13 today = time.strftime('%Y-%m-%d', time.localtime)

14 fileName = '武汉汉街万达广场店' + today + '.txt'

15 with codecs.open(fileName, 'a+', 'utf-8') as fp:

16 fp.write('%s %s %s %s rn'

17 %(item['movieTitleCn'],

18 item['movieTitleEn'],

19 item['director'],

20 item['runtime']))

21 # return item

这个脚本没什么可说的,比较简单。就是把当日的年月日抽取出来当成文件名的一部分。然后把wuHanMovieSpider.py中获取项的内容输入到该文件中。这个脚本中只需要注意两点。第一,open创建文件时必须是以追加的形式创建,也就是说open的第二个参数必须是a,也就是文件写入的追加模式append。。因为wuHanMovieSpider.py返回的是一个item列表items,这里的写入文件只能一个一个item地写入。如果open的第二个参数是写入模式write,造成的后果就是先擦除前面写入的内容,再写入新内容,一直循环到items列表结束,最终的结果就是文件里只保存了最后一个item的内容。第二是保存文件中的内容如果含有汉字就必须转换成utf8码。汉字的unicode码保存到文件中正常人类都是无法识别的,所以还是转换成正常人类能识别的utf8吧。

到了这一步,这个Scrapy爬虫基本上完成了。回到scrapy.cfg文件的同级目录下(实际上只要是在todayMovie项目下的任意目录中执行都行,之所以在这一级目录执行纯粹是为了美观而已),执行命令:

scrapy crawl wuHanMovieSpider

结果却什么都没有?为什么呢?

(4)分派任务的settings.py

先看看settings.py的初始。它仅指定了Spider的位置。再看看写好的Spider的开头,它导入了items.py作为模块,也就是说现在Scrapy已经知道了爬取哪些项目,怎样爬取内容,而pipelines说明了最终的爬取结果怎样处理。唯一不知道的就是由谁来处理这个爬行结果,这时候就该setting.py出点力气了。setting.py的最终如下:

1 # -*- coding: utf-8 -*-

2

3 # Scrapy settings for todayMovie project

4 #

5 # For simplicity, this file contains only the most important settingsby

6 # default. All the other settings are documented here:

7 #

8 # http://doc.scrapy.org/en/latest/topics/settings.html

9 #

10

11 BOT_NAME = 'todayMovie'

12

13 SPIDER_MODULES = ['todayMovie.spiders']

14 NEWSPIDER_MODULE = 'todayMovie.spiders'

15

16 # Crawl responsibly by identifying yourself (and your website) on theuser-a gent

17 #USER_AGENT = 'todayMovie (+http://www.yourdomain.com)'

18

19 ### user define

20 ITEM_PIPELINES = {'todayMovie.pipelines.TodaymoviePipeline':300}

这跟初始的settings.py相比,就是在最后添加了一行ITEM_PIPELINES。它告诉Scrapy最终的结果是由todayMovie模块中pipelines模块的TodaymoviePipeline类来处理。ITEM_PIPELINES是一个字典,字典的key用来处理结果的类,字典的value是这个类执行的顺序。这里只有一种处理方式,value填多少都没问题。如果需要多种处理结果的方法,那就要确立顺序了。数字越小的越先被执行。

现在可以测试这个Scrapy爬虫了,还是执行命令:

scrapy crawl wuHanMovieSpider

ls

cat *.txt

执行结果如图7所示。

图7 Scrapy爬虫结果

这个最简单的爬虫就到这里了。从这个项目可以看出,Scrapy爬虫只需要顺着思路照章填空就可以了。如果需要的项比较多,获取内容的网页源比较复杂或者不规范,可能会稍微麻烦点,但处理起来基本上都是大同小异的。与re爬虫相比,越复杂的爬虫就越能体现Scrapy的优势。返回搜狐,查看更多

责任编辑:

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值