一次性付费进群,长期免费索取教程,没有付费教程。
教程列表见微信公众号底部菜单
进微信群回复公众号:微信群;QQ群:460500587
微信公众号:计算机与网络安全
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所示。
图1 创建Scrapy项目项目模版创建完毕,项目文件如图2所示。
图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所示。
图3 scrapy shell 从上图可看出response的返回代码为200,是正常返回,已成功获取该网页的response。下面开始试验选择器了。打开Chrome浏览器(任意一个浏览器都可以,哪个方便用哪个),在地址栏输入https://www.tianqi.com/wuhan/,按Enter键打开网页。在任意空白处右击,选择“查看网页源代码”。 在框架源代码页,使用Ctrl+f组合键查找关键词“武汉天气预报一周”,虽然有5个结果,但也能很容易就找到所需数据的位置,如图4所示。 图4 查找所需数据位置 仔细观察了一下,似乎所有的数据都是在selector=response.xpath('//div[@]')
selector1=selector.xpath('ul[@]/li')
selector1
执行结果如图6所示。
图6 确定XPath锚点然后从selector1中提取有效数据,如图7所示。
图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所示。
图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所示。
图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所示。
图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所示。
图11 创建数据库 其中,第一条命令创建了一个默认字符编码为utf8、名字为scrapyDB的数据库,第二条命令进入数据库,第三条命令创建了一个默认字符编码为utf8、名字为weather的表格。查看这个表格的结构,如图12所示。 图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所示。
图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所示。
图14 Linux安装PyMySQL3模块
安装这个模块必须是root用户权限。
(2)Windows中安装PyMySQL3模块
这个模块在Windows下安装时也必须是管理员权限,所以首先得用管理员权限打开终端,如图15所示。图15 使用管理员权限
在Windows中安装PyMySQL3最简单的方法还是pip,如果不觉得麻烦也可以下载源码安装,执行命令:pip install pymysql3
执行结果如图16所示。
图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所示。
图17 MySQL中数据MySQL中显示PyMySQL3模块存储数据有效。这个Scrapy项目到此就顺利完成了。
一般来说为了阅读方便,结果保存为txt就可以了。 如果爬取的数据不多,需要存入表格备查,那可以保存为cvs或json比较方便。 如果需要爬取的数据非常大,那还是老老实实考虑用MySQL吧。 专业的软件做专业的事情。微信公众号:计算机与网络安全
ID:Computer-network
【推荐书籍】