京公网安备 11010802034615号
经营许可证编号:京B2-20210330
“你喜欢旅游吗?”
这个简单的问题经常会得到一个积极的回复甚至还会额外收到一个或两个冒险的故事。通常来讲,旅行是一种体验新文化和拓宽自己视野的好方法。
但如果把问题换成“你喜欢查机票的过程吗?”,我敢肯定大家的反应一定会不那么热情......
那么,用Python解决你的难点吧!本文作者Fábio Neves,一位资深的商业数据分析师将会带你建立一个网络爬虫项目,帮助我们找到最优惠的价格!
具体做法是对特定目的地以及灵活的日期范围(根据你选择的日期前后最多3天)进行航班价格搜索。
搜索结果保存到一个excel中并为你发送一封展示快速统计信息的电子邮件。显然,最终的目的是帮助我们找到最优惠的价格!
如果你真的想试试,你可以在服务器上执行这个脚本(一个简单的Raspberry Pi就可以(注:Raspberry Pi树莓派又称卡片式电脑,外形只有信用卡大小,运算性能和智能手机相仿。So大家在自己笔记本电脑上折腾就足够了。。)),并且每天运行一次或两次。它会将检索结果以邮件的形式发给你,我建议将excel文件保存到Dropbox云端,这样你就可以随时随地访问它。
注:Dropbox是一个类似于百度云的云端服务
我还是没找到任何错误低价票,但我想还是有可能的!
它会根据“弹性日期范围”进行检索,以便查找你首选日期的前后最多3天的所有航班。尽管该脚本一次只适用于一组from/to目的地,但你可以轻松地调整它在每个循环内运行多组行程目的地。你甚至可能最终找到一些错误低价票......简直棒极了!
爬虫脚本
当我第一次开始做网络爬虫时,我对这块并不特别感兴趣。我本想用预测建模,财务分析和一些情绪分析来做更多的项目,但事实证明,弄明白如何构建第一个网络爬虫是很有趣的。随着我不断学习,我意识到网络抓取是互联网运转的精髓。
是的......就像Larry 和 Sergey一样,在启动爬虫程序后去尽情享受按摩浴缸吧!
你可能认为这是一个非常大胆的想法,但如果我告诉你谷歌就诞生于Larry 和 Sergey通过Java和Python写的爬虫程序呢?谷歌通过爬取整个互联网来试图为你的问题提供最佳答案。有非常多关于网络爬虫的应用程序,即便你更喜欢数据科学中的其他主题,你仍然需要一些爬虫技能来获取想要的数据。
Python可以来拯救你
第一个挑战是选择从哪个平台抓取信息。这其实并不容易,但我最终选择了Kayak。决定之前我尝试了Momondo,Skyscanner,Expedia等等,但这些网站上的验证码部分真的是让人抓狂。经过几次尝试选择交通信号灯,人行横道和自行车的这种“你是真人吗”的检查后,我的结论是Kayak是目前最好的选择,即使它在短时间内加载太多页面时也会抛出安全性校验。
我设置机器人以4到6小时的间隔来查询网站,这样就不会有问题了。在这里和那里偶尔可能会出现卡壳中断现象,但是如果你遇到验证码校验,那么你需要手动进行验证码认证,确认完毕后再启动机器人程序,然后等待几个小时它就会重置。你也可以随意将这些代码应用到其他平台,欢迎你在评论部分分享你的应用!
如果你是个爬虫新手,或者还不了解为什么有一些网站总会设置各种障碍来阻止网络抓取,那么在写第一行爬虫代码之前,请你先阅读了解一下谷歌“ 网络抓取礼仪 ”。如果你像疯子一样准备好了开始网络抓取,你获得努力成果可能会比你想象的要快得多。
网络抓取礼仪 :
http://lmgtfy.com/?q=web+scraping+etiquette
请系好安全带……
打开chrome标签页后,我们将定义一些在循环内使用的函数。关于整体结构的大致想法是这样的:
OK,每个Selenium项目都将以webdriver作为开头。我用的是ChromeDriver,当然还有其他选择。比如,PhantomJS或Firefox也很受欢迎。webdriver下载好之后,将其放在一个文件夹中就可以了。代码的第一行将会自动打开一个空白的Chrome标签页。
请注意,我不是在这里开辟新天地,或是提出一种非常具有开拓性的创新。当下确实已经有更先进的方法来寻找便宜的票价,但我希望我的这个帖子可以跟大家分享一些简单而实用的东西!
这些是我用于整个项目所引用的包。我将使用randint来让机器人在每次搜索之间随机停顿几秒钟。这是所有机器人所必备的功能。如果你运行了前面的代码,则需要先打开一个Chrome网页窗口作为机器人检索的入口。
所以,先让我们来快速测试一下,在新网页打开http://kayak.com。选择你要飞往的城市和日期。选择日期时,请务必选择“+ -3天”。我已经编写了相关的代码,如果你只想搜索特定日期,那么你需要适当地进行一些调整。我将尽量在整个文本中指出所有的变动值。
点击搜索按钮并获取地址栏中的链接。这个链接应该就是我在下面需要用的链接,在这里我将变量kayak定义为url并调用webdriver的get方法。你的搜索结果接下来应该就会出现了。
每当短时间内多次使用get命令的时候,系统就会跳出验证码检查。你可以手动解决验证码问题,并在下一个问题出现之前继续测试脚本。从我的测试来看,第一次搜索运行似乎一切正常,所以如果你想要用这段代码,并且让它们之间保持较长的执行间隔,就可以解决掉这个难题。你并不需要每10分钟就更新这些价格,不是吗?!
XPath的坑
目前为止,我们打开了一个浏览器窗口并获得了网址。接下来我会使用XPath或者CSS选择器来抓取价格等其他信息。曾经我也只用XPath,当时我觉得没必要用CSS,但是现在看来最好结合着用。你可以直接用浏览器复制网页XPath来用,你也会发现由XPath虽可以定位网页元素但是可读性很差,所以我渐渐意识到只用XPath很难获得你想要的页面元素。有时候,指向得越细就越不好用。
接下来,我们用Python来选择出最低票价的页面元素。上述代码中红色部分就是XPath选择器的代码,在网页中,你可以在任意位置点击右键并选择“检查”来找到它。试试吧,在你想看代码的地方点右键,“检查”它。
为了说明我前面所说的XPath的不足,请大家对比如下差异:
1 # This is what the copy method would return. Right click highlighted rows on the right side and select "copy > Copy XPath"//*[@id="wtKI-price_aTab"]/div[1]/div/div/div[1]/div/span/span2 # This is what I used to define the "Cheapest" buttoncheap_results = ‘//a[@data-code = “price”]’
上述代码中,第二种方式的简洁性清晰可见。它会去搜素具有data-code属性值为price的a元素。而第一种方式则是去搜素一个id为wtKI-price_aTab元素,且该元素嵌在5层div及2层span内。对于这次页面,它能起作用,但这里的坑在于,下次加载页面时,这个id会变,而且每次加载时wtKI值也是动态变化的,所以到时候这段代码就无效了。所以多花点功夫研究一下XPath表示的内容还是对你有价值的。
不过这种直接复制XPath的方法对于那些不是很复杂善变的页面来说还是蛮好用的。
基于上述代码结果,如果我想找出所有匹配的结果并存到list里,该怎么做呢?很简单,因为所有结果都在CSS对象resultWrapper中,只要按照我下图代码中写个for循环就能获得所有结果。这个思路掌握了,那下图的代码你也就基本看明白了。也就是说,先选定最外层的页面元素(如本文网站中的resultWrapper),再找一种方式(如XPath)来获取信息,最后再将信息存到可读的对象中(本例中先存在flight_containers中,再存在flights_list中)。
我把前三个结果详细内容都打印出来了,里面有我们需要的全部有用信息,但我们还是要找个更好的方法提取它们,这时我们就要对这些元素单独解析。
开始爬数据!
最简单的代码就是读取更多这个函数,我们先从这里开始。我希望在不触发安全校验的情况下获取尽量多的航班,所以在每次加载完页面我都会点击“load more results”按钮。值得注意的是我用到了try语句,因为有的时候不一定会存在这个按钮。
哦嘞,前期铺垫的有点长(抱歉,我确实比较容易跑偏)。我们现在要开始定义用于爬数据的函数了。
我在下文会提到的page_scrape函数中解析了大部分元素。有时候,返回来的航班list中会有两段行程。我简单粗暴地把它拆成两个变量,如section_a_list 和section_b_list。当然,函数还是会返回一个名为flights_df 的DataFrame对象,有了它我们接下来就可以任意排序并视情况切片或合并。
变量名中带a的表示第一段行程,带b的表示第二段行程。接着看下一个函数。
别急,还有干货!
到现在为止,我们有用于加载更多结果的函数,有用于解析这些结果的函数。你可以认为这就完事了,可以靠着它们去手动地爬网页了,但我前面还提到过,我们的目标是能给自己发邮件,当然还能包括一些其他信息。看看下面这个函数start_kayak,所有这些都在里面。
这需要我们定义一下要查询的航班的地点和日期。我们会打开kayak变量中的网址,并且查询结果会直接按照“best”方式排序。在第一次爬数之后,我就获得了页面上方的价格矩阵数据集,它将用于计算均价和最低价,然后和Kayak的预测价(页面的左上角)一起通过电子邮件发出。在单个日期搜素时可能导致错误,因为这种情况下页面顶端没有价格矩阵。
我用outlook邮箱(http://hotmail.com)做了测试。虽然Gmail我没试过,甚至还有其他各种邮箱,但我想应该都没问题。而且我前文提到的书中也写了其他发邮件的方式,如果你有hotmail邮箱,可以直接在代码中替换你的邮箱信息,就可以用了。
如果你想知道脚本中某部分代码的功能,你要把那部分拷出来测试一下,因为只有这样你才能彻底地理解它。
把代码跑起来
当然,我们还能把我们前面编的函数放进循环里让它一直执行。写明4个输入提示,包括起降的城市和起止时间(输入)。但在测试的时候,我们并不想每次都去输入这个四个变量,就直接修改4个变量,如注释的那四行代码所示。
恭喜各位,至此我们已经大功告成了!其实还有很多可以改进的地方,比如我能想到的还可以用Twilio实现发送短信进而取代邮件。你还能架VPN或者以其他隐蔽的方式,同时通过多个服务器来爬数据。还有验证码问题,它们总会不时地跳出来,不过这还是有办法解决的。如果你有比较好的基础,我觉得你可以试试加上这些功能。甚至你还会想把Excel文件作为邮件的附件一起发出。
编译:高延、熊琰、胡笳、蒋宝尚
数据分析咨询请扫描二维码
若不方便扫码,搜微信号:CDAshujufenxi
【核心关键词】产品、经营、客户、调研、销售额、宏观、会计行业、客户满意度、发展趋势、经营状况、数据分析、竞争对手、数据 ...
2026-07-14问卷调查是市场调研、用户研究、社会调研与产品分析的核心数据采集方式。问卷数据大多以分类数据为主,例如用户性别、年龄分层、 ...
2026-07-14 很多数据分析师画过趋势图、做过业绩预测,但当被问到“这个月销售额增长20%,到底是长期趋势自然增长,还是促销活动的短期 ...
2026-07-14在数据分析、业务效果验证、AB实验扩展、行业对比等场景中,我们经常需要对比三组及以上样本的均值差异,例如不同区域的客单价对 ...
2026-07-13在互联网产品运营、用户生命周期管理与商业化数据分析中,留存指标是判断产品价值、用户满意度与商业模式健康度的核心基准。常规 ...
2026-07-13 很多数据分析师做过按月份的销售额趋势图,画过按天的流量折线图,但当被问到“时间序列和普通数据有什么本质区别”“季节性 ...
2026-07-13【核心关键词】统计学、互联网、知识、课程、学生、数学、软件、招聘、数据分析、实习经历、机器学习、理论基础、业务思维、统 ...
2026-07-10在互联网运营、产品设计、市场营销与商业数据分析领域,所有转化、成交、复购行为的底层逻辑,都依托于用户决策流程。用户从产生 ...
2026-07-10 很多数据分析师能熟练地计算指标、搭建标签体系,但当被问到“画像到底在解决什么问题”“画像和标签是什么关系”“画像如何 ...
2026-07-10数据透视表是数据分析中最常用、最高效的汇总分析工具,具备快速分组、聚合计算、维度拆解、数据可视化等优势,能够轻松完成求和 ...
2026-07-09在统计学、CDA数据分析、机器学习与商业数据研究中,正态分布是最基础、最重要的数据分布形态。绝大多数参数检验、数据建模、指 ...
2026-07-09 很多分析师在设计标签时思路清晰,但真到落地环节却面临“数据在手,不知如何转化为可用标签”的困境:或因加工方式选择不当 ...
2026-07-09【核心关键词】采购、周期、原材料、企业、产品、成本、要素、库存、供应商、数据分析、生产计划、生产制造、加工制造、技术工 ...
2026-07-08在数据分析、特征工程、机器学习建模的工作流程中,原始数据往往包含多个不同维度的数值指标,例如客户交易数据中的消费金额、交 ...
2026-07-08 很多分析师每天和数据打交道,但当被问到“标签是什么”“标签和指标有什么区别”“标签体系如何设计”时,却常常答不上来。 ...
2026-07-08商业谈判是企业采购合作、渠道签约、价格议价、项目合作、客户签约的核心关键环节,直接决定企业的合作成本、利润空间与经营风险 ...
2026-07-07在数据分析、业务效果验证、AB 测试、学术研究等场景中,T 检验是假设检验体系里最基础、应用最广泛的统计方法,也是均值差异分 ...
2026-07-07 很多数据分析师每天都在写SQL,但当被问到“数据查询语言(DQL)的本质是什么”“SELECT语句中各子句的书写顺序与实际执行顺 ...
2026-07-07【核心关键词】转化率、企业、策略、岗位、互联网、拆分、产品、运营、分析师、指标体系、数据分析、用户画像、数据诊断、产品 ...
2026-07-06在数据分析工作中,文本数据处理是高频刚需场景,用户评论、客服工单、日志信息、调研问卷、商品文案等数据都包含大量文本内容。 ...
2026-07-06