使用scrapy框架爬取中国各城市天气预报 实验
实验目的:
-
熟练安装 Python 扩展库 scrapy。
-
熟悉常见 HTML 标签的用法。
-
理解网页源代码结构。
-
理解 scrapy 框架工作原理。
实验内容:
安装Python扩展库 scrapy ,然 后 编 写 爬 虫 项 目 ,从网站http://www.weather.com.cn/shandong/index.shtml 爬取山东各城市的天气预报数据,并把爬取到的天气数据写入本地文本 weather.txt。
实验步骤:
- 在命令提示符环境使用
pip install scrapy
命令安装 Python 扩展库 scrapy。 - 在命令提示符环境使用
scrapy startproject sdWeatherSpider
创建爬虫项目 - 进入爬虫项目文件夹,然后执行命令
scrapy genspider everyCityinSD.py www.weather.com.cn
创建爬虫程序。 - 使用浏览器打开网址 http://www.weather.com.cn/shandong/index.shtml
- 找到下面位置
- 在页面上单击鼠标右键,
选择 “查看网页源代码”,按下F12打开开发者模式,然后找到与 “城市预报列表” 对应的位置。
点击选中图中红框位置,然后鼠标移到红色箭头位置。
我们的爬虫需要拿到每个城市的天气入口,这里可以用正则表达式<a title=".*?" href="(.+?)" target="_blank">(.+?)</a>
匹配,后续会实现在代码里。
- 进入上图找到的济南天气
- 老方法,打开F12,选中图中红框位置,然后鼠标移到红色箭头位置,这时候会定位到这个卡片的源代码附近,分析一下。
-
-
分析一下两张图
-
网页中的天气卡片是以
ul
标签包裹着,li
标签存放着接下来七天的天气数据。 -
从左上图可以看到,我们找到了天气数据中的
date,cloud,当日气温,最低/高气温,风速风向
-
记住他们的
Xpath
位置,如,date
也就是14日(今天)
,的Xpath。提取Xpath方式如下↓ -
那么这个date的Xpath为:
//*[@id="7d"]/ul/li[1]/h1
,其他的元素以此类推,详情内容参见Xpath语法。
-
-
修改 items.py 文件,定义要爬取的内容。
import scrapy
class SdweatherspiderItem(scrapy.Item):
# definethefieldsforyouritemherelike:
# name=scrapy.Field()
city=scrapy.Field()
weather=scrapy.Field()
11.修改爬虫文件 everyCityinSD.py,定义如何爬取内容,其中用到的规则参考前面 对页面的分析,如果无法正常运行,有可能是网页结构有变化,可以回到前面的步骤重新 分析网页源代码。
from re import findall
from urllib.request import urlopen
import scrapy
from sdWeatherSpider.items import SdweatherspiderItem
class EverycityinsdSpider(scrapy.Spider):
name = 'everyCityinSD'
allowed_domains = ['www.weather.com.cn']
start_urls = []
# 遍历各城市,获取要爬取的页面
url = r'http://www.weather.com.cn/guangdong/index.shtml'
with urlopen(url) as fp:
contents = fp.read().decode()
pattern = '<a title=".*?" href="(.+?)" target="_blank">(.+?)</a>'
for url in findall(pattern, contents):
start_urls.append(url[0])
def parse(self, response, **kwargs):
# 处理每个城市的天气预报页面数据
item = SdweatherspiderItem()
city = response.xpath('//div[@class="crumbs fl"]//a[3]//text()').extract()[0]
item['city'] = city
# 每个页面只有一个城市的天气数据,直接取[0]
# 存放天气数据
selector = response.xpath('//ul[@class="t clearfix"]')[0]
weather = ''
for li in selector.xpath('./li'):
try:
date = li.xpath('./h1//text()').extract()[0]
cloud = li.xpath('./p[@title]//text()').extract()[0]
high_tmp_list = li.xpath('./p[@class="tem"]//span//text()').extract()
low = li.xpath('./p[@class="tem"]//i//text()').extract()[0]
# 这里不加长度判断会导致找不到每日最高气温的时候抛出IndexError异常。
if high_tmp_list.__len__() != 0:
tmp = high_tmp_list[0] + r'/' + low
else:
tmp = low
wind = li.xpath('./p[@class="win"]//em//span[1]/@title').extract()[0]
wind = wind + li.xpath('./p[@class="win"]//i//text()').extract()[0]
weather = weather + date + ':' + cloud + ',' + tmp + ',' + wind + '\n'
except IndexError as e:
continue
item['weather'] = weather
return [item]
- 修改 pipelines.py 文件,把爬取到的数据写入文件 weather.txt。
class SdweatherspiderPipeline:
def process_item(self, item, spider):
# 每一个段落执行完毕后都会调用此函数,所以文件写入模式为`a`,追加模式
with open('weather.txt', 'a', encoding='utf8') as fp:
fp.write(item['city'] + '\n')
fp.write(item['weather'] + '\n\n')
return item
- 修改 settings.py 文件,分派任务,指定处理数据的程序。
BOT_NAME = 'sdWeatherSpider'
SPIDER_MODULES = ['sdWeatherSpider.spiders']
NEWSPIDER_MODULE = 'sdWeatherSpider.spiders'
ITEM_PIPELINES = { 'sdWeatherSpider.pipelines.SdweatherspiderPipeline':1, }
- 接下来去验证
验证
- scrapy项目根目录
在项目根目录下执行命令scrapy crawl everyCityinSD
命令运行爬虫。

我们去输出文件weather.txt
里看看。vim weather.txt
符合实验要求。
彩蛋
其实我爬取的是广东省每个市区的天气,我在上面的代码里面改了一个地方。你知道怎么改吗?
评论区告诉我~