用python爬取開放數據

作者:王樹義
鏈接:https://www.jianshu.com/p/424e1c65f424
來源:簡書

分別介紹如何把 CSV/XML/JSON這三種常見的網絡開放數據格式讀取到python,形成結構化數據框,方便後續分析操作。

csv: comma separated values  逗號分隔數值

jupyter notebook中:

  • 打開文件

!cat + 文件名
  • 爲了讓圖像在 Jupyter Notebook 上正確顯示,使用以下語句,允許頁內嵌入圖像
%matplotlib inline
pandas 對csv的數據最爲友好,提供了read_csv方法,直接讀取csv數據。
df = pd.read_csv("ZILLOW-M550_SALES.csv")

我們把csv數據存儲到了數據框變量df。下面顯示一下數據讀取效果。


下面我們編制一個函數,幫我們整理數據框。它主要實現以下功能:

  • 把列名變成小寫的“date”和“value”;
  • 按照時間順序,排列數據。把最舊的日期和對應的數值放在第一行,最新的日期和對應的數值置於末尾;
  • 把時間設置爲數據框的索引,這主要是便於後面繪圖的時候,橫軸正確顯示日期數據。
    def arrange_time_dataframe(df):
        df.columns = ['date', 'value']
        df.sort_values(by='date', inplace=True)
        df.set_index('date', inplace=True)
        return df
    
inplace=True 表示的是在原地進行處理:

inplace : bool, default False   if True, perform operation in-place

下面我們調用這個函數,整理數據框變量df。

df = arrange_time_dataframe(df)

我們展示一下df的前5行。

df.head()


你會看到,日期數據變成了索引,而且按照升序排列。

下面我們該繪圖了。數據框工具Pandas給我們提供了非常方便的時間序列圖形繪製功能。

爲了顯示更爲美觀,我們把圖形的長寬比例做了設置。

df.plot(figsize=(16, 6))
可以看見df.plot() 此時plot是一個pandas方法

json: javascript object nonation(JavaScript對象標記)

它和csv一樣,是文本文件

首先我們讀取json工具包。

import json

打開咱們下載的M550_SALES.json文件,讀取數據到變量data。

with open("M550_SALES.json") as f:
    data = json.load(f)
 #data = f.read()
函數邏輯:因爲f代表的是一個 json 格式的文件,
print(f)
<_io.TextIOWrapper name='M550_SALES.json' mode='r' encoding='UTF-8'>


所以用json.load() 一次性的將f轉變爲json顯示的data.直接用f.read()也沒啥子區別吧
但是data很亂,非常亂,所以我們對data進行處理,json格式的處理,當然用json的方法.

爲了看得更爲直觀,咱們把JSON正確縮進後輸出。這裏我們只展示前面的一些行。

print(json.dumps(data, indent=2))

{
  "dataset": {
    "dataset_code": "M550_SALES",
    "column_names": [
      "Date",
      "Value"
    ],
    "newest_available_date": "2016-06-30",
    "description": "The Zillow Home Value Index is Zillow's estimate of the median market value of home sales (nsa) within the metro of Morehead City, NC. This data is calculated by Zillow Real Estate Research (www.zillow.com/research) using their database of 110 million homes.",
    "end_date": "2016-06-30",
    "data": [
      [
        "2016-06-30",
        64.0
      ],
      [
        "2016-05-31",
        163.0
      ],
可以看到,JSON文件就像是一個大字典(dictionary)。我們選擇其中某個索引,就能獲得對應的數據。

我們選擇“dataset”:

data['dataset']

下面是結果的前幾行。

{u'collapse': None,
 u'column_index': None,
 u'column_names': [u'Date', u'Value'],
 u'data': [[u'2016-06-30', 64.0],
  [u'2016-05-31', 163.0],
  [u'2016-04-30', 118.0],

我們關心的數據在“data”下面。繼續來:

data['dataset']['data']

還是隻展示前幾行:

[[u'2016-06-30', 64.0],
 [u'2016-05-31', 163.0],
 [u'2016-04-30', 118.0],

這不就是我們想要讀取的數據嘛

爲了和csv數據做出區分,我們這次將數據讀取後存儲在df1變量。

df1 = pd.DataFrame(data['dataset']['data'])

顯示一下前幾行:

df1.head()

數據都對,可是列名稱怪怪的。

沒關係,我們剛纔不是編制了整理函數嗎?不管多麼奇怪的列名稱,都可以整理好。

df1 = arrange_time_dataframe(df1)

整理之後,咱們再次調用繪圖函數,繪製df1的數據:

df1.plot(figsize=(16, 6))

XML:eXtensible Markup Language--擴展標記語言


它看起來有些像我們上網時每天都要用到的HTML源碼,但是有區別。它的設計初衷,不是爲了展示Web頁面,而是爲了數據交換。
我們在Jupyter Notebook中打開下載的XML文件。

在頁面下方,我們看到了自己感興趣的數據部分,但是數據是用很多標籤來包裹的。

下面我們嘗試使用Python來提取和整理XML數據。

首先,我們讀入網頁分析工具Beautifulsoup。

from bs4 import BeautifulSoup

這是一個非常重要的網頁信息提取工具,是Python爬蟲編寫的基礎技能之一。

下面我們用“lxml”工具分析解析data數據,並且存儲到soup變量裏面。

soup = BeautifulSoup(data, "lxml")

解析之後,我們就可以利用Beautifulsoup的強大搜索功能了。

這裏我們觀察XML文件:

可以看到,我們關心的日期和交易中位數記錄存放在datum標籤下。

其中,日期數據的類型爲“date”,交易價格中位數的類型爲“float”。

我們先來嘗試使用Beautifulsoup的find_all函數,提取所有的日期數據:

我們先來嘗試使用Beautifulsoup的find_all函數,提取所有的日期數據:

dates = soup.find_all('datum', type='date')

我們看看提取結果的前5行:

dates[:5]

[<datum type="date">2016-06-30</datum>,
 <datum type="date">2016-05-31</datum>,
 <datum type="date">2016-04-30</datum>,
 <datum type="date">2016-03-31</datum>,
 <datum type="date">2016-02-29</datum>]

很好,數據正確提取出來。問題是還有標籤數據在前後,此時我們不需要它們。

我們處理一下。對列表每一項,使用Beautifulsoup的text屬性提取內容。

dates = [item.text for item in dates]
注意到 dates 是一個列表,列表的元素就是一個存儲日期的結構,然後使用列表推倒式,重要的是text 這個算是方法吧,與xpath有一點點不同,在後者裏面 要用text()才能得到標籤的內容。

再看看這次的提取結果:

dates[:5]
[u'2016-06-30', u'2016-05-31', u'2016-04-30', u'2016-03-31', u'2016-02-29']
當然,這次的dates 還是一個列表。
我們用同樣的方式處理交易價格中位數記錄:

values= soup.find_all('datum', type='float')

顯示一下結果:

values[:5]
[<datum type="float">64.0</datum>, <datum type="float">163.0</datum>, <datum type="float">118.0</datum>, <datum type="float">110.0</datum>, <datum type="float">83.0</datum>]

這次還是有標籤,需要去掉。

注意這裏我們希望把結果存儲爲浮點數,所以除了用text屬性提取數值以外,還用float()函數做了轉換。

values = [float(item.text) for item in values]

顯示一下前5行:

values[:5]
[64.0, 163.0, 118.0, 110.0, 83.0]

數據被正確轉換成了浮點數。

我們手裏,分別有了日期和交易價格中位數記錄列表。下面我們將其轉換成爲Pandas數據框,並且存儲於df2變量裏。可見,DataFrame()接受的是一個字典

df2 = pd.DataFrame({'dates':dates, 'values':values})

看看df2的前幾行:

df2.head()


數據我們有了,下面也用我們的自編函數整理一下:

df2 = arrange_time_dataframe(df2)

然後我們嘗試對df2繪圖:

df2.plot(figsize=(16, 6))

xml小結:找到函數(with open),封裝文件內容(data = f.read()),將文件內容化成soup(BeautifulSoup(data,‘lxml')),觀察soup,找到需要的數據結構,然後用dates=soup.find_all(datum,type='----'),此時dates是一個列表,而且是一個太胖的列表,我們需要把需要的信息提取出來 dates = [item.text for item in dates],values也是同樣的處理。最後將他們兩個導入pd.DataFrame()中時,記得需要以一個字典的形式,因爲要有columns阿!
















發佈了25 篇原創文章 · 獲贊 8 · 訪問量 1萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章