【大数据实战项目六】数据实体提取与数据扩充


手动反爬虫,禁止转载: 原博地址 https://blog.csdn.net/lys_828/article/details/121296019(CSDN博主:Be_melting)

 知识梳理不易,请尊重劳动成果,文章仅发布在CSDN网站上,在其他网站看到该博文均属于未经作者授权的恶意爬取信息

经过上面一系列的操作,现在在我们需要进行数据分析中非常重要的一个环节,即实体提取。

  • 在进行深入数据分析前,我们需要把原子数据记录按照属性进行分组和聚合。
  • 原子数据记录就是最小层面的数据,所有高级报表都是基于原子数据进行分析和加工汇聚的产物。
  • 数据集中包含的实体有:飞机、航班和航空公司

7.1 获取飞机具体航班数量并保存到数据库

接下来主要对飞机进行实体提取,获取机尾编号并将数据存到数据库中。新建一个example02.py文件,然后前置准备环境不变,代码如下,获取部分字段。

from SparkReady import start_spark
import time

spark = start_spark('C04S02',12,'18g')
on_time_dataframe = spark.read.parquet('../data/on_time.parquet')
on_time_dataframe.registerTempTable("on_time_performance")
flights = spark.sql("""
select Carrier,FlightDate,FlightNum,Origin,Dest,TailNum from on_time_performance
""")

进行数据展示时,可以直接进行flights.show()或者使将数据转化为rdd,然后进行take()获取指定的数据,两种方式的代码如下。

flights.show(1)
flights2 = on_time_dataframe.rdd.map(
    lambda x:
  {
      'Carrier': x.Carrier,
      'FlightDate': x.FlightDate,
      'FlightNum': x.FlightNum,
      'Origin': x.Origin,
      'Dest': x.Dest,
      'TailNum': x.TailNum
  }
)
print(flights2.first())

通过rdd转化后的数据类型可以进一步进行分组操作,比如可以统计每个飞机的航班数量,代码设计如下。

flights_per_airplane = flights2 \
        .map(lambda  x :(x['TailNum'],[x])) \
        .reduceByKey(lambda  a,b : a+b) \
        .map(lambda   x : {  'TailNum' : x[0],
                            'Flights'  : sorted(x[1],key=lambda   x : (x['FlightNum'],x['FlightDate'],x['Origin'] , x['Dest']))})

print(flights_per_airplane.first())

程序运行结束后,输出内容如下。
在这里插入图片描述

通过观察可以发现Flights键对应的值是列表套字典,使用SQL数据库是没有办法进行处理,此时就体现出NoSQL的优势了,直接可以存储此类型数据,保存的代码如下。

import pymongo_spark
pymongo_spark.activate()
flights_per_airplane.saveToMongoDB('mongodb://localhost:27017/example.flights_per_airplane')

程序运行完毕后,刷新Compass页面,后出现flights_per_airplane表,输出如下。
在这里插入图片描述

7.2 利用Flask进行数据展示

将刚刚处理过后的数据进行展示,在Compass软件上,当我们进行单条记录的查看时候会很卡顿,想要查看到里面具体的信息时候很不方便,因此可以进一步将数据表现在网页上面,创建7.0版本的on_time07.py文件。在最后添加如下内容。

@app.route("/airplane/flights/<tail_number>")
def flights_per_airplane(tail_number):
    flights = client.example.flights_per_airplane.find_one({'TailNum' : tail_number})
    return render_template('flights_per_airplane.html',flights=flights,tail_number=tail_number)

由于指定的是flights_per_airplane.html渲染文件,所以需要设置里面的内容,具体的代码如下。

{% extends "index.html" %}
{% block body2 %}
  <div>
    <p class="lead">机尾编号为 {{tail_number}} 的航班情况</p>
    <table class="table table-condensed table-striped">
      <thead>
        <th>航空公司</th>
        <th>飞行时间</th>
        <th>航班编号</th>
        <th>出发地</th>
        <th>目的地</th>
      </thead>
      <tbody>
        {% for flight in flights['Flights'] %}
        <tr>
          <td>{{flight['Carrier']}}</td>
          <td>{{flight['FlightDate']}}</td>
          <td><a href="/on_time?Carrier={{flight['Carrier']}}&FlightDate={{flight['FlightDate']}}&FlightNum={{flight['FlightNum']}}">{{flight['FlightNum']}}</a></td>
          <td>{{flight['Origin']}}</td>
          <td>{{flight['Dest']}}</td>
        </tr>
        {% endfor %}
      </tbody>
    </table>
  </div>
{% endblock %}

两个文件的代码进行修改,保存后运行,然后再浏览器的网址栏输入:http://127.0.0.1:5000/airplane/flights/N35236,输出的结果如下。
在这里插入图片描述
其中航班编号一列是蓝色的数值,属于添加了超链接,可以鼠标点击,会跳转到具体该航班的信息页面,比如点击第一行航班编号为1034的数据,输出结果如下。
在这里插入图片描述

7.3 数据查找与索引添加

如果直接在Compass软件中进行数据的查找,要查询到一条数据就需要把当前表中的数据全部遍历一遍。
请添加图片描述

考虑到查询的速度,可以添加要查询字段的索引,比如这里查询的是TailNum,就可以设置一下这个字段的索引,然后再次进行查询,搜索结果如下。(查询的速度会大幅度提升)
在这里插入图片描述

7.4 利用爬虫获取补充数据

通过飞机的机尾编号可以查询飞机的详细信息,可以借助美国官方网站Aircraft Registration (faa.gov)进行查询。

具体输入的地方是在页面的中间,如下。

在这里插入图片描述

比如输入N35236然后回车,就会跳转到对应的飞机详细页面。
在这里插入图片描述
通过以上的查询就可以获得一个飞机的详细数据,从而补充数据库。具体实现的思路就先从数据库中获取所有飞机的唯一机尾编号,然后单独保存,接着利用爬虫程序,以此读取文件中的数据,输入到网站中的对应框中,点击Go按钮,跳转到详情页面,从而实现数据的爬取。

(1)第一步,获取所有航班的机尾编号。创建一个新的文件为example03.py,可以连接刚刚保存到Mongo DB中的数据,也可以直接读取原数据,这里采用获取原数据的方式,因为比较简单快捷,具体的代码操作如下。

from util.SparkReady import start_spark
import time

spark = start_spark('C04S03',14,'12g')
on_time_dataframe = spark.read.parquet('../data/on_time.parquet')
on_time_dataframe.registerTempTable("on_time_dataframe")
total_flights_by_month = spark.sql ("""
select count(distinct(TailNum)) from on_time_dataframe 
""")
total_flights_by_month.show(5)

输出结果如下。(注意由于是计算位置唯一值,SQL语句进行count会自动过滤掉空值)
在这里插入图片描述
如果不采用SparkSQL进行数据的操作,而是采用rdd的方式处理,就需要额外的注意空值和空字符串的数据,代码操作及输出结果如下。
在这里插入图片描述

(2)将数据保存到文件。选择保存的是json文件,需要将数据转化为DF数据类型,然后由于是Spark会自动根据使用的处理器数量进行分区,因此为了方便获取文件中的数据,这里指定重新分区合并所有数据到一个文件中,然后以覆盖写的方式进行数据的写入。

records = unique_tail_numbers.map(lambda x : {'TailNum' : x}).toDF()
records.repartition(1).write.mode("overwrite").json("../data/tail_numbers.json")

整个example03.py文件运行后,会在data文件夹下生成目标数据,打开文件后,内容如下。
在这里插入图片描述
(3)爬虫获取相应的数据。这里可以使用商业的爬虫软件,也可以自己通过selenium进行程序设计爬取数据,最终可以获取到对应的飞机信息,数据文件结果如下。
在这里插入图片描述

(4)将爬虫数据于原数据进行组合。创建一个新的文件为example04.py,然后进行数据的合并操作,具体代码如下。

from SparkReady import  start_spark


spark = start_spark('C04S04',12,'12g')
faa_tail_number_inquiry = spark.read.json('../data/faa_tail_number_inquiry.jsonl')
faa_tail_number_inquiry.show()

print(faa_tail_number_inquiry.count())

输出的结果为:3988(由于是爬虫获取的数据,可能网站上确实没有对应结尾编号的信息,也可能程序爬取的过程中出现了问题,所以最终的数据量肯定是低于原表的数据量)

然后再读取原表中的数据,进行左连接(以原表为依据),代码如下。

print ("***"*80)
unique_tail_numbers = spark.read.json('../data/tail_numbers.jsonl')
tail_num_plus_inquiry = unique_tail_numbers.join(
faa_tail_number_inquiry,faa_tail_number_inquiry.TailNum == unique_tail_numbers.TailNum,
    'left_outer'
)
tail_num_plus_inquiry.show(5)
print (tail_num_plus_inquiry.count())

输出的结果如下。(数据的有效匹配率:3988/4898=81.42%)
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

lys_828

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值