亚洲免费在线-亚洲免费在线播放-亚洲免费在线观看-亚洲免费在线观看视频-亚洲免费在线看-亚洲免费在线视频

用Python和Pandas以及爬蟲技術統計歷史天氣

系統 1932 0

這里寫自定義目錄標題

    • 背景
    • 爬取數據
    • 用Pandas顯示數據
      • 太多雨天
      • 多個月的數據
      • 畫圖
    • 功能擴展
    • 遇到的坑

背景

最近在計劃明年從北京rebase到深圳去,所以最近在看深圳的各個方面。去年在深圳呆過一段時間,印象最深的是,深圳總是突然就下雨,還下好大的雨。對于我這種從小在南方長大但是后面又在北京呆了2年多的人來說,熟悉而又無奈。

今天早上本來想隨便瀏覽瀏覽一個天氣網站,看看深圳的歷史天氣如何的,但是,一不小心發現,這家網站竟然直接能用API來抓數據,這~~~還不抓一波,省的自己一個月一個月地看。

先上最后的效果圖:

用Python和Pandas以及爬蟲技術統計歷史天氣_第1張圖片

所有的code都在我的GitHub上:boydfd

下面從幾個方面講一講我是怎么做的:

  1. 爬取數據
  2. 用pandas顯示數據
  3. 功能擴展
  4. 遇到的坑

爬取數據

先是在http://tianqi.2345.com上面瀏覽了一下深圳的6月份天氣。然后發現點切換月份的時候,網址沒有變,那應該有請求API吧,看看這個API長啥樣吧。
用Python和Pandas以及爬蟲技術統計歷史天氣_第2張圖片

用Python和Pandas以及爬蟲技術統計歷史天氣_第3張圖片

發現返回值就是純JS代碼,那就解析一下吧:

  1. 去掉 var = 和最后的 ; 。
  2. 用到 demjson 解析成Python的 List[Dict] 對象。
  3. 轉成pandas的 DataFrame
  4. 加上我們的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

            
          

結果是這樣的:

用Python和Pandas以及爬蟲技術統計歷史天氣_第4張圖片

用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
              
                ]
              
              
                )
              
            
          

用Python和Pandas以及爬蟲技術統計歷史天氣_第5張圖片

功能擴展

現在只能收集到一個月的數據,想收集多個月的數據,還都自己去頁面上找城市代表的code是啥,太低效了。

這個網站這么容易爬,那就再試試能不能找到調用code的API。

啊哦,一不小心找到了所有的code,哈哈哈。

用Python和Pandas以及爬蟲技術統計歷史天氣_第6張圖片

那就在JS里面提取一下。

  1. 先把所有的JS代碼都復制到瀏覽器的console里, 結果長這樣:

  1. 將其轉換成字符串。
            
              provqx
              
                .
              
              
                flatMap
              
              
                (
              
              a 
              
                =>
              
               a
              
                )
              
              
                .
              
              
                join
              
              
                (
              
              
                '|'
              
              
                )
              
            
          
  1. 在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元等您想捐的金額吧,狠狠點擊下面給點支持吧,站長非常感激您!手機微信長按不能支付解決辦法:請將微信支付二維碼保存到相冊,切換到微信,然后點擊微信右上角掃一掃功能,選擇支付二維碼完成支付。

【本文對您有幫助就好】

您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描上面二維碼支持博主2元、5元、10元、自定義金額等您想捐的金額吧,站長會非常 感謝您的哦?。。?/p>

發表我的評論
最新評論 總共0條評論
主站蜘蛛池模板: 久久99这里精品8国产 | 国产一级毛片国语普通话对白 | 久久乱码精品区中文字幕 | 亚洲不卡免费视频 | 欧美激情在线免费观看 | 国产高清美女一级毛片久久 | 一及 片日本 | 国产va免费精品 | 日日天干夜夜人人添 | 久久国产精品国产精品 | 国产日韩亚洲 | 精品国产一区二区三区成人 | 99精品国产综合久久久久 | 久久99精品久久久久久黑人 | 甜心女孩泰剧在线观看 | 97久久精品国产精品青草 | 亚洲日本视频在线观看 | 亚洲光棍天堂 | 69日本xxxxxxxx59 | 欧美色视频网 | 日本中文字幕在线看 | 99资源在线观看 | 中文字幕久久久久久精 | 成人性色生活片免费看爆迷你毛片 | 又粗又大的机巴好爽7 | 亚洲欧美日韩一区成人 | 欧美一级特黄一片免费 | 77yyzz男人的天堂 | 成人香蕉视频 | 九九九| 日韩欧美三区 | 99久久综合久中文字幕 | 五月婷婷激情视频 | 曰本一区二区 | 农村寡妇一级毛片免费看视频 | 99尹人香蕉国产免费天天拍 | 97国产成人精品免费视频 | 久久精品二区 | 日本特级黄毛片毛片视频 | 全黄毛片 | 男女啪网站 |