python 爬虫实例_Python 爬虫:Scrapy 实例(二)

本篇博客通过Scrapy爬虫实例,演示了如何从网站抓取天气预报信息,并将数据分别保存为txt、json格式,还介绍了如何将数据存储到MySQL数据库。详细讲解了items.py、Spider文件、pipelines.py和settings.py的修改过程,最终成功实现了数据的多形式保存和持久化。
摘要由CSDN通过智能技术生成

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

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

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

3b5dbde60a426ac15b5a73349c797fed.png

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

ID:Computer-network

稍微增加点难度,做个所需项目多一点的爬虫,并将爬虫的结果以多种形式保存起来。我们就从网络天气预报开始。

首先要做的是确定网络天气数据的来源。打开百度,搜索“网络天气预报”,有很多网站可以选择,任意选择一个都可以。在浏览器中打开该网站,并找到所属的城市,将会出现当地一周的天气预报。 在这里,包含的信息有城市日期、星期、天气图标、温度、天气状况以及风向。除了天气图标是以图片的形式显示,其他的几项都是字符串。本文Scrapy爬虫的目标将包含所有的有用信息。至此,items.py文件已经呼之欲出了。

1、创建编辑Scrapy爬虫

首先还是打开Putty,连接到Linux。在工作目录下创建Scrapy项目,并根据提示依照spider基础模版创建一个spider。执行命令:

cd

cd code/scrapy

scrapy startproject weather

cd weather

scrapy genspider wuHanSpider wuhan.tianqi.com

执行结果如图1所示。

22b647e42d3d566d58f01c362532ce4a.png

图1  创建Scrapy项目

项目模版创建完毕,项目文件如图2所示。

44ed2fcb99c2163dc767ffe9f1022e7f.png

图2  基础项目模版

(1)修改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 WeatherItem(scrapy.Item):

12     # define the fields for your item here like:

13     # name = scrapy.Field()

14     cityDate = scrapy.Field() #城市及日期

15     week = scrapy.Field() #星期

16     img = scrapy.Field() #图片

17     temperature = scrapy.Field() #温度

18     weather = scrapy.Field() #天气

19     wind = scrapy.Field() #风力

在items.py文件中,只需要将希望获取的项名称按照文件中示例的格式填入进去即可。唯一需要注意的就是每一行最前面的到底是空格还是Tabstop。这个文件可以说是Scrapy爬虫中最没有技术含量的一个文件了。填空,就是填空而已。

(2)修改Spider文件wuHanSpider.py

第二个修改的文件是spiders/wuHanSpider.py。暂时先不要修改文件,使用scrapy shell命令来测试、获取选择器。执行命令:

scrapy shell https://www.tianqi.com/wuhan/

执行结果如图3所示。

e795db39c85c23b8bd74c96f36786d9e.png

图3  scrapy shell 从上图可看出response的返回代码为200,是正常返回,已成功获取该网页的response。下面开始试验选择器了。打开Chrome浏览器(任意一个浏览器都可以,哪个方便用哪个),在地址栏输入https://www.tianqi.com/wuhan/,按Enter键打开网页。在任意空白处右击,选择“查看网页源代码”。 在框架源代码页,使用Ctrl+f组合键查找关键词“武汉天气预报一周”,虽然有5个结果,但也能很容易就找到所需数据的位置,如图4所示。

3ead7bdb123b764fe49de7bbaac4d485.png

图4  查找所需数据位置 仔细观察了一下,似乎所有的数据都是在
这个标签下的,试下查找页面还有没有其他的
的标签(这种可能性已经很小了)。如果没有就将
作为XPath的锚点,如图5所示。

f3a4ab3e2dd115cbe9de5cb4e1cbd3ca.png

图5  测试锚点 从页面上来看,每天的数据并不是存在一起的。而是用类似表格的方式,按照列的方式来存储的。不过没关系,可以先将数据抓取出来再处理。先以锚点为参照点,将日期和星期抓取出来。回到Putty下的scrapy shell中,执行命令:

selector=response.xpath('//div[@]')

selector1=selector.xpath('ul[@]/li')

selector1

执行结果如图6所示。

01c6aca8ddd2dcd05ea09075b7b69268.png

图6  确定XPath锚点

然后从selector1中提取有效数据,如图7所示。

5908bff58b13d299c3739473a52ae083.png

图7  XPath选择器获取数据 图7已经将日期、星期和图片挑选出来了,其他所需的数据可以按照相同的方法一一挑选出来。过滤数据的方法既然已经有了,Scrapy项目中的爬虫文件wuHanSpider.py也基本明朗了。wuHanSpider.py的代码如下:

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

2   import scrapy

3   from weather.items import WeatherItem

4

5

6   class WuhanspiderSpider(scrapy.Spider):

7     name = 'wuHanSpider'

8     allowed_domains = ['tianqi.com']

9     citys = ['wuhan', 'shanghai']

10     start_urls = []

11     for city in citys:

12         start_urls.append('https://www.tianqi.com/' + city)

13

14     def parse(self, response):

15         items= []

16         city = response.xpath('//dd[@]/h2/text()').extract()

17         Selector = response.xpath('//div[@]')

18         date = Selector.xpath('ul[@]/li/b/text()').extract()

19         week = Selector.xpath('ul[@]/li/span/text()').extract()

20         wind = Selector.xpath('ul[@]/li/text()').extract()

21         weather = Selector.xpath('ul[@]/li/text()').extract()

22         temperature1 =Selector.xpath('div[@]/ul/li/span/text()').extract()

23         temperature2 =Selector.xpath('div[@]/ul/li/b/text()').extract()

24         for i in range(7):

25             item = WeatherItem()

26             try:

27                 item['cityDate'] = city[0] + date[i]

28                 item['week'] = week[i]

29                 item['wind'] = wind[i]

30                 item['temperature'] = temperature1[i] + ',' + temperature2[i]

31                 item['weather'] = weather[i]

32             except IndexError as e:

33                 sys.exit(-1)

34             items.append(item)

35         return items

文件开头别忘了导入scrapy模块和items模块。在第8~11行中,给start_urls列表添加了上海天气的网页。如果还想添加其他的城市天气,可以在第9行的citys列表中添加城市代码。

(3)修改pipelines.py,处理Spider的结果

这里还是将Spider的结果保存为txt格式,以便于阅读。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: https://doc.scrapy.org/en/latest/topics/item-pipeline.html

7

8   import time

9   import codecs

10

11  class WeatherPipeline(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 \t %s \t %s \t %s \t %s \r\n"

17                     %(item['cityDate'],

18                         item['week'],

19                         item['temperature'],

20                         item['weather'],

21                         item['wind']))

22         return item

第1行,确认字符编码。实际上这一行没多大必要,在Python 3中默认的字符编码就是utf-8。第8~9行,导入所需的模块。第13行,用time模块确定了当天的年月日,并将其作为文件名。后面则是一个很简单的文件写入。

(4)修改settings.py,决定由哪个文件来处理获取的数据

Python 3版本的settings.py比Python 2版本的要复杂很多。这是因为Python 3版本的settings.py已经将所有的设置项都写进去了,暂时用不上的都当成了注释。所以这里只需要找到ITEM_PIPELINES这一行,将前面的注释去掉就可以了。Settings.py这个文件比较大,这里只列出了有效的设置。settings.sp文件内容如下:

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

2

3   # Scrapy settings for weather 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 = 'weather'

12

13  SPIDER_MODULES = ['weather.spiders']

14  NEWSPIDER_MODULE = 'weather.spiders'

15

16  # Crawl responsibly by identifying yourself (and your website) on the User-Agent

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

18

19  #### user add

20  ITEM_PIPELINES = {

21  'weather.pipelines.WeatherPipeline':300,

22  }

最后,回到weather项目下,执行命令:

scrapy crawl wuHanSpider

ls

more *.txt

得到的结果如图8所示。

ec87ded1195d604d521e6793d4aa6690.png

图8  保存结果为txt 至此,一个完整的Scrapy爬虫已经完成了。这个爬取天气的爬虫稍微复杂一点,但流程基本是做填空题。

2、数据存储到json

前面完成了一个Scrapy爬虫,并将其爬取的结果保存到了txt文件。但txt文件的优点仅仅是方便阅读,而程序阅读一般都是使用更方便的json、cvs等等格式。有时程序员更加希望将爬取的结果保存到数据库中便于分析统计。下面继续讲解Scrapy爬虫的保存方式,也就是继续对pipelines.py动手术。 这里以json格式为例,其他的格式都大同小异,您可自行摸索测试。既然是保存为json格式,当然就少不了Python的json模块了。幸运的是json模块是Python的标准模块,无须安装可直接使用。 保存爬取结果,那必定涉及了pipelines.py。我们可以直接修改这个文件,然后再修改一下settings.py中的ITEM_PIPELINES项即可。但是仔细看看settings.py中的ITEM_PIPELINES项,它是一个字典。字典是可以添加元素的。因此完全可以自行构造一个Python文件,然后把这个文件添加到ITEM_PIPELINES不就可以了吗?这个思路是否可行,测试一下就知道了。 为了“表明身份”,给这个新创建的Python文件取名为pipelines2json.py,这个名字简单明了,而且显示了与pipellines.py的关系。pipelines2.json的文件内容如下:

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: https://doc.scrapy.org/en/latest/topics/item-pipeline.html

7

8   import time

9   import codecs

10 import json

11

12  class WeatherPipeline(object):

13     def process_item(self, item, spider):

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

15         fileName = today + '.json'

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

17             jsonStr = json.dumps(dict(item))

18             fp.write("%s \r\n" %jsonStr)

19         return item

然后修改settings.py文件,将pipelines2json加入到ITEM_PIPELINES中去。修改后的settings.py文件内容如下:

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

2

3   # Scrapy settings for weather 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 = 'weather'

12

13 SPIDER_MODULES = ['weather.spiders']

14 NEWSPIDER_MODULE = 'weather.spiders'

15

16 # Crawl responsibly by identifying yourself (and your website) on the User-Agent

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

18

19

20 ITEM_PIPELINES = {

21 'weather.pipelines.WeatherPipeline':300,

22 'weather.pipelines2json.WeatherPipeline':301

23 }

测试一下效果。回到weather项目下执行命令:

scrapy crawl wuHanSpider

ls

cat *.json

得到的结果如图9所示。

fa9eb2921721f9246e349d131c7451cd.png

图9  保存结果为json 从图9来看试验成功了。按照这个思路,如果要将结果保存成csv等格式,settings.py应该怎么修改就很明显了。

3、数据存储到MySQL

数据库 有很多,MySQL、Sqlite3、Access、Postgresql等等,可选择的范围很广。这里选择的标准是,Python支持良好、能够跨平台、使用方便,其中Python标准库默认支持Sqlite3。但谁让Sqllit3声名不显呢,Access不能跨平台。所以这里选择名气最大,Python支持也不错的MySQL。MySQL使用人数众多,资料随处可见,出现问题咨询也挺方便。就是它了。

在Linux上安装MySQL很方便。首先连接Putty后,使用root用户权限,执行命令:

apt-get install mysql-server mysql-client

在安装过程中,会要求输入MySQL用户root的密码(此root非彼root,一个是系统用户root,一个是MySQL的用户root)。这里设置MySql的root用户密码为debian8。 MySQL 安装完毕后,默认是自动启动的。首先连接到MySQL上,查看MySQL的字符编码。执行命令:

mysql -u root -p

SHOW VARIABLES LIKE "character%";

执行结果如图10所示。

f625a645dd1b8ae1e4b7d08616629802.png

图10  MySQL默认字符编码 其中,character_set_database和character_set_server设置的是latin1编码,刚才用Scrapy采集的数据都是utf8编码。如果直接将数据加入数据库,必定会在编程处理中出现乱码问题,所以要稍微修改一下。网上流传着很多彻底修改MySQL默认字符编码的帖子,但由于版本的问题,不能通用。所以只能采取笨方法,不修改MySQL的环境变量,只在创建数据库和表的时候指定字符编码。创建数据库和表格,在MySQL环境下执行命令:

CREATE DATABASE scrapyDB CHARACTER SET 'utf8' COLLATE 'utf8_general_Ci';

USE scrapyDB;

CREATE TABLE weather(

id INT AUTO_INCREMENT,

cityDate char(24),week char(6),

img char(20),

temperature char(12),

weather char(20),

wind char(20),

PRIMARY KEY(id))ENGINE=InnoDB DEFAULT CHARSET=utf8;

执行结果如图11所示。

fec27f0c9a3beb1d351a95027417de86.png

图11  创建数据库 其中,第一条命令创建了一个默认字符编码为utf8、名字为scrapyDB的数据库,第二条命令进入数据库,第三条命令创建了一个默认字符编码为utf8、名字为weather的表格。查看这个表格的结构,如图12所示。

243aabc5e969730b5add2b26e9c6e24c.png

图12  查询表结构 由图12可以看出表格中的项基本与wuHanSpider爬取的项相同。至于多出来的那一项id,是作为主键存在的。MySQL的主键是不可重复的,而wuHanSpider爬取的项中没有符合这个条件的,所以还需要另外提供一个主键给表格更加合适。 创建完数据库和表格,下一步创建一个普通用户,并给普通用户管理数据库的权限。在MySQL环境下,执行命令:

INSERT INTO mysql.user(Host,User,Password)

VALUES("%","crawlUSER",password("crawl123")); 

INSERT INTO mysql.user(Host,User,Password)

VALUES("localhost","crawlUSER",password("crawl123"));

GRANT all privileges ON scrapyDB.* to crawlUSER@all IDENTIFIED BY

'crawl123';

GRANT all privileges ON scrapyDB.* to crawlUSER@localhost IDENTIFIED BY

'crawl123';

执行结果如图13所示。

e745adc09869b35c1811a66669b61107.png

图13  创建新用户、赋予管理权限 第1条命令创建了一个用户名为crawlUSER的远程用户,该用户只能远程登录,不能本地登录。第2条命令创建了一个用户名为crawlUSER的本地用户,该用户只能本地登录,不能远程登录。第3~4条命令则赋予了crawlUSER用户管理scrapyDB数据库的所有权限。最后退出MySQL。至此,数据库方面的配置已经完成,静待Scrapy来连接了。 Python 的标准库中没有直接支持MySQL的模块。在Python第三方库中能连接MySQL的不少,这里选择使用最广的PyMySQL3模块。

(1)Linux中安装PyMySQL3模块

在Python 2的年代,连接MySQL的首选是MySQLdb模块。到了Python 3横行,MySQLdb模块终于被淘汰了,好在有功能完全一致的模块替代了它:PyMySQL3模块。 在Linux下安装PyMySQL3模块,最简单的方法是借助Debian庞大的软件库(可以说,只要不是私有软件,Debian软件库总不会让人失望)。在终端下执行命令:

python3 -m pip install pymysql3

执行结果如图14所示。

3ee86de881d981d38c2f09f60e13f45a.png

图14  Linux安装PyMySQL3模块

安装这个模块必须是root用户权限。

(2)Windows中安装PyMySQL3模块

这个模块在Windows下安装时也必须是管理员权限,所以首先得用管理员权限打开终端,如图15所示。

481b1cd31a7f84e5f1cc9ef0822f89b9.png

图15  使用管理员权限

在Windows中安装PyMySQL3最简单的方法还是pip,如果不觉得麻烦也可以下载源码安装,执行命令:

pip install pymysql3

执行结果如图16所示。

a2bbf380bed4c8ccd7002b762aeb7f84.png

图16  Windows安装PyMySQL3模块 Python 模块已经准备完毕,MySQL的库表格也准备完毕,现在可以编辑pipelines2mysql.py了。在项目名为weather的Scrapy项目中的pipelines.py同层目录下,使用文本编辑器编写pipelines2mysql.py,编辑完毕的pipeliens2mysql.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: https://doc.scrapy.org/en/latest/topics/item-pipeline.html

7

8  import pymysql

9

10 class WeatherPipeline(object):

11     def process_item(self, item, spider):

12         cityDate = item['cityDate']

13         week = item['week']

14         temperature = item['temperature']

15         weather = item['weather']

16         wind = item['wind']

17

18         conn = pymysql.connect(

19                 host = 'localhost',

20                 port = 3306,

21                 user = 'crawlUSER',

22                 passwd = 'crawl123',

23                 db = 'scrapyDB',

24                 charset = 'utf8')

25         cur = conn.cursor()

26         mysqlCmd = "INSERT INTO weather(cityDate, week, temperature,weather,wind) VALUES('%s','%s','%s','%s','%s');"%(cityDate,week,temperature,weather,wind)

27         cur.execute(mysqlCmd)

28         cur.close()

29         conn.commit()

30         conn.close()

31

32         return item

第1行指定了爬取数据的字符编码,第8行导入了所需的模块。第25~30行使用PyMySQL模块将数据写入了MySQL 数据库 中。最后在settings.py中将pipelines2mysql.py加入到数据处理数列中去。修改后的settings.py内容如下:

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

2

3  # Scrapy settings for weather 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 = 'weather'

12

13 SPIDER_MODULES = ['weather.spiders']

14 NEWSPIDER_MODULE = 'weather.spiders'

15

16 # Crawl responsibly by identifying yourself (and your website) on the User-Agent

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

18

19 #### user add

20 ITEM_PIPELINES = {

21 'weather.pipelines.WeatherPipeline':300,

22 'weather.pipelines2json.WeatherPipeline':301,

23 'weather.pipelines2mysql.WeatherPipeline':302

24 }

实际上就是把pipelines2mysql加入到settings.py的ITEM_PIPELINES项的字典中去就可以了。

最后运行scrapy爬虫,查看MySQL中的结果,执行命令:

scrapy crawl wuHanSpider

mysql -u crawlUSER -p

use scrapyDB;

select * from westher;

执行结果如图17所示。

dfac32b81a4037d611f2554184af8869.png

图17  MySQL中数据

MySQL中显示PyMySQL3模块存储数据有效。这个Scrapy项目到此就顺利完成了。

一般来说为了阅读方便,结果保存为txt就可以了。 如果爬取的数据不多,需要存入表格备查,那可以保存为cvs或json比较方便。 如果需要爬取的数据非常大,那还是老老实实考虑用MySQL吧。 专业的软件做专业的事情。

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

ID:Computer-network

【推荐书籍】
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值