Python 爬虫:Scrapy 实例(一)

2019 年 8 月 19 日 计算机与网络安全

一次性付费进群,长期免费索取教程,没有付费教程。

教程列表见微信公众号底部菜单

微信群回复公众号:微信群QQ群460500587

微信公众号:计算机与网络安全

ID:Computer-network


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结尾的是同名Python程序编译得到的字节码文件,settings.pyc是settings.py的字节码文件,__init__.pyc是__init__.py的字节码文件。据说用来加快程序的运行速度,可以忽视。至于__init__.py文件,它是个空文件,里面什么都没有。在此处唯一的作用就是将它的上级目录变成了一个模块。也就是说第二层的todayMovie模块下,如果没有__init__.py文件。那么todayMovie就只是一个单纯的文件夹。在任何一个目录下添加一个空的__init__.py文件,就会将该文件夹编程模块化,可以供Python导入使用。


有用的这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 important or

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

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() #电影时长


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


与最初的items.py比较一下,修改后的文件只是按照原文的提示添加了需要爬取的项目,然后将类结尾的pass去掉了。这个类是继承与Scrapy的Iteam类,它没有重载Python类的__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/script[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

在这个python文件中,首先导入了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字符串包含在script标签内,数一下script标签的位置,在脚本中执行语句:


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


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


scrapy shell

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


执行结果如图5所示。

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


selector =

response.xpath('/html/body/script[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字符串转换成了一个Python字典格式。第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 \r\n'

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 settings by

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 the user-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的优势。


微信公众号:计算机与网络安全

ID:Computer-network


【推荐书籍】
登录查看更多
1

相关内容

Scrapy,Python开发的一个快速、高层次的屏幕抓取和web抓取框架,用于抓取web站点并从页面中提取结构化的数据。
【实用书】学习用Python编写代码进行数据分析,103页pdf
专知会员服务
190+阅读 · 2020年6月29日
【实用书】Python爬虫Web抓取数据,第二版,306页pdf
专知会员服务
115+阅读 · 2020年5月10日
【干货书】流畅Python,766页pdf,中英文版
专知会员服务
223+阅读 · 2020年3月22日
【资源】100+本免费数据科学书
专知会员服务
105+阅读 · 2020年3月17日
【干货书】机器学习Python实战教程,366页pdf
专知会员服务
332+阅读 · 2020年3月17日
算法与数据结构Python,369页pdf
专知会员服务
160+阅读 · 2020年3月4日
【书籍推荐】简洁的Python编程(Clean Python),附274页pdf
专知会员服务
173+阅读 · 2020年1月1日
手把手教你用Python做一个哄女友神器,小白可上手
网易智能菌
5+阅读 · 2019年6月15日
抖音爬虫
专知
3+阅读 · 2019年2月11日
Python用法速查网站
Python程序员
17+阅读 · 2018年12月16日
我是一个爬虫
码农翻身
12+阅读 · 2018年6月4日
干货 | Python 爬虫的工具列表大全
机器学习算法与Python学习
10+阅读 · 2018年4月13日
Python 爬虫实践:《战狼2》豆瓣影评分析
数据库开发
5+阅读 · 2018年3月19日
教你用Python来玩跳一跳
七月在线实验室
6+阅读 · 2018年1月2日
Python NLP入门教程
计算机与网络安全
8+阅读 · 2017年11月21日
Python NLP 入门教程
大数据技术
19+阅读 · 2017年10月24日
Python3爬虫之入门和正则表达式
全球人工智能
7+阅读 · 2017年10月9日
A Survey on Deep Learning for Named Entity Recognition
Arxiv
25+阅读 · 2020年3月13日
Arxiv
34+阅读 · 2019年11月7日
Meta-Learning to Cluster
Arxiv
17+阅读 · 2019年10月30日
Embedding Logical Queries on Knowledge Graphs
Arxiv
3+阅读 · 2019年2月19日
Arxiv
8+阅读 · 2018年5月15日
VIP会员
相关VIP内容
【实用书】学习用Python编写代码进行数据分析,103页pdf
专知会员服务
190+阅读 · 2020年6月29日
【实用书】Python爬虫Web抓取数据,第二版,306页pdf
专知会员服务
115+阅读 · 2020年5月10日
【干货书】流畅Python,766页pdf,中英文版
专知会员服务
223+阅读 · 2020年3月22日
【资源】100+本免费数据科学书
专知会员服务
105+阅读 · 2020年3月17日
【干货书】机器学习Python实战教程,366页pdf
专知会员服务
332+阅读 · 2020年3月17日
算法与数据结构Python,369页pdf
专知会员服务
160+阅读 · 2020年3月4日
【书籍推荐】简洁的Python编程(Clean Python),附274页pdf
专知会员服务
173+阅读 · 2020年1月1日
相关资讯
手把手教你用Python做一个哄女友神器,小白可上手
网易智能菌
5+阅读 · 2019年6月15日
抖音爬虫
专知
3+阅读 · 2019年2月11日
Python用法速查网站
Python程序员
17+阅读 · 2018年12月16日
我是一个爬虫
码农翻身
12+阅读 · 2018年6月4日
干货 | Python 爬虫的工具列表大全
机器学习算法与Python学习
10+阅读 · 2018年4月13日
Python 爬虫实践:《战狼2》豆瓣影评分析
数据库开发
5+阅读 · 2018年3月19日
教你用Python来玩跳一跳
七月在线实验室
6+阅读 · 2018年1月2日
Python NLP入门教程
计算机与网络安全
8+阅读 · 2017年11月21日
Python NLP 入门教程
大数据技术
19+阅读 · 2017年10月24日
Python3爬虫之入门和正则表达式
全球人工智能
7+阅读 · 2017年10月9日
Top
微信扫码咨询专知VIP会员