1. 程式人生 > >Python爬蟲抓取動態資料

Python爬蟲抓取動態資料

一個月前實習導師佈置任務說通過網路爬蟲獲取深圳市氣象局釋出的降雨資料,網頁如下:


心想,爬蟲不太難的,當年跟zjb爬煎蛋網無(mei)聊(zi)圖的時候,多麼清高。由於接受任務後的一個月考試加作業一大堆,導師也不催,自己也不急。

但是,導師等我一個月都得讓我來寫意味著這東西得有多難吧。。。今天開啟一看的確是這樣。網站是基於Ajax寫的,資料動態獲取,所以無法通過下載原始碼然後解析獲得。

從某不良少年寫的抓取淘寶mm的例子中收到啟發,對於這樣的情況,一般可以同構自己搭建瀏覽器實現。phantomJs,CasperJS都是不錯的選擇。

導師的要求是獲取過去一年內深圳每個區每個站點每小時的降雨量,執行該操作需要通過如上圖中的歷史查詢實現,即通過一個時間來查詢,而這個時間存放在一個hidden型別的input標籤裡,當然可以通過js語句將其改為text型別,然後執行send_keys之類的操作。然而,我失敗了。時間可以修改設定,可是結果如下圖。

為此,僅抓取實時資料。選取python的selenium,模擬搭建瀏覽器,模擬人為的點選等操作實現資料生成和獲取。selenium的一大優點就是能獲取網頁渲染後的原始碼,即執行操作後的原始碼。普通的通過 url解析網頁的方式只能獲取給定的資料,不能實現與使用者之間的互動。selenium通過獲取渲染後的網頁原始碼,並通過豐富的查詢工具,個人認為最好用的就是find_element_by_xpath("xxx"),通過該方式查詢到元素後可執行點選、輸入等事件,進而向伺服器發出請求,獲取所需的資料。

# coding=utf-8
from testString import *
from selenium import webdriver
import string
import os
from selenium.webdriver.common.keys import Keys
import time
import sys
default_encoding = 'utf-8'
if sys.getdefaultencoding() != default_encoding:
    reload(sys)
    sys.setdefaultencoding(default_encoding)


district_navs = ['nav2','nav1','nav3','nav4','nav5','nav6','nav7','nav8','nav9','nav10']
district_names = ['福田區','羅湖區','南山區','鹽田區','寶安區','龍崗區','光明新區','坪山新區','龍華新區','大鵬新區']


flag = 1
while (flag > 0):
    driver = webdriver.Chrome()
    driver.get("http://www.szmb.gov.cn/article/QiXiangJianCe/")
    # 選擇降雨量
    driver.find_element_by_xpath("//span[@id='fenqu_H24R']").click()

    filename = time.strftime("%Y%m%d%H%M", time.localtime(time.time())) + '.txt'
    #建立檔案
    output_file = open(filename, 'w')
    # 選擇行政區
    for i in range(len(district_navs)):
        driver.find_element_by_xpath("//div[@id='" + district_navs[i] + "']").click()
        # print driver.page_source
        timeElem = driver.find_element_by_id("time_shikuang")
        #輸出時間和站點名
        output_file.write(timeElem.text + ',')
        output_file.write(district_names[i] + ',')
        elems = driver.find_elements_by_xpath("//span[@onmouseover='javscript:changeTextOver(this)']")
        #輸出每個站點的資料,格式為:站點名,一小時降雨量,當日累積降雨量
        for elem in elems:
            output_file.write(AMonitorRecord(elem.get_attribute("title")) + ',')
        output_file.write('\n')
    output_file.close()
    driver.close()
    time.sleep(3600)
檔案中引用的檔案testString只是修改輸出格式,提取有效資料。
#Encoding=utf-8
def OnlyCharNum(s, oth=''):
    s2 = s.lower()
    fomart = 'abcdefghijklmnopqrstuvwxyz0123456789,.'
    for c in s2:
        if not c in fomart:
            s = s.replace(c, '')
    return s


def AMonitorRecord(str):
    str = str.split(":")
    return str[0] + "," + OnlyCharNum(str[1])

一小時抓取一次資料,結果如下:


參考網站:http://cuiqingcai.com/2599.html