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


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

    请求、解析、处理数据是通用爬虫的三个步骤,在本案例中,利用机场官网的详细信息,在网页上定位各类数据的路径,通过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文件。

    1. import scrapy
    2. class TrafficItems(scrapy.Item):
    3. sysmbol = scrapy.Field() #标识符
    4. model = scrapy.Field()
    5. leavePlace = scrapy.Field() #始发地
    6. leaveAirport = scrapy.Field() #出发机场
    7. destssination = scrapy.Field() #目的地
    8. destssinationAirport = scrapy.Field() #到达机场
    9. flightTime = scrapy.Field() #起飞时间
    10. flightTimeEx = scrapy.Field() #起飞时区
    11. arrivedTime = scrapy.Field() #到达时间
    12. arrivedTimeEx = scrapy.Field() #到达时区
    13. pass

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

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

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

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

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

    1. import scrapy
    2. from yryProject.TrafficItems
    3. import TrafficItems
    4. class MySpider(scrapy.Spider):
    5. name ="MySpider"allowed domains =['flightaware.com']start_urls =['https://zh, flightaware. com/live/airport/RJAA/arrivals?;offset = 0; sort =ASC;order =actualarrivaltime']
    6. def parse(self,response):
    7. items =targe
    8. 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") :
    9. item = TrafficItems()
    10. Symbol = box.xpath("./td[1]/span/a/text()").extract()
    11. model = box.xpath("./td[ 2]/span/a/text()").extract()
    12. leavePlace = box.xpath("./td[3]/span[1]/span/text()").extract()
    13. 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()
    14. flyTime = box.xpath("./td[ 4]/text()").extract()
    15. flyTimeEx = box.xpath("./td[4]/span/text()").extract()
    16. arriveTime = box.xpath("./td[ 5]/text()").extract()
    17. arriveTimeEX = box.xpath("./td[5]/span/text()").extract()
    18. if (Symbol !=[]):
    19. item['Symbol =Symbol[ 0]
    20. else:
    21. item['Symbol'] = unknown'
    22. if (model !=[]):
    23. item['model'] = model[0]
    24. else:
    25. item['model'] =unknown'if (leavePlace != []):item['leavePlace'] = leavePlace[0]
    26. else:
    27. item['leavePlace'] = unknown'
    28. if (leaveAirport !=[]):
    29. item[leaveAirport'] = eaveAirport[0]else:
    30. item[leaveAirport'] = unknownif (flyTime != []):
    31. item['flightTime'] = flyTime[0]else:
    32. item['flightTime'] = unknownif (flyTimeEx != []):
    33. item['flightTimeEx'] = flyTimeEx[0]else:
    34. item['flightTimeEx'] = unknown'if (arriveTime !=[]):
    35. item['arrivedTime'] = arriveTime[0]else:
    36. item['arrivedTime']"'unknownif (arriveTimeEX != []):
    37. item[arrivedTimeEx'] = arriveTimeEX[0]
    38. else:
    39. itemarrivedTimeEx'] = unknown!yield item
    40. response. xpath( "/html/body/div[1]/div[1]/table[ 2]/tbody/tr/td[1].next url =
    41. span[2]/a[1]/@href").extract first()print(next url)yield scrapy.Request(next url,callback = self.parse)
    42. #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】约定爬取到的内容如何处理。

    1. #Mypipeline.py
    2. #引入文件
    3. from scrapy.exceptions import DropItem
    4. import json
    5. class MyPipeline(object):
    6. def init (self):
    7. # 打开文件
    8. self.file = open('data.json''w',encoding ='utf - 8')
    9. # 该方法用于处理数据
    10. def process item(self,item,spider):
    11. #读取 item 中的数据
    12. line = json.dumps(dict(item),ensure ascii= Ealse)
    13. #写入文件
    14. self.file.write(line)
    15. #返回 item
    16. return item
    17. #该方法在 spider 被开启时被调用def open spider(self,spider):
    18. pass
    19. #该方法在 spider 被关闭时被调用def close spider(self,spider):
    20. pass

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

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

    1. # chromeMiddleware.py
    2. from selenium import webdriver
    3. from selenium.webdriver.chrome.options import Options
    4. from scrapy.http import HtmlResponse
    5. import time
    6. class chromeMiddleware(object):
    7. def process request(self,request,spider):if spider.name == "MySpider":chrome options = Options()chrome options.add argument('--headless
    8. chrome options.add argument('--disable -gpu')
    9. chrome options.add argument('-- no -sandbox')
    10. chrome options.add argument('-- ignore- certificate-errors')
    11. chrome options.add argument('-- ignore - ssl - errors')
    12. 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:
    13. request
    14. else:
    15. return None

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

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

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

    03、爬虫的使用说明

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

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

    ■ 图4 爬取结果展示

     

     

  • 相关阅读:
    读vue源码搞懂响应式原理
    C#—Json序列化和反序列化
    Qt SQLite的创建和使用
    离散事件仿真原理DES
    【Ansible】YAML语法
    飞书开发学习笔记(六)-网页应用免登
    图文详细解决IDEA使用Debug模式启动项目一直转圈圈跑起不来(亲测可以)
    @Documented 的作用
    SQL Server Reporting Services
    kafka初体验基础认知部署
  • 原文地址:https://blog.csdn.net/qq_41640218/article/details/133266052