這里寫自定義目錄標題
- 背景
- 爬取數據
- 用Pandas顯示數據
- 太多雨天
- 多個月的數據
- 畫圖
- 功能擴展
- 遇到的坑
背景
最近在計劃明年從北京rebase到深圳去,所以最近在看深圳的各個方面。去年在深圳呆過一段時間,印象最深的是,深圳總是突然就下雨,還下好大的雨。對于我這種從小在南方長大但是后面又在北京呆了2年多的人來說,熟悉而又無奈。
今天早上本來想隨便瀏覽瀏覽一個天氣網站,看看深圳的歷史天氣如何的,但是,一不小心發現,這家網站竟然直接能用API來抓數據,這~~~還不抓一波,省的自己一個月一個月地看。
先上最后的效果圖:
所有的code都在我的GitHub上:boydfd
下面從幾個方面講一講我是怎么做的:
- 爬取數據
- 用pandas顯示數據
- 功能擴展
- 遇到的坑
爬取數據
先是在http://tianqi.2345.com上面瀏覽了一下深圳的6月份天氣。然后發現點切換月份的時候,網址沒有變,那應該有請求API吧,看看這個API長啥樣吧。
發現返回值就是純JS代碼,那就解析一下吧:
-
去掉
var =
和最后的;
。 -
用到
demjson
解析成Python的List[Dict]
對象。 -
轉成pandas的
DataFrame
- 加上我們的date字段
date
=
'201905'
weather
=
requests
.
get
(
'http://tianqi.2345.com/t/wea_history/js/{date}/59493_{date}.js'
.
format
(
date
=
date
)
)
.
text
.
split
(
'='
)
[
1
]
[
:
-
1
]
weather
=
demjson
.
decode
(
weather
)
[
'tqInfo'
]
df
=
pd
.
DataFrame
(
weather
)
df
[
'month'
]
=
date
結果是這樣的:
用Pandas顯示數據
太多雨天
我們可以看到,有各種雷陣雨啊,陰轉雨啊,雨轉陰之類的,這樣看到的天氣太雜了,所以我就統一了一下,按照雨、多云、陰、晴的順序來排序,先出出現的關鍵詞優先級更高。
寫一個函數來處理之:
rain
=
'雨'
rain_index
=
' '
+
rain
cloudy
=
'多云'
cloudy_index
=
' '
+
cloudy
overcast
=
'陰'
overcast_index
=
' '
+
overcast
sunny
=
'晴'
sunny_index
=
' '
+
sunny
def
weath_category
(
row
)
:
tianqi
=
row
[
'tianqi'
]
if
tianqi
.
find
(
rain
)
!=
-
1
:
return
rain_index
if
tianqi
.
find
(
overcast
)
!=
-
1
:
return
overcast_index
if
tianqi
.
find
(
cloudy
)
!=
-
1
:
return
cloudy_index
return
sunny_index
多個月的數據
一個月的數據不夠啊,我們想要很多個月的數據,那就寫得函數來生成月份吧。
def
date_generate
(
start
,
end
)
:
start
=
datetime
.
strptime
(
start
,
'%Y%m'
)
end
=
datetime
.
strptime
(
end
,
'%Y%m'
)
while
True
:
next_start
=
start
+
relativedelta
(
months
=
1
)
yield
start
.
strftime
(
'%Y%m'
)
if
next_start
>
end
:
break
start
=
next_start
畫圖
分好類,爬了多個月份的數據,就剩最終的畫圖部分了。使用Pandas提供給我們的函數,可以很容易就畫出圖來。
def
plot_weather
(
start
,
end
)
:
df
=
read_weather
(
start
,
end
)
.
dropna
(
)
.
reset_index
(
)
df
[
'weather'
]
=
df
.
apply
(
weath_category
,
axis
=
1
)
from
pylab
import
rcParams
rcParams
[
'figure.figsize'
]
=
40
,
10
weather_df
=
df
.
groupby
(
[
'month'
,
'weather'
]
)
.
aqi
.
count
(
)
.
unstack
(
)
.
reset_index
(
)
weather_df
.
plot
.
bar
(
x
=
'month'
,
y
=
[
rain_index
,
overcast_index
,
cloudy_index
,
sunny_index
]
)
功能擴展
現在只能收集到一個月的數據,想收集多個月的數據,還都自己去頁面上找城市代表的code是啥,太低效了。
這個網站這么容易爬,那就再試試能不能找到調用code的API。
啊哦,一不小心找到了所有的code,哈哈哈。
那就在JS里面提取一下。
- 先把所有的JS代碼都復制到瀏覽器的console里, 結果長這樣:
- 將其轉換成字符串。
provqx
.
flatMap
(
a
=>
a
)
.
join
(
'|'
)
- 在Python里處理它。
def
line_to_city_code
(
line
)
:
return
line
.
split
(
' '
)
[
1
]
.
split
(
'-'
)
def
get_city_to_code
(
)
:
city_code_list
=
list
(
map
(
line_to_city_code
,
city_code
.
split
(
'|'
)
)
)
return
{
city_code
[
0
]
:
city_code
[
1
]
for
city_code
in
city_code_list
if
len
(
city_code
)
==
2
}
這樣我們就拿到所有的code了,只需要輸入城市,開始時間,結束時間,一張漂亮的圖就出來了,我還寫了個類稍微封裝了一下,只需要這樣就能使用了:
Weather
(
'深圳'
)
.
plot_weather
(
'201701'
,
'201906'
)
遇到的坑
以前在電腦里面處理過一次,就是matplotlib畫圖中文亂碼的事情,這次換了新電腦又碰到了。所以又搞了一次,
大概的步驟可以參考https://www.jianshu.com/p/8ed59ac76c06
我為了以防下次再經歷一次,就寫了個腳本自動處理這件事,目前只支持macOS和Python3。
腳本也在我的GitHub:bash,
直接執行下面的bash腳本就可以解決這個問題:
curl
-o- https://raw.githubusercontent.com/boydfd/one_step_solve/master/matplotlib_chinese.sh
|
bash
更多文章、技術交流、商務合作、聯系博主
微信掃碼或搜索:z360901061

微信掃一掃加我為好友
QQ號聯系: 360901061
您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點擊下面給點支持吧,站長非常感激您!手機微信長按不能支付解決辦法:請將微信支付二維碼保存到相冊,切換到微信,然后點擊微信右上角掃一掃功能,選擇支付二維碼完成支付。
【本文對您有幫助就好】元
