欢迎光临我的Blog,虽然这里还很简陋,但未来一定会焕发生机的!

广州市白云机场到港航班数据爬取——炎泽汐 の Blog

计算机 yanzexi 2年前 (2022-11-27) 501次浏览 已收录 0个评论 扫描二维码
文章目录[隐藏]

网站分析

      广州市白云国际机场的到达航班数据可以在其官网的到达航班中进行查询,具体网址为:https://www.gbiac.net/byairport-web/flight/list?depOrArr=2&type=1&day=0&terminal=ALL。

      通过分析网站页面我们可以锁定我们所需要数据包括计划到达时间和状态这两列,如下图所示:

广州市白云机场到港航班数据爬取——炎泽汐 の Blog

      通过浏览器开发者工具的 Elements 功能进行定位找所需元素时间和状态的位置在类为”column w200 bold”和”column w80″的 li 容器里中。

广州市白云机场到港航班数据爬取——炎泽汐 の Blog

      将网页下拉,发现网站的数据是动态加载的,直接爬取只能得到部分信息,更多的信息需要点击加载更多按钮才可以获取。

广州市白云机场到港航班数据爬取——炎泽汐 の Blog

      于是打开开发者工具的 Notwork 来研究按钮的功能,发现点击按钮后发出一个名为 loadMore 的请求,点击查看其详情。

广州市白云机场到港航班数据爬取——炎泽汐 の Blog

      通过详情可以看到按钮的功能是向地址 https://www.gbiac.net/byairport-web/flight/loadMore 发送一个 Post 请求。

广州市白云机场到港航班数据爬取——炎泽汐 の Blog

      查看返回报文可以看出其结构与原网页相似,无需改动,因此复用前面处理方法即可。

广州市白云机场到港航班数据爬取——炎泽汐 の Blog

      然后,研究 Post 请求的报文结构,关键是 header 头部的组成以及 Data 部分的数据处理。头部信息如下,复用以下信息即可。

广州市白云机场到港航班数据爬取——炎泽汐 の Blog

      Data 部分通过对比原网页和不同 loadMore 请求,可以发现发生改变的位置只有 flightNo 和 dataTime 字段。同样进行对比可以发现 flightNo 和 dataTime 字段实际上为上一也最后一行数据。到处网页分析部分就已经全部完成了,接下来开始编码实现。

广州市白云机场到港航班数据爬取——炎泽汐 の Blog

数据爬取

      我使用 python 进行编程编程,代码具体如下:

1)导包:

import csv
import time
import requests
from bs4 import BeautifulSoup

2)构建函数用于判断航班号以及航班状态的合法性:

def IsChinese(character):
    """
    判断是否为中文
    :param character: 字符串
    :return: 是中文返回 False,否则返回 True
    """
    for cha in character:
        if '\u0e00' <= cha <= '\u9fa5':
            return False
    else:
        return True

def IsState(character):
    """
    判断状态是否合法
    :param character: 字符串
    :return: 是否合法
    """
    if character.find("到达") == 0:
        return True
    elif character.find("计划") == 0:
        return True
    elif character.find("途中") == 0:
        return True
    else:
        return False

3)初始化元素,定义访问的 url 和头部信息:

# 元素初始化
sj = list()
zt = list()
# 存储路径
savedatapath = r'D:\University\大三\数据挖掘\第五次作业\白云机场 10.20 航班数据.csv'
# 初始化爬取的网站和访问头
url = 'https://www.gbiac.net/byairport-web/flight/list?depOrArr=2&type=1&terminal=ALL&day=-1'
url2 = 'https://www.gbiac.net/byairport-web/flight/loadMore'
headers = {
    'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.198 Safari/537.36'}
headers2 = {
    'Accept': 'text/html, */*; q=0.01',
    'Accept-Encoding': 'gzip, deflate, br',
    'Accept-Language': 'zh-CN,zh;q=0.9,ja;q=0.8',
    'Connection': 'keep-alive',
    'Content-Length': '81',
    'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8',
    'Host': 'www.gbiac.net',
    'Origin': 'https://www.gbiac.net',
    'Referer': 'https://www.gbiac.net/',
    'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.198 Safari/537.36',
    'X-Requested-With': 'XMLHttpRequest'
}
# post 请求数据包
data = {
    'depOrArr': '2',
    'type': '1',
    'day': '-1',
    'terminal': 'ALL'
}

4)访问原网页读取信息

# 解析原始网页
res = requests.get(url=url, headers=headers)
res.encoding = 'utf-8'
html = res.text
if len(html) > 100:
    print('解析成功')
else:
    print('解析失败', len(html))

# 元素提取
soup = BeautifulSoup(html, features="html.parser")
company_items = soup.find_all('li', class_='column w200 bold')
for company_item in company_items:
    dd = company_item.text.strip()
    sj.append(dd)
lt = dd
company_items = soup.find_all('li', class_='column w80')
for company_item in company_items:
    dd = company_item.text.strip()
    if IsState(dd):
        zt.append(dd)

5)发送 Post 请求获取后续信息:

# 发起 post 请求
FL = 'MU2542'
for i in range(11):
    print('第' + str(i + 2) + '页数据请求中')
    data['flightNo'] = FL
    data['dataTime'] = '2022-10-19 ' + lt
    res = requests.post(url=url2, data=data, headers=headers2)
    res.encoding = 'utf-8'
    html = res.text
    if len(html) > 100:
        print('第' + str(i + 2) + '页数据获取成功')
    else:
        print('第' + str(i + 2) + '页数据获取失败,结束进程:', len(html))
        break
    soup = BeautifulSoup(html, features="html.parser")
    company_items = soup.find_all('li', class_="column w200 bold")
    company_items2 = soup.find_all('div', class_="item")
    for company_item in company_items:
        dd = company_item.text.strip()
        sj.append(dd)
    lt = dd
    for company_item in company_items2:
        tx = company_item.text.strip()
        if tx.isalnum() & IsChinese(tx):
            FL = tx
    company_items = soup.find_all('li', class_='column w80')
    for company_item in company_items:
        dd = company_item.text.strip()
        if IsState(dd):
            zt.append(dd)
    time.sleep(2)

6)写入数据到 csv 文件中:

# 存储数据
rows = zip(sj, zt)
with open(savedatapath, "w", newline='') as f:
    writer = csv.writer(f)
    for row in rows:
        writer.writerow(row)
喜欢 (6)
[炎泽汐de收款码]
分享 (0)

您必须 登录 才能发表评论!