获取特定城市的历史天气数据,并保存为csv文件方便处理。(2345天气网)
寻找需要的数据在哪:
发现网页有历史天气一栏,直接点击之后发现可以进行爬取,可以采用selenium自动化测试框架进行爬取,也可以找到network里面的数据。本次采用寻找json数据的方法。
找到Fetch/XHR一栏,发现有一个前缀是GetHistory的,点击preview就是他的数据,点击headers就可以得到数据交互的url。
其中几个是可以替换的,分别是id还有年份还有月份,替换之后就可以得到想要的数据。
url = f'https://tianqi.2345.com/Pc/GetHistory' \
f'?areaInfo%5BareaId%5D={city_dict[city]}' \
f'&areaInfo%5BareaType%5D=2&date%5Byear%5D={year}' \
f'&date%5Bmonth%5D={month}'
#分别查找得到id和城市的对应关系
city_dict = {'北京': , '上海': , '广州': , '深圳': }
爬取到的数据处理成json再解析,这里可以直接使用resopnse.json处理,之后的爬取还有别的处理过程。
#发送请求
response = requests.get(url=url,headers=headers)
#获取json数据
json_data = response.json()
#得到data
html_data = json_data['data']
之后可以用bs4进行数据解析,这种定位循环的用bs4更方便,而且可以避免渲染前后xpath路径不一致的问题
page = BeautifulSoup(html_data, "html.parser")
table = page.find("table", attrs={"class": "history-table"})
trs = table.find_all("tr")
for it in trs[1:]:
td = it.find_all('td')
e1 = td[0].text # 日期
同样我也采取了xpath进行解析:
tree=etree.HTML(html_data)
tr_list=tree.xpath('//table[@class="history-table"]/tr')
for tr in tr_list[1:]:
# td_list=tr.xpath('./td')
#xpath的索引是从下往上
d1 = tr.xpath('./td[1]/text()') # 日期
d2 = tr.xpath('./td[2]/text()') # 最高温
d3 = tr.xpath('./td[3]/text()') # 最低温
d4 = tr.xpath('./td[4]/text()') # 天气
d5 = tr.xpath('./td[5]/text()') # 风力风向
d6 = tr.xpath('./td[6]//text()') # 空气质量指数
lst = [city, d1[0], d2[0], d3[0], d4[0], d5[0], d6[0]]
得到的每行数据进行写入:
with open(r'.\北上广深历史天气.csv', mode='w+', newline='', encoding='utf-8') as f:
csv_writer = csv.writer(f)
#写入表格的索引
csv_writer.writerow(['城市', '日期', '最高温', '最低温', '天气', '风力风向', '空气质量指数'])
#没得到一行进行一次写入
csv_writer.writerow(lst)
1对于需要频繁操作的数据,可以使用selenium也可以分析他的传输的包,找到他的json数据是怎么传输的,然后构造url。
2对于数据量比较大的,不用构造dataframe浪费算力,直接得到一行数据,就进行写入。
3如果代码需要再优化的话,可以完善一个能够交互的系统,输入自己想要的城市还有时间,得到数据之后能够进行可视化展示。