Python爬蟲 -- 天氣預(yù)報(bào)

這個(gè)天氣預(yù)報(bào)的爬蟲寫的比較簡單旺订,沒有坑很快就完成了,很適合我這種小白则披,而之前寫作業(yè)都是到大半夜才調(diào)試好的呀/(ㄒoㄒ)/~~听皿,這次正好有時(shí)間可以整理下思路。(●'?'●)

這次要爬的站點(diǎn)是這個(gè):http://www.weather.com.cn/forecast/
要求是把你所在城市過去一年的歷史數(shù)據(jù)爬出來静檬。

分析網(wǎng)站

首先來到目標(biāo)數(shù)據(jù)的網(wǎng)頁 http://www.weather.com.cn/weather40d/101280701.shtml

中國天氣網(wǎng)


我們可以看到炭懊,我們需要的天氣數(shù)據(jù)都是放在圖表上的,在切換月份的時(shí)候巴柿,發(fā)現(xiàn)只有部分頁面刷新了凛虽,就是天氣數(shù)據(jù)的那塊,而URL沒有變化广恢。
-_-
這是因?yàn)榫W(wǎng)頁前端使用了JS異步加載的技術(shù)凯旋,更新時(shí)不用加載整個(gè)頁面,從而提升了網(wǎng)頁的加載速度钉迷。
_-
對(duì)于這種非靜態(tài)頁面至非,我們?cè)谡?qǐng)求數(shù)據(jù)時(shí),就不能簡單的通過替換URL來請(qǐng)求不同的頁面糠聪。
著眼點(diǎn)要放在Network荒椭,觀察整個(gè)請(qǐng)求的過程,從中尋找突破口舰蟆。
--
-
老規(guī)矩按下F12 > network趣惠,切換下頁面,發(fā)現(xiàn)多了一些東西身害,這其實(shí)是切換月份后瀏覽器發(fā)出的請(qǐng)求味悄,可以很清楚的看到請(qǐng)求頭和請(qǐng)求參數(shù)。

JS請(qǐng)求

再來看看Response是怎樣的吧

response

真是沒想到塌鸯,返回的居然是json格式的天氣數(shù)據(jù)侍瑟!直接做 json 反序列化就能變成字典的形式,省掉了我們解析 html 的麻煩呀。既然找到了數(shù)據(jù)所在的地方涨颜,就可以開始嘗試構(gòu)建請(qǐng)求了费韭。

構(gòu)建請(qǐng)求

先直接copy上面的Request URL,試下請(qǐng)求庭瑰。http://d1.weather.com.cn/calendar_new/2017/101280701_201706.html?_=1495720234075
然后發(fā)現(xiàn)報(bào)錯(cuò)了星持,先把請(qǐng)求頭全部滿上懟進(jìn)去,發(fā)現(xiàn)可以正常的響應(yīng)弹灭。
但是我們還要分析下到底哪個(gè)參數(shù)不對(duì)出了問題钉汗。經(jīng)過嘗試,發(fā)現(xiàn)請(qǐng)求頭里的Referer的原因鲤屡,去掉就會(huì)報(bào)錯(cuò)。

這是因?yàn)檫@是瀏覽器發(fā)出請(qǐng)求時(shí)福侈,會(huì)通過Referer告訴服務(wù)器我是從哪個(gè)頁面鏈接過來的酒来,有些網(wǎng)站會(huì)對(duì)這個(gè)做驗(yàn)證,主要時(shí)為了防止別人盜鏈的問題肪凛。
這個(gè)中國天氣網(wǎng)堰汉,就是驗(yàn)證了Referer里的域名是不是自己的,不是的話就會(huì)403禁止訪問服務(wù)器伟墙。

接下來就要考慮怎么請(qǐng)求不同月份的數(shù)據(jù)翘鸭。
通過觀察URL,發(fā)現(xiàn)其實(shí)很簡單戳葵,直接替換年月就乓,就可以循環(huán)抓取,得到整年的數(shù)據(jù)拱烁。
那中間的101280701是什么意思呢生蚁,經(jīng)過請(qǐng)求不同的城市對(duì)比URL,我發(fā)現(xiàn)這是表示地理位置的一個(gè)數(shù)據(jù)戏自。
前3位表示國家中國邦投,后6位依次表示,省份擅笔,城市和區(qū)縣志衣。修改這里,就能實(shí)現(xiàn)對(duì)不同城市進(jìn)行查詢了猛们。
最后一個(gè)參數(shù)1495720234075念脯,開始以為是隨機(jī)數(shù),后來有朋友提醒這是unix時(shí)間戳阅懦,實(shí)際上就算去掉這個(gè)和二,也能正常訪問數(shù)據(jù),沒什么影響耳胎。

解析數(shù)據(jù)

拿到數(shù)據(jù)以后惯吕,就可以開始解析了惕它。不過這里根本用不上xpath,直接用Json.load()废登,就能反序列化成json對(duì)象淹魄,從中取出字典,節(jié)省很多麻煩堡距。需要注意的是甲锡,返回的40天的天氣數(shù)據(jù) fc40 字符串是這樣的
var fc40 = [{"blue":"","c1":"","c2":"","cla":"history","date":"20151227","des":"歷史均值","fe":"","hgl":"17%","hmax":"17","hmin":"13","hol":"","jq":"" .....]}
前面的字符串需要去掉,才能反序列化羽戒,注意這里的json對(duì)象實(shí)際是個(gè)存儲(chǔ)字典的list[]缤沦。開始想用正則,不過不熟沒弄好易稠。后來發(fā)現(xiàn) python 字符串也能使用切片 [a:b] 來取出位置a到位置b的字符串缸废,所以就直接用[11 : ], 就能取出fc40 后面的字符串,也很方便驶社。

保存數(shù)據(jù)

因?yàn)閿?shù)據(jù)量比較大企量,就采用mongodb來做數(shù)據(jù)持久化。mongodb 我也是才學(xué)習(xí)亡电,參考了別人的教程届巩,才做好了環(huán)境配置,過程打算總結(jié)到另一篇份乒,這里就打算不多說了恕汇。

因?yàn)樵镜姆帕颂鞖鈹?shù)據(jù)的字典里面有太多沒用的數(shù)據(jù),我只想提取出我想要的部分冒嫡,就用了一個(gè)列表推導(dǎo)拇勃。
將想要的數(shù)據(jù)的key,保存成subkey這個(gè)字典孝凌,用 for in取出subkey中的key方咆,再回到原本的dict中取出對(duì)應(yīng)的值,最后將這些鍵值對(duì)蟀架,都存儲(chǔ)在一個(gè)subdict字典里瓣赂,就完成了提取出子字典的功能。說起來很麻煩片拍,但是代碼卻很簡單煌集,這可能就是python的魅力吧。

subkey = {'date', 'hmax', 'hmin', 'hgl', 'fe', 'wk', 'time'}
subdict = {key: dict[key] for key in subkey} 

然后我還做了個(gè)用中文替換的原來key的功能捌省,只需要稍作修改苫纤,for in 取出來的是鍵值對(duì),然后用中文的value,替換英文的key卷拘,就ok了喊废。

 subkey = {'date': '日期', 'hmax': '最高溫度', 'hmin': '最低溫度', 'hgl': '降水概率', 'fe': '節(jié)日', 'wk': '星期'}
 subdict = {value: dict[key] for key, value in subkey.items()} 

最后的結(jié)果如下圖,這是用pycharm上的mongodb可視化插件Mongo Plugin看到的,在pycharm>settings>plugins里面可以搜索安裝栗弟。需要注意的是污筷,默認(rèn)只顯示300條數(shù)據(jù)。想要看到更多乍赫,就在Row limit 上輸入總數(shù)就行瓣蛀。

天氣數(shù)據(jù).png

Python的代碼非常短才30多行,就完成了爬蟲的整個(gè)流程雷厂, 請(qǐng)求惋增,解析,保存改鲫,一氣呵成器腋,可謂是爬蟲界的豪杰。

# encoding=utf-8
import requests
import json
import pymongo
import time

def request(year, month):
    url = "http://d1.weather.com.cn/calendar_new/" + year + "/101280701_" + year + month + ".html?_=1495685758174"
    headers = {
        "User-Agent": "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/50.0.2661.102 Safari/537.36",
        "Referer": "http://www.weather.com.cn/weather40d/101280701.shtml",
    }
    return requests.get(url, headers=headers)

def parse(res):
    json_str = res.content.decode(encoding='utf-8')[11:]
    return json.loads(json_str)

def save(list):
    subkey = {'date': '日期', 'hmax': '最高溫度', 'hmin': '最低溫度', 'hgl': '濕度', 'fe': '節(jié)日', 'wk': '星期', 'time': '發(fā)布時(shí)間'}
    for dict in list:
        subdict = {value: dict[key] for key, value in subkey.items()}   #提取原字典中部分鍵值對(duì)钩杰,并替換key為中文
        print(subdict)
        forecast.insert_one(subdict)                                    #插入mongodb數(shù)據(jù)庫

if __name__ == '__main__':
    year = "2016"
    month = 1
    client = pymongo.MongoClient('localhost', 27017)   # 連接mongodb,端口27017
    test = client['test']                              # 創(chuàng)建數(shù)據(jù)庫文件test
    forecast = test['forecast']                        # 創(chuàng)建表forecast
    for i in range(month, 13):
        month = str(i) if i > 9 else "0" + str(i)      #小于10的月份要補(bǔ)0
        save(parse(request(year, month)))             
        time.sleep(1)
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市诊县,隨后出現(xiàn)的幾起案子讲弄,更是在濱河造成了極大的恐慌,老刑警劉巖依痊,帶你破解...
    沈念sama閱讀 217,509評(píng)論 6 504
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件避除,死亡現(xiàn)場離奇詭異,居然都是意外死亡胸嘁,警方通過查閱死者的電腦和手機(jī)瓶摆,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,806評(píng)論 3 394
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來性宏,“玉大人群井,你說我怎么就攤上這事『潦ぃ” “怎么了书斜?”我有些...
    開封第一講書人閱讀 163,875評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵,是天一觀的道長酵使。 經(jīng)常有香客問我荐吉,道長,這世上最難降的妖魔是什么口渔? 我笑而不...
    開封第一講書人閱讀 58,441評(píng)論 1 293
  • 正文 為了忘掉前任样屠,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘痪欲。我一直安慰自己悦穿,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,488評(píng)論 6 392
  • 文/花漫 我一把揭開白布勤揩。 她就那樣靜靜地躺著咧党,像睡著了一般。 火紅的嫁衣襯著肌膚如雪陨亡。 梳的紋絲不亂的頭發(fā)上傍衡,一...
    開封第一講書人閱讀 51,365評(píng)論 1 302
  • 那天,我揣著相機(jī)與錄音负蠕,去河邊找鬼蛙埂。 笑死,一個(gè)胖子當(dāng)著我的面吹牛遮糖,可吹牛的內(nèi)容都是我干的绣的。 我是一名探鬼主播,決...
    沈念sama閱讀 40,190評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼欲账,長吁一口氣:“原來是場噩夢(mèng)啊……” “哼屡江!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起赛不,我...
    開封第一講書人閱讀 39,062評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤惩嘉,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后踢故,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體文黎,經(jīng)...
    沈念sama閱讀 45,500評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,706評(píng)論 3 335
  • 正文 我和宋清朗相戀三年殿较,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了耸峭。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,834評(píng)論 1 347
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡淋纲,死狀恐怖劳闹,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情洽瞬,我是刑警寧澤玷或,帶...
    沈念sama閱讀 35,559評(píng)論 5 345
  • 正文 年R本政府宣布,位于F島的核電站片任,受9級(jí)特大地震影響偏友,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜对供,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,167評(píng)論 3 328
  • 文/蒙蒙 一位他、第九天 我趴在偏房一處隱蔽的房頂上張望氛濒。 院中可真熱鬧,春花似錦鹅髓、人聲如沸舞竿。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,779評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽骗奖。三九已至,卻和暖如春醒串,著一層夾襖步出監(jiān)牢的瞬間执桌,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,912評(píng)論 1 269
  • 我被黑心中介騙來泰國打工芜赌, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留仰挣,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 47,958評(píng)論 2 370
  • 正文 我出身青樓缠沈,卻偏偏與公主長得像膘壶,于是被迫代替她去往敵國和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子洲愤,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,779評(píng)論 2 354

推薦閱讀更多精彩內(nèi)容

  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理颓芭,服務(wù)發(fā)現(xiàn),斷路器柬赐,智...
    卡卡羅2017閱讀 134,656評(píng)論 18 139
  • 發(fā)現(xiàn) 關(guān)注 消息 iOS 第三方庫畜伐、插件、知名博客總結(jié) 作者大灰狼的小綿羊哥哥關(guān)注 2017.06.26 09:4...
    肇東周閱讀 12,103評(píng)論 4 62
  • AFHTTPRequestOperationManager 網(wǎng)絡(luò)傳輸協(xié)議UDP躺率、TCP、Http万矾、Socket悼吱、X...
    Carden閱讀 4,337評(píng)論 0 12
  • 像風(fēng)飄過 我用淚送走你 不在乎此生 犯了多少錯(cuò)誤 不愿留下的都可以 獲得自由
    Cactussnow閱讀 248評(píng)論 0 0
  • 生氣,是因?yàn)槟悴粔虼蠖龋?郁悶良狈,是因?yàn)槟悴粔蚧磉_(dá)后添; 焦慮,是因?yàn)槟悴粔驈娜荩?悲傷薪丁,是因?yàn)槟悴粔驁?jiān)強(qiáng)遇西; 惆悵,是因...
    前端老翁閱讀 296評(píng)論 0 0