用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阿!
















  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值