Python程序设计实例 | 爬取机场航班信息

news2024/12/25 0:00:45

案例中将展示机场官网中航班信息(如机场航班的离港与进港信息)的爬取过程。有兴趣的读者可以在本案例的基础上对数据进一步分析,或是对爬虫做进一步的开发,增加更多功能。

请求、解析、处理数据是通用爬虫的三个步骤,在本案例中,利用机场官网的详细信息,在网页上定位各类数据的路径,通过Scrapy爬取得到对应的数据,最后将多个数据统筹整合进一个JSON文件,最终得到机场航班的相关信息。

01、分析网页

打开机场官网(详见前言中的二维码),以进港航班信息为例,存储航班信息的详细页面如图1所示。

■ 图1 机场进港航班数据列表

按F12键打开浏览器的调试模式,可以通过Elements来定位当前页面中数据的存放位置,样例如图2所示。Elements中的元素比较复杂,所以本次爬虫决定使用Scrapy框架直接获取网页的页面内容,通过element的XPath来精准定位需要爬取的数据。

■ 图2 数据存放位置的样例图

02、编写爬虫

该爬虫使用了Scrapy框架,读者需预先安装Python发行版,并在终端中输入pip install scrapy指令来安装Scrapy框架。

Scrapy框架的目录层次如图3所示。

■ 图3  Scrapy框架的目录层次

比较重要的是items.py、settings.py、pipelines.py、middlewares.py以及spiders文件夹中放置的爬虫主程序。在settings.py文件中,可以对框架进行一些设置。例如,是否使用中间件、是否使用管道等。items.py文件是一个对象文件,用于指示本次爬虫爬取对象的结构,以存放爬取到的数据,下面以TrafficItems.py文件为例,来看一看该内容需要如何实现。

【例1】指示爬取对象的结构,将爬取到的数据保存至TrafficItems.py文件。

import scrapy
class TrafficItems(scrapy.Item):
sysmbol = scrapy.Field()   #标识符
model  = scrapy.Field()
leavePlace = scrapy.Field() #始发地
leaveAirport = scrapy.Field() #出发机场
destssination = scrapy.Field() #目的地
destssinationAirport = scrapy.Field() #到达机场
flightTime = scrapy.Field()   #起飞时间
flightTimeEx = scrapy.Field()  #起飞时区
arrivedTime = scrapy.Field()  #到达时间
arrivedTimeEx = scrapy.Field() #到达时区
pass

构造对象的过程利用了Python面向对象写法,在这里需要引用Scrapy库,使用Field是为了以下两点。

(1) Field对象指明了每个字段的元数据(任何元数据),Field对象接收的值没有任何限制。

(2) 设置Field对象的主要目的就是在一个地方定义好所有的元数据。

MySpiders.py文件位于文件Spiders下,该文件中存放了提取数据的Spider,它用于定义初始URL根网址、请求初始URL之后的逻辑,以及从页面中爬取数据的规则(即写正则或xpath等)。

【例2】执行Spider,爬虫获取数据MySpider.py主文件。

import scrapy
from yryProject.TrafficItems 
import TrafficItems
class MySpider(scrapy.Spider):
name ="MySpider"allowed domains =['flightaware.com']start_urls =['https://zh, flightaware. com/live/airport/RJAA/arrivals?;offset = 0; sort =ASC;order =actualarrivaltime']
def parse(self,response):
items =targe
tFile = open("target.html",w',encoding = "utf - 8")targetFile.write(str(response.body))for box in response.xpath( "//*[@ d ='slide0utPanel']/div[1]/table[2]/tbody/trtdl11/table/tbody/tr") :
item = TrafficItems()
Symbol = box.xpath("./td[1]/span/a/text()").extract()
model = box.xpath("./td[ 2]/span/a/text()").extract()
leavePlace = box.xpath("./td[3]/span[1]/span/text()").extract()
landPlace = box.xpath("./td[3]/span[1]/span/text()").extract()leaveAirport = b ox.xpath("./td[3]/span[2]/a/text()").extract()#landAirport = box.xpath("./td[3]/span[2]/a/text()").extract()
flyTime = box.xpath("./td[ 4]/text()").extract()
flyTimeEx = box.xpath("./td[4]/span/text()").extract()
arriveTime = box.xpath("./td[ 5]/text()").extract()
arriveTimeEX = box.xpath("./td[5]/span/text()").extract()
if (Symbol !=[]):
item['Symbol =Symbol[ 0]
else:
item['Symbol'] = unknown'
if (model !=[]):
item['model'] = model[0]
else:
item['model'] =unknown'if (leavePlace != []):item['leavePlace'] = leavePlace[0]
else:
item['leavePlace'] = unknown'
if (leaveAirport !=[]):
item[leaveAirport'] = eaveAirport[0]else:
item[leaveAirport'] = unknownif (flyTime != []):
item['flightTime'] = flyTime[0]else:
item['flightTime'] = unknownif (flyTimeEx != []):
item['flightTimeEx'] = flyTimeEx[0]else:
item['flightTimeEx'] = unknown'if (arriveTime !=[]):
item['arrivedTime'] = arriveTime[0]else:
item['arrivedTime']"'unknownif (arriveTimeEX != []):
item[arrivedTimeEx'] = arriveTimeEX[0]
else:
itemarrivedTimeEx'] = unknown!yield item
response. xpath( "/html/body/div[1]/div[1]/table[ 2]/tbody/tr/td[1].next url =
span[2]/a[1]/@href").extract first()print(next url)yield scrapy.Request(next url,callback = self.parse)
#return items

在Spider文件中,需要定义一个爬虫名与爬取的网址的域名(allowed_domains),首先需要给出一个起始地址(start_urls),然后Scrapy框架就可以根据这个起始地址获取网页源代码,通过源代码获取所需值。下面通过XPath定位对应数据所在的HTML位置,再存放至item中构造好的对应字段中。这样就完成了一次爬取。

此处,一次性爬取一个页面的完整内容后,对于后续页面,可以通过next_url存放下一页面的网址。在爬取完后通过yield scrapy.Request(next_url,callback=self.parse)定位下一页,从而实现模拟翻页。

Mypipeline.py文件是一个管道文件,它约定了爬虫爬取后的内容流向哪里,由于需要存储这些爬取后的文件,所以在管道中将其写入了一个JSON文件。Item在Spider中被收集之后,它将会被传递到Item Pipeline,Pipeline接收到Item并通过它执行一些行为,同时也决定此Item是否能继续通过Pipeline,或是被丢弃。例3为Mypipeline.py的详细代码。

【例3】约定爬取到的内容如何处理。

#Mypipeline.py
#引入文件
from scrapy.exceptions import DropItem
import json
class MyPipeline(object):
def  init (self):
# 打开文件
self.file = open('data.json','w',encoding ='utf - 8')
# 该方法用于处理数据
def process item(self,item,spider):
#读取 item 中的数据
line = json.dumps(dict(item),ensure ascii= Ealse)
#写入文件
self.file.write(line)
#返回 item
return item
#该方法在 spider 被开启时被调用def open spider(self,spider):
pass
#该方法在 spider 被关闭时被调用def close spider(self,spider):
pass

由于案例中爬取数据所用的浏览器为Chrome,本爬虫使用了ChromeDriver。当编写此爬虫时, Chrome版本为85.0.4183.83,所使用的ChromeDriver需要和Chrome版本相匹配,则需要在chromeMiddleware.py中将driver初始化的指向路径改为本机中存放ChromeDriver的绝对路径。

【例4】设置ChromeDriver启动参数的中间件配置文件。

# chromeMiddleware.py
from selenium import webdriver
from selenium.webdriver.chrome.options import Options
from scrapy.http import HtmlResponse
import time
class chromeMiddleware(object):
def process request(self,request,spider):if spider.name == "MySpider":chrome options = Options()chrome options.add argument('--headless
chrome options.add argument('--disable -gpu')
chrome options.add argument('-- no -sandbox')
chrome options.add argument('-- ignore- certificate-errors')
chrome options.add argument('-- ignore - ssl - errors')
driver = webdriver.Chrome( "E: scrapy_work yryProject\yryProject chromedriverexe",chrome options = chrome options)driver.get(request.url)body = driver.page source#print("访问”+ request.url)return HtmlResponse(driver.current url, body= body, encoding = UTF - 8,request:
request
else:
return None

在爬虫运行的过程中,需要对一些细节进行设定,如设定爬虫运行的持续时间、限制爬取内容的数量,或是对爬虫延迟做出调整,这些需要调整的变量都存放于settings.py中,代码如例5所示。

【例5】设置爬虫通用属性的文件。

# settings.py
import uagent
BOT NAME =yryProject'
SPIDER MODULES =['yryProject.spiders']NEWSPIDER MODULE = yryProject.spidersCLOSESPIDER PAGECOUNT = 4
FEED EXPORT ENCODING =UTF - 8
ROBOTSTXT OBEY = False
USER AGENT = uagent.randomUserAgent()
DEFAULT REOUEST HEADERS =
Accept':'text/html,application/xhtml + xml,application/xml;q= 0.9,*/*;q= 0.8''Accept - Language':'en'
DOWNLOADER MIDDLEWARES = yryProject.chromeMiddleware.chromeMiddleware': 543
ITEM PIPELINES = (
yryProject.MyPipeline.MyPipeline': 1
}

03、爬虫的使用说明

修改完地址后,进入\yryProject目录,执行scrapy crawl MySpider即可运行爬虫。

爬取的结果保存在data.json文件中,其截图如图4所示。

■ 图4 爬取结果展示

 

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1038773.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

一文了解什么SEO

搜索引擎优化 (SEO) 是一门让页面在 Google 等搜索引擎中排名更高的艺术和科学。 一、搜索引擎优化的好处 搜索引擎优化是在线营销的关键部分,因为搜索是用户浏览网络的主要方式之一。 搜索结果以有序列表的形式呈现,网站在该列表中的排名越高&#x…

一个含不少免费额度和数据下载的IP地址来源查询工具

大家好,我是TJ君! 如今在国内运营的各种互联网应用都有接入IP来源显示的要求,现在相关API的供应商也很多。今天TJ刚好看到一个不错的,所以马上给大家推荐一下。 这款不错的产品名称为:IPInfo 产品特性 该IP查询工具…

解决 react 项目启动端口冲突

报错信息: Emitted error event on Server instance at:at emitErrorNT (net.js:1358:8)at processTicksAndRejections (internal/process/task_queues.js:82:21) {code: EADDRINUSE,errno: -4091,syscall: listen,address: 0.0.0.0,port: 8070 }解决方法&#xff…

第二证券:美国政府又要“关门”?3万亿市值蒸发!

上星期,欧美股市全线跌落,科技股大跌,纳斯达克指数跌逾3%,苹果、微软、谷歌、亚马逊、英伟达、特斯拉、脸书母公司Meta等七大科技股上星期市值算计削减4615亿美元(合人民币3.37万亿元)。 本周市场将发布我…

查看吾托帮88.47的docker里的tomcat日志

步骤如下 (1)ssh (2)ssh root192.168.88.47 等待输入密码:fytest (3)pwd #注释:输出/root (4)docker exec -it wetoband_deploy /bin/bash #注释&#xff1…

jmeterbeanshell调用jsonpath获取对应值

1.jmeter 新建线程组、Java Request、BeanShell Assertion、View Results Tree 2、在BeanShell Assertion中贴入代码: import org.apache.jmeter.extractor.json.jsonpath.JSONManager; import java.util.List; JSONManager js new JSONManager(); String jsonStr…

Vuex命名空间及如何获取根模块、兄弟模块状态管理器

模块化思想 import global from ./modules/global; import form from ./modules/form; import formDesign from ./modules/form-design; ...const store new Vuex.Store({state: {},mutations: {},actions: {},strict: true,modules: {global,form,formDesign,...},... } 此时…

现场直击|亚数TrustAsia精彩亮相IOTE深圳物联网展,CSA联盟展台等你来!

2023年9月20日,IOTE 2023第二十届深圳国际物联网展在深圳国际会展中心(宝安)顺利开幕。作为物联网领域年度最重要的行业盛会之一,本次展会汇聚全球来自工业、物流、基建、智慧城市、智慧零售等领域的600企业、10万行业人士&#x…

springboot 获取参数

1.获取简单参数 2.实体对象参数

软考高级+系统架构设计师教程+第二版新版+电子版pdf

注意!!! 系统架构设计师出新版教程啦,2022年11月出版。所以今年下半年是新版第一次考试,不要再复习老版教程了,内容改动挺大的。 【内容简介】系统架构设计师教程(第2版)作为全国计…

RuntimeException

1.介绍 说明:RuntimeException是一个运行时异常类,通常用于处理程序运行时发生的异常,例如空指针异常、数组越界异常等。运行时异常类是在程序中出现这类异常时,即使没有try...catch语句捕获异常或使用throws关键字声明抛出异常&…

漫谈:C语言 C++ 左值、右值、类型转换

编程不是自然语言&#xff0c;编程自有其内在逻辑。 左值引起的BUG 编译器经常给出类似这样的BUG提示&#xff1a; “表达式必须是可修改的左值” “非常量引用的初始值必须是左值” 看一下示例&#xff1a; #include <iostream>void f(int& x) {} int main() {sho…

激活函数总结(四十一):激活函数补充(ShiLU、ReLUN)

激活函数总结&#xff08;四十一&#xff09;&#xff1a;激活函数补充 1 引言2 激活函数2.1 ShiLU激活函数2.2 ReLUN激活函数 3. 总结 1 引言 在前面的文章中已经介绍了介绍了一系列激活函数 (Sigmoid、Tanh、ReLU、Leaky ReLU、PReLU、Swish、ELU、SELU、GELU、Softmax、Sof…

实验五 熟悉 Hive 的基本操作

实验环境&#xff1a; 1.操作系统&#xff1a;CentOS 7。 2.Hadoop 版本&#xff1a;3.3.0。 3.Hive 版本&#xff1a;3.1.2。 4.JDK 版本&#xff1a;1.8。 实验内容与完成情况&#xff1a; &#xff08;1&#xff09;创建一个内部表 stocks&#xff0c;字段分隔符为英文逗号…

PS4 9.0 使用ESP32 自动破解器时如何保持 内/外网通讯 | PS4 9.0 ESP32 HEN with Internet

环境&#xff1a;PS49.0 ESP32 破解器 群晖 问题&#xff1a;连接到破解器无线网络后无法与内外网通讯&#xff0c;需要先golden hen后再切换无线网络 解决办法&#xff1a;修改ESP32 WIFI工作模式为WIFI 客户端模式 背景&#xff1a;当我在PS4 9.0上使用ESP32时&#xff0c;…

spingboot之devtools热部署IntelliJ IDEA 2022.2.3不生效问题,解决

目录 环境&#xff1a; 添加依赖&#xff1a; 修改idea配置&#xff1a; 步骤一&#xff1a;“command,”命令进入配置界面。勾选下面配置 步骤二&#xff1a;进入Advanced Setting设置 步骤三&#xff1a;修改启动配置 步骤四&#xff1a;保存 开发过程中避免不了代码…

uniapp iconfont-引用阿里巴巴矢量图标库

k-icons-font图标插件: https://ext.dcloud.net.cn/plugin?id14612 下载图标库 https://www.iconfont.cn/ 为了方便使用设置FontClass为空&#xff0c;当然不设置也可以 下载图标库 将图标可以中的&#xff1a;iconfont.css、iconfont.ttf拷贝到插件目录上"k-icons-f…

助力养殖行业数字化转型,基于深度学习模型开发构建羊脸识别系统

养殖行业的数字化进程在国内还是比较缓慢的&#xff0c;一些大厂在前面的一些探索时期做过一些相关的工作&#xff0c;但是受限于各种因素并没有能够广泛地铺展开来&#xff0c;数字化不应该被理解为非常高大上的遥不可及的东西&#xff0c;数字化也不应该成为中低产的一道鸿沟…

C++标准模板库STL——list的使用及其模拟实现

1.list的介绍 list的文档介绍 1. list是可以在常数范围内在任意位置进行插入和删除的序列式容器&#xff0c;并且该容器可以前后双向迭代。 2. list的底层是双向链表结构&#xff0c;双向链表中每个元素存储在互不相关的独立节点中&#xff0c;在节点中通过指针指向 其前一个…

【Kubernetes】Kubernetes的污点和容忍度

Kubernetes的污点和容忍度 在K8S中&#xff0c;如果Pod能容忍某个节点上的污点&#xff0c;那么Pod就可以调度到该节点。如果不能容忍&#xff0c;那就无法调度到该节点。污点和容忍度就像谈恋爱的小情侣&#xff0c;你情我愿&#xff0c;女生知道男生的缺点&#xff0c;却依然…