php怎么写邮件发送,有哪些好用却不为人知的国产软件?
这几款国产软件太可惜了!全是大厂出品,超好用,还免费,可惜知道的人太少了!各个堪称“神器”
01 滴答音乐一款免费的音乐下载软件,可以下载一切高品质音乐!软件体积只有3M,却功能强大发,是个人用户开发的软件,全免费!
有了滴答音乐,帮你搞定所有音乐下载问题。你只需记住自己想要下载的歌曲名,在滴答音乐中进行搜索,选择后点击下载即可。
十分方便,最重要的是支持多种品质下载。
滴答音乐几乎可以下载所有的音乐,资源十分丰富,且页面无广告,使用简单!简直神奇啊!
不过,可惜的是,这个软件在一些平台上,你可能无法下载,不过不用担心,我给你下载好了安装包。
关注@旁门左道PPT ,点击我的头像,进入主页,点击私信,回复关键词【国产】,即可获取全文所有软件安装包。
02 夸克浏览器一款阿里旗下的超实用,无广告的免费小众手机浏览器。
搜索结果中不会有竞价广告,大多数网站里的广告,都会被过滤。智能拼页的浏览方式,堪称是神器!
打开和加载的速度都特别快。我把夸克,谷歌,百度放在一起,做了一个对比,简直秒杀:
在同一手机同一网络环境下,打开浏览器的时间依次是:夸克<1秒,谷歌2秒,百度9秒(6秒打开+3秒广告)
我比较喜欢它的高速百度网盘下载功能,在浏览器下载设置里直接把下载线程调为64,你就会发现下载速度竟然高达1-5M/S,与几十K/S的龟速比起来,效率是不是高多了:
不说了,谁用谁爱~不过可惜的是,这款良心的小软件,用的人有点少……
03 爱奇艺万能播放器爱奇艺旗下的一款免费本地视频软件,可以播放图片,视频等多种格式文件,支持几乎所有主流视频格式查看,堪称强大!
当然,也因为小众,被很多人忽视,但真的超好用!而且大厂出品,比较稳定!
这款万能播放器,提及特别小,仅有15M,启动速度快,卡顿现象几乎没有,可播放文件的格式十分丰富:支持mp4、mkv、3gp、rmvb等任意视频及音乐播放:
这个播放的格式,可以说真的无敌了!
它的功能还有很多,最让我惊喜的是,借助它可以几乎实现全速百度网盘内容的下载!只需轻松点击界面上百度云图标,登录账号,便可以实现下载,几乎全速:
用了就舍不得放下的视频播放软件!
目前这个软件已经下架了,不过我给你准备好了安装包。
关注@旁门左道PPT,点击我的头像,进入主页,点击私信,回复关键词【国产】即可获取~
04 用药助手这是一款帮你了解医药信息的APP。
这款APP是由丁香医生团队开发,一款专门面向医生、用户等提供医药信息查询的专业查询工具,避免药物食用错误!
软件内包含40000种药品的说明书,帮助你更好地了解生活常用药品的功能;包括5000多个专业的医生给出的用药指南,防止用药错误。
也收录了近万种常见疾病的介绍以及相关治疗信息;
还有比较贴心的药物相互作用指南,这个功能真的很贴心,可以很大程度上帮助我们告别药物用错导致的副作用!
不过呢,这个软件只能作为辅助,用药还是要遵医嘱哦~
05 袋鼠输入百度旗下的一个小众免费APP,一款用手机遥控电脑的神器工具
在电脑和手机端同时下载之后,只要在同一网络下,你就可以使用手机操控电脑,非常方便。
你可以利用它完成文字输入:
直接对着手机讲话就可以自动输入到电脑上~
你还可以把它当作一个电脑的遥控器:
汇报的时候,可以用它遥控PPT播放;
追剧的时候,可以用它遥控视频播放。
最赞的是,你还可以使用【鼠标模式】,可以直接把手机当作无线鼠标使用:
体验非常好,简直是给电脑加了一块触控板。让你再也不用担心忘了带PPT遥控器!
06 妙读阿里旗下出品的一款读书软件,它除了界面简约清晰之外,最大的优点就是让你能充分利用碎片时间,提炼书中内容干货,让你15分钟内以最快速度、便捷的方式读透一本书。
不愧是阿里出品的图书,在妙读精选页面,每一本书推荐都很精致:
在书架板块,有超多的精选书籍,另外,所有的图书都支持听书模式,让你随时随地看书!听书模式的声音还挺自然的:
大厂的东西,还是很优秀的,知识知道的人太少了
07 给未来写封信这是一个非常小众的国产软件,很温情,专属于你自己!给未来的你写封信!
界面做得很精致,有意境。
我个人比较喜欢写信的功能,你可以给未来的自己写一封信,并定义好时间:
想象一下,日后的某一天,你收到了来自自己的信,现在的你,看着当年或哭或笑,或吵或闹的自己,别有一番感触。
软件中,你还能看到不同人的信件,遇见与你相似的一颗灵魂。试着用这款软件去记录你现在的每一刻,邮寄给未来的自己吧!
08 折扇腾讯收购的一款中国风的折扇知识普及软件。
界面太美了,作为一名设计师,我实在是忍不住沉浸其中。
设计美到巅峰是什么样子,大概就是折扇这款软件的样子,每一个页面都能让人欣赏半天。
这是一款科普扇子文化的软件,你可以详细地端详每款扇子。了解关于扇子的知识,除此之外,APP的动画和触感,简直让人心动,太美了!这款软件,你一定要试试!
你可以亲手体验制作扇子的过程,设计出属于自己的扇子!掌握关于扇子的文化!
另外,大家不要忘记领取这些软件的安装包!
关注@旁门左道PPT,点击我的头像,进入主页,点击私信,回复关键词【国产】即可获取~
看到这里,别忘了给我点个赞哦!
你手机里有哪些逆天的app?
推荐的都算是深度使用过的吧。
可能比较杂,各个方面的App都会提。
自己平时也比较喜欢在各大应用市场,App Store上挖掘一些新应用哈哈哈哈。
话不多说,开始整吧。
1、看理想这个可能听说过他们公号的会比较多一点。
公号在这一次疫情中产出了许多爆款。
不过App更推荐。
做知识付费的App不少,但如此有人文关怀和艺术素养的,只此一家不过分。
道长的“八分”也几乎是看理想上的每期必看了。
2、全历史这一个是在最近几年渐渐火起来的。
也是通过口碑发酵,在用户之间口耳相传,逐渐有了知名度。
可见,只要内容过硬,质量够好。
真的不愁没有人用。
顾名思义是一款历史知识相关的App,但它绝对能颠覆掉你对历史的过往认知。
不多说了,用了就知道。
3、幕布幕布刚用不久。
但是一个刚用就能让人确定:这玩意儿以后可能得常用了。
梳理思路,整理idea,把碎片化的知识体系化。
最好用的是思维导图,这对一个做内容的互联网人来说,太爱了。
4、闲猫星球可能是唯一推荐的社交App?
原因真的只有一个,也是最重要的一个。
真,真实。
现在的交友App,10个里面,4个机器人,3个卖东西的,2个骗钱的,还剩一个不理你。
闲猫星球里面,小哥哥小姐姐都是经过双重认证之后才能上线和其他人聊天。
就真实这一点,能吊打许多同行了。
如果是真想解决情感需求的,上这里没错。
5、国家地理不知道吧?
国家地理除了每个月一本厚厚的全彩杂志,还有App。
作为喜欢旅游,但囊中羞涩的人来说,太爱了。
因为工作,基本上一年也就能出去一两次。
但已经习惯了,通勤的时候,必刷一下国家地理的每日推荐。
最重要的是,除了一幅幅美景,
那些和美景有关的人文介绍,才是真正吸引我的地方。
如何自学Python?
无论题主是否已经学习了一些其他的编程语言,在开始学习Python时,都应该先从Python的基本概念学起,这样在之后的编程实战中就能尽量减少因为不熟悉语言机制而出现的错误。
《Python编程:从入门到实践》,作者:Eric Matthes,译者:袁国忠这是一本Python入门书,共分为入门和实践两个部分:第一部分介绍了Python编程的基本概念,包括matplotlib、NumPy和Pygal等强大的Python库和工具介绍,以及列表、字典、if语句、类、文件与异常、代码测试等内容;第二部分通过三个项目(Python 2D游戏开发,利用数据生成交互式信息图,以及创建和定制简单的Web应用)将理论付诸于实践。帮助读者理解Python编程的概念及用途。使用Python 2或Python 3的读者都可以利用这本书来学习。
《Python编程快速上手——让繁琐工作自动化》,作者:[美] Al Sweigart 斯维加特,译者:王海鹏这本书致力于教大家利用Python 编程,在几分钟内完成手工需要几小时的工作。比如:在一个文件或多个文件中搜索文本;创建、更新、移动和重命名文件和文件夹;搜索网页和下载的在线内容;在任意大小的Excel电子表格中更新和格式化数据……这本书一步一步地引导你完成每个程序,并用你学到的新技能来让类似的任务自动化。你不用再浪费时间去做任何可以自动化的工作。即使你从未写过一行代码,也可以让计算机来做繁重的工作。在学习爬虫以前,可以先利用这些小功能来体会一下Python编程带来的便利。
《Python基础教程 第3版》,作者:[挪]Magnus Lie Hetland,译者:袁国忠这本书专门针对Python 3进行讲解,包括了Python程序设计的方方面面:从列表、元组等基础概念,到抽象、异常等相对高级的话题,再到将Python与数据库、网络、C语言等工具结合使用,Python程序的测试、打包和发布。最后,这本书按照实际项目开发的步骤向读者介绍了10个具有实际意义的Python项目的开发过程,供读者练习并体会代码功能。
仅仅学习一些分散的基础知识还不能让你熟练地开发一个综合功能,最好能利用几个通用的应用来体会Python语言中各种知识点的应用场景,并将其融会贯通,举一反三。
《Python核心编程(第3版)》,作者:[美]Wesley Chun,译者:孙波翔 李斌 李晗这本书是经典畅销图书《Python核心编程(第二版)》的全新升级版本,全书共分为3部分。第1部分讲解了Python的一些通用应用,包括正则表达式、网络编程、Internet客户端编程等内容;第2部分讲解了与Web开发相关的主题;第3部分则包括文本处理以及一些其他内容。适合具有一定基础的Python开发人员作为进阶教程来学习。
既然题主想利用Python从网上爬取数据,那么阅读一些网络爬虫方面的书籍就非常有必要了。
《Python 3网络爬虫开发实战》,作者:崔庆才这本书介绍了如何利用Python 3开发网络爬虫,书中讨论了urllib、requests、正则表达式、Beautiful Soup、XPath、pyquery、数据存储、Ajax数据爬取等内容,接着通过多个案例介绍了不同场景下如何实现数据爬取,最后介绍了pyspider框架、Scrapy框架和分布式爬虫,适合Python程序员阅读。
得益于Python强大而丰富的库以及数据分析能力,Python在神经网络、深度学习等方面都已经有了成熟的包可供调用。除了网络爬虫以外,题主也可以对Python在其他方向的应用进行扩展学习。
《Python神经网络编程》,作者:[英]塔里克·拉希德,译者:林这本书从简单的思路着手,利用Python语言详细介绍了神经网络工作所须的基础知识,共包括三部分:第1部分介绍基本的思路,包括神经网络底层的数学知识,第2部分介绍了学习Python编程的流行方法,并使用Python构建神经网络,让其像专家所开发的网络那样工作(如手写字母的识别)。第3部分扩展介绍了如何将神经网络的性能提升到工业应用的层级,甚至让其在Raspberry Pi(树莓派,一款单板计算机)上工作。
这几本书基本覆盖了从学习基础概念到利用Python完成实际工作的完整学习路线,建议题主根据自己的程度进行针对性的学习。不必急于求成,毕竟在学习过程中的每一条bug都可能让你学到一点新技能。
更多关于IT、经管和心理学精彩内容和图书推荐请大家关注@人民邮电出版社
如何写一封好的外贸开发信?
说说几个重要的原则:
1. 首先,重要的事情说三遍:
找准目标客户再写!找准目标客户再写!找准目标客户再写!
因为,如果这个客户不做你的产品,或者规模太小只在当地采购,或者只是完全是另一个行业的,那么你一天发出去200封开发信,也全部是无效的。目标客户正确了,开发信给对了人,即使你只发一封邮件,这一封的有效率是100%。举个例子,我的第一个外贸客户,是我实习的时候遇到的,初入职场的嫩草,完全不知道怎么开始,但是认准了一点,就是不做无用功。我搜到这个客户,先查了一下公司网站,确定是做这个产品的,再根据领英等平台判断客户规模,判断他有进口需要后,才开始开发这个客户。我的一个同事,每天发200多封开发信,初入外贸的我羡慕得很,觉得人家的工作效率真高啊!结果呢,我第二天收到这个客户的回复,同事一个月没有收到一封回复,反而被垃圾邮件占满了,因为她发的全是各种能看到的邮箱,比如xxx采购名录,邮箱那头是谁,完全不知道,也不知道这个邮箱是不是骗子留下的。
2,一定要发对人。也就是说,确定这个公司是目标客户后,那就要开始找对人。我们都知道国外客户不喜欢留下采购部的联系方式,就是怕大家打扰他啊!但是我们不打扰他,怎么能把产品推销给他呢? 所以还是要想方设法地烦扰他啊!如果你发的邮箱对应的是叉车司机、财务主任、生产工人。。。你想,他看到邮件会不会直接无视呢?情况好的,会帮你转发,或者告诉你他不负责;但是,99%以上的人,会无视或者删除,哪怕你让他给你负责人联系方式,他也不敢,也不想啊。所以,你要自己找。具体方法先不说,以后再详谈,因为方法太多了。
3,标题不要写敏感词汇。举个例子,做LED灯的,采购经理真的每天收到几十封上百封邮件,而且”LED”标题的太多了,看到你是陌生人,很多会选择“未读删除”。建议直接列举出来优势,比如你们产品的独家优势是xxx,那就直接在标题里面写出来。很多人建议你用当地的大品牌做标题,代表你们给大品牌供货了。我试过,的确很多回复你的,然后结果就是客户会一再确认你们是不是供过货给大品牌,如果是,在哪里,他要去看,刨根问底。。。因为他就是被这个吸引来的。而且这样做的另一个隐患是:绝大部分客户不希望自己在哪家供应商拿货被别人知道,明目张胆地大量开发,他会认为你将来也会打着他的旗号去开发别人,第一印象真的很重要。
4,要有针对性。也就是说,千篇一律的模板不适合所有客户,尤其一些特殊客户,比如你的竞争对手的客户。举个例子:我通过海关数据发现竞争对手的客户,这封开发信的重点就是:直接表明我们的产品不存在xx问题,这个问题当然就是你的竞争对手的问题。再举个例子,我的一个客户,通通过研究网站发现他的产品存在一个缺陷,开发信里就直接说:我发现你的产品....当然,不要说这是严重的问题,而要说我们有更好的解决方式,我们的产品这方面性能更好...etc。 越是重要客户,越是要区别对待。
5,连贯性。意思是,不要一遍一遍、一轮一轮地发同一封开发信,发几次就被拉黑了。很多新手看到客户不回复,那就再次复制粘贴,再发一次,结果肯定是拉黑,不拉黑留着过年吗?只要你确定你开发的是对的人,那么就要连续性的开发他。举个例子,第一封开发信是开门见山地介绍产品,或者确认他的需求;第二封就要不重样,发个产品优势表,来个小视频展示性能等。再不回复,打电话确认下,的确是有需求的,那就继续吧,一般是会被你吸引住的。
6,最基本的:字体不要花里胡哨、格式不要乱七八糟、签名不要五颜六色、链接不要到处都是、附件不要太大、内容不要太冗杂。这些是基本的注意事项,学好了再进行下一步。
暂时想到的是这些,后期想到的会再更新。
你们有什么好的想法呢?有没有新的技巧可以分享的?欢迎留言,大家一起学习,一起成长。
<我是“小G外贸源”,欢迎关注我。有问题可以留言,我会及时回复的>
用爬虫技术能做到哪些有趣的事情?
看到这个问题必须来怒答一波~用python爬虫爬便宜机票了解一下?
喜欢旅行又怕吃土?让Python来爬取最便宜机票吧!图源:
videoblocks.com
你喜欢旅行吗?
这个问题通常会得到一个肯定的答案,随后引出一两个有关之前冒险经历的故事。大多数人都认为旅行是体验新文化和开阔视野的好方法。但如果问题是“你喜欢搜索机票的过程吗?”也许话题就到此为止了……
可事实上,便宜的机票往往也很重要!本文将尝试构建一个网络爬虫,该爬虫对特定目的地运行并执行带有浮动日期(首选日期前后最多三天)的航班价格搜索。它会将结果保存为excel文件并发送一封包含快速统计信息的电子邮件。显然,这个爬虫的目的就是帮助我们找到最优惠的价格!
你可以在服务器上运行脚本(一个简单的Raspberry Pi就可以),每天运行一到两次。结果会以邮件形式发送,建议将excel文件存入Dropbox文件夹,以便随时随地查看。
因为爬虫以“浮动日期”进行搜索,所以它会搜索首选日期前后最多三天的航班信息。尽管该脚本一次仅运行一对目的地,但可以很容易地改写该爬虫使其每个循环运行多个目的地。最终甚至可能找到一些错误票价...那会很有意思!
另一个爬虫某种意义上来讲,网络爬取是互联网“工作”的核心。
也许你认为这是一个十分大胆的说法,但谷歌就是从拉里·佩奇用Java和Python构建的网络爬虫开始的。爬虫不断地爬取信息,整个互联网都在试图为所有问题提供最佳的可能答案。网络爬取有不计其数的应用程序,即使更喜欢数据科学中的其他分支,你仍需要一些爬取技巧以获得数据。
这里用到的一些技术来自于最近新的一本佳作《Python网络数据采集》,书中包含与网络爬取相关的所有内容,并提供了大量简例和实例。甚至有一个特别有意思的章节,讲述如何解决验证码检验的问题。
Python的拯救第一个挑战就是选择爬取信息的平台,本文选择了客涯(Kayak)。我们试过了Momondo, 天巡(Skyscanner), 亿客行(Expedia)和其它一些网站,但是这些网站上的验证码特别变态。
在那些“你是人类吗?”的验证中,尝试了多次选择交通灯、十字路口和自行车后,客涯似乎是最好的选择,尽管短时间内加载太多页面它会跳出安全检查。
我们设法让机器人每4到6个小时查询一次网站,结果一切正常。虽然说不定哪个部分偶尔会出点小问题,但是如果收到验证码,既可以手动解决问题后启动机器人,也可以等待几小时后的自动重启。
如果你是网络爬取新手,或者不知道为何有些网站花费很大力气阻止网络爬取,那么为构建爬虫写下第一行代码前,你一定要多加努力。
谷歌的“网络爬取规范”:
http://lmgtfy.com/?q=web+scraping+etiquette
系紧安全带...导入并打开Chrome浏览器标签页后,会定义一些循环中会用到的函数。这个架构的构思大概是这样的:
· 一个函数用于启动机器人程序,表明想要搜索的城市和日期。
· 这个函数获得首轮搜索结果,按“最佳”航班排序,然后点击“加载更多结果”。
· 另一个函数会爬取整个页面,并返回一个dataframe数据表。
· 随后重复步骤2和步骤3,得出按“价格”和“航行时间”排序的结果。
· 发送一封简要总结价格(最低价和平均价)的邮件,并将带有这三种排序类型的dataframe数据表保存为一份excel文件。
· 以上所有步骤会在循环中重复,每X小时运行一次。
每个Selenium项目都以一个网页驱动器开始。我们使用Chromedriver驱动器,但还有其它选择。PhantomJS和Firefox也很受欢迎。下载Chromedriver后,将其置于一个文件夹中即可。第一行代码会打开一个空白Chrome标签页。
from time import sleep, strftime
from random import randint
import pandas as pd
from selenium import webdriver
from selenium.webdriver.common.keys import Keys
import smtplib
from email.mime.multipart import MIMEMultipart
# Change this to your own chromedriver path!
chromedriver_path = 'C:/{YOUR PATH HERE}/chromedriver_win32/chromedriver.exe'
driver = webdriver.Chrome(executable_path=chromedriver_path) # This will open the Chrome window
sleep(2)
这些是将用于整个项目的包。使用randint函数令机器人在每次搜索之间随机睡眠几秒钟。这对任何一个机器人来说都是必要属性。如果运行前面的代码,应该打开一个Chrome浏览器窗口,机器人会在其中导航。
一起来做一个快速测试:在另一个窗口上访问客涯网(http://kayak.com),选择往返城市和日期。选择日期时,确保选择的是“+-3天”。由于在编写代码时考虑到了结果页面,所以如果只想搜索特定日期,很可能需要做一些微小的调整。
点击搜索按钮在地址栏获取链接。它应该类似于下面所使用的链接,将变量kayak定义为url,并从网页驱动器执行get方法,搜索结果就会出现。
无论何时,只要在几分钟内使用get命令超过两到三次,就会出现验证码。实际上可以自己解决验证码,并在下一次验证出现时继续进行想要的测试。从测试来看,第一次搜索似乎一直没有问题,所以如果想运行这份代码,并让它在较长的时间间隔后运行,必须解决这个难题。你并不需要十分钟就更新一次这些价格,对吧?
每个XPath都有陷阱到目前为止,已经打开了一个窗口,获取了一个网站。为了开始获取价格和其他信息,需要使用XPath或CSS选择器,我们选择了XPath。使用XPath导航网页可能会令人感到困惑,即使使用从inspector视图中直接使用“复制XPath”,但这不是获得所需元素的最佳方法。有时通过“复制XPath”这个方法获得的链接过于针对特定对象,以至于很快就失效了。《Python网络数据采集》一书很好地解释了使用XPath和CSS选择器导航的基础知识。
接下来,用Python选择最便宜的结果。上面代码中的红色文本是XPath选择器,在网页上任意一处右键单击选择“inspect”就可以看到它。在想要查看代码的位置,可以再次右键单击选择“inspect”。
为说明之前所观察到的从“inspector”复制路径的缺陷,请参考以下差异:
1 # This is what the copymethod 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/span
2 # This is what I used todefine the “Cheapest” buttoncheap_results= ‘//a[@data-code = “price”]’
第二种方法的简洁性清晰可见。它搜索具有data-code等于price属性的元素a。第一种方法查找id等于wtKI-price_aTab的元素,并遵循第一个div元素和另外四个div和两个span。这次……会成功的。现在就可以告诉你,id元素会在下次加载页面时更改。每次页面一加载,字母wtKI会动态改变,所以只要页面重新加载,代码就会失效。花些时间阅读XPath,保证你会有收获。
不过,使用复制的方法在不那么“复杂”的网站上工作,也是很好的!
基于以上所展示的内容,如果想在一个列表中以几个字符串的形式获得所有搜索结果该怎么办呢?其实很简单。每个结果都在一个对象中,这个对象的类是“resultWrapper”。获取所有结果可以通过像下面这样的for循环语句来实现。如果你能理解这一部分,应该可以理解接下来的大部分代码。它基本上指向想要的结果(结果包装器),使用某种方式(XPath)获得文本,并将其放置在可读对象中(首先使用flight_containers,然后使用flight_list)。
前三行已展示在图中,并且可以清楚地看到所需的内容,但是有获得信息的更优选择,需要逐一爬取每个元素。
准备起飞吧!最容易编写的函数就是加载更多结果的函数,所以代码由此开始。为了在不触发安全验证的前提下最大化所获取的航班数量,每次页面显示后,单击“加载更多结果”。唯一的新内容就是所添加的try语句,因为有时按钮加载会出错。如果它对你也有用,只需在前面展示的start_kayak函数中进行简要注释。
# Load more results to maximize the scraping
def load_more():
try:
more_results = '//a[@class = “moreButton”]'
driver.find_element_by_xpath(more_results).click()
# Printing these notes during the program helps me quickly check what it is doing
print('sleeping…..')
sleep(randint(45,60))
except:
pass
现在,经过这么长的介绍,已经准备好定义实际爬取页面的函数。
我们编译了下一个函数page_scrape中的大部分元素。有时这些元素会返回列表插入去程信息和返程信息之间。这里使用了一个简单的办法分开它们,比如在第一个 section_a_list和section_b_list变量中,该函数还返回一个flight_df数据表。所以可以分离在不同分类下得到的结果,之后再把它们合并起来。
def page_scrape():
“““This function takes care of the scraping part”““
xp_sections = '//*[@class=“section duration”]'
sections = driver.find_elements_by_xpath(xp_sections)
sections_list = [value.text for value in sections]
section_a_list = sections_list[::2] # This is to separate the two flights
section_b_list = sections_list[1::2] # This is to separate the two flights
# if you run into a reCaptcha, you might want to do something about it
# you will know there's a problem if the lists above are empty
# this if statement lets you exit the bot or do something else
# you can add a sleep here, to let you solve the captcha and continue scraping
# i'm using a SystemExit because i want to test everything from the start
if section_a_list == []:
raise SystemExit
# I'll use the letter A for the outbound flight and B for the inbound
a_duration = []
a_section_names = []
for n in section_a_list:
# Separate the time from the cities
a_section_names.append(''.join(n.split()[2:5]))
a_duration.append(''.join(n.split()[0:2]))
b_duration = []
b_section_names = []
for n in section_b_list:
# Separate the time from the cities
b_section_names.append(''.join(n.split()[2:5]))
b_duration.append(''.join(n.split()[0:2]))
xp_dates = '//div[@class=“section date”]'
dates = driver.find_elements_by_xpath(xp_dates)
dates_list = [value.text for value in dates]
a_date_list = dates_list[::2]
b_date_list = dates_list[1::2]
# Separating the weekday from the day
a_day = [value.split()[0] for value in a_date_list]
a_weekday = [value.split()[1] for value in a_date_list]
b_day = [value.split()[0] for value in b_date_list]
b_weekday = [value.split()[1] for value in b_date_list]
# getting the prices
xp_prices = '//a[@class=“booking-link”]/span[@class=“price option-text”]'
prices = driver.find_elements_by_xpath(xp_prices)
prices_list = [price.text.replace('$','') for price in prices if price.text != '']
prices_list = list(map(int, prices_list))
# the stops are a big list with one leg on the even index and second leg on odd index
xp_stops = '//div[@class=“section stops”]/div[1]'
stops = driver.find_elements_by_xpath(xp_stops)
stops_list = [stop.text[0].replace('n','0') for stop in stops]
a_stop_list = stops_list[::2]
b_stop_list = stops_list[1::2]
xp_stops_cities = '//div[@class=“section stops”]/div[2]'
stops_cities = driver.find_elements_by_xpath(xp_stops_cities)
stops_cities_list = [stop.text for stop in stops_cities]
a_stop_name_list = stops_cities_list[::2]
b_stop_name_list = stops_cities_list[1::2]
# this part gets me the airline company and the departure and arrival times, for both legs
xp_schedule = '//div[@class=“section times”]'
schedules = driver.find_elements_by_xpath(xp_schedule)
hours_list = []
carrier_list = []
for schedule in schedules:
hours_list.append(schedule.text.split('\n')[0])
carrier_list.append(schedule.text.split('\n')[1])
# split the hours and carriers, between a and b legs
a_hours = hours_list[::2]
a_carrier = carrier_list[1::2]
b_hours = hours_list[::2]
b_carrier = carrier_list[1::2]
cols = (['Out Day', 'Out Time', 'Out Weekday', 'Out Airline', 'Out Cities', 'Out Duration', 'Out Stops', 'Out Stop Cities',
'Return Day', 'Return Time', 'Return Weekday', 'Return Airline', 'Return Cities', 'Return Duration', 'Return Stops', 'Return Stop Cities',
'Price'])
flights_df = pd.DataFrame({'Out Day': a_day,
'Out Weekday': a_weekday,
'Out Duration': a_duration,
'Out Cities': a_section_names,
'Return Day': b_day,
'Return Weekday': b_weekday,
'Return Duration': b_duration,
'Return Cities': b_section_names,
'Out Stops': a_stop_list,
'Out Stop Cities': a_stop_name_list,
'Return Stops': b_stop_list,
'Return Stop Cities': b_stop_name_list,
'Out Time': a_hours,
'Out Airline': a_carrier,
'Return Time': b_hours,
'Return Airline': b_carrier,
'Price': prices_list})[cols]
flights_df['timestamp'] = strftime(“%Y%m%d-%H%M”) # so we can know when it was scraped
return flights_df
尽量让这些名字容易理解。记住变量a表示旅行的去程信息,变量b表示旅行的返程信息。接下来说说下一个函数。
等等,还有什么吗?截至目前,已经有了一个能加载更多结果的函数和一个能爬取其他结果的函数。本可以在此结束这篇文章,而你可以自行手动使用这些函数,并在浏览的页面上使用爬取功能。但是前文提到给自己发送邮件和一些其他信息的内容,这都包含在接下来的函数start_kayak中。
它要求填入城市名和日期,并由此打开一个kayak字符串中的地址,该字符串直接跳转到“最佳”航班结果排序页面。第一次爬取后,可以获取价格的顶部矩阵,这个矩阵将用于计算平均值和最小值,之后和客涯(Kayak)的预测结果(页面左上角)一同发送到邮件中。这是单一日期搜索时可能导致错误的原因之一,因其不包含矩阵元素。
def start_kayak(city_from, city_to, date_start, date_end):
“““City codes it's the IATA codes!
Date format YYYY-MM-DD”““
kayak = ('https://www.kayak.com/flights/' + city_from + '-' + city_to +
'/' + date_start + '-flexible/' + date_end + '-flexible?sort=bestflight_a')
driver.get(kayak)
sleep(randint(8,10))
# sometimes a popup shows up, so we can use a try statement to check it and close
try:
xp_popup_close = '//button[contains(@id,”dialog-close”) and contains(@class,”Button-No-Standard-Style close “)]'
driver.find_elements_by_xpath(xp_popup_close)[5].click()
except Exception as e:
pass
sleep(randint(60,95))
print('loading more.....')
# load_more()
print('starting first scrape.....')
df_flights_best = page_scrape()
df_flights_best['sort'] = 'best'
sleep(randint(60,80))
# Let's also get the lowest prices from the matrix on top
matrix = driver.find_elements_by_xpath('//*[contains(@id,”FlexMatrixCell”)]')
matrix_prices = [price.text.replace('$','') for price in matrix]
matrix_prices = list(map(int, matrix_prices))
matrix_min = min(matrix_prices)
matrix_avg = sum(matrix_prices)/len(matrix_prices)
print('switching to cheapest results…..')
cheap_results = '//a[@data-code = “price”]'
driver.find_element_by_xpath(cheap_results).click()
sleep(randint(60,90))
print('loading more…..')
# load_more()
print('starting second scrape…..')
df_flights_cheap = page_scrape()
df_flights_cheap['sort'] = 'cheap'
sleep(randint(60,80))
print('switching to quickest results…..')
quick_results = '//a[@data-code = “duration”]'
driver.find_element_by_xpath(quick_results).click()
sleep(randint(60,90))
print('loading more…..')
# load_more()
print('starting third scrape…..')
df_flights_fast = page_scrape()
df_flights_fast['sort'] = 'fast'
sleep(randint(60,80))
# saving a new dataframe as an excel file. the name is custom made to your cities and dates
final_df = df_flights_cheap.append(df_flights_best).append(df_flights_fast)
final_df.to_excel('search_backups//{}_flights_{}-{}_from_{}_to_{}.xlsx'.format(strftime(“%Y%m%d-%H%M”),
city_from, city_to,
date_start, date_end), index=False)
print('saved df…..')
# We can keep track of what they predict and how it actually turns out!
xp_loading = '//div[contains(@id,”advice”)]'
loading = driver.find_element_by_xpath(xp_loading).text
xp_prediction = '//span[@class=“info-text”]'
prediction = driver.find_element_by_xpath(xp_prediction).text
print(loading+'\n'+prediction)
# sometimes we get this string in the loading variable, which will conflict with the email we send later
# just change it to “Not Sure” if it happens
weird = '¯\\_(ツ)_/¯'
if loading == weird:
loading = 'Not sure'
username = 'YOUREMAIL@hotmail.com'
password = 'YOUR PASSWORD'
server = smtplib.SMTP('smtp.outlook.com', 587)
server.ehlo()
server.starttls()
server.login(username, password)
msg = ('Subject: Flight Scraper\n\n\
Cheapest Flight: {}\nAverage Price: {}\n\nRecommendation: {}\n\nEnd of message'.format(matrix_min, matrix_avg, (loading+'\n'+prediction)))
message = MIMEMultipart()
message['From'] = 'YOUREMAIL@hotmail.com'
message['to'] = 'YOUROTHEREMAIL@domain.com'
server.sendmail('YOUREMAIL@hotmail.com', 'YOUROTHEREMAIL@domain.com', msg)
print('sent email…..')
虽然没有使用Gmail账户测试发送邮件,但是可以搜索到很多的替代方法,前文提到的那本书中也有其他方法来实现这一点。如果已有一个Hotmail账户,只要替换掉个人的详细信息,它就会开始工作了。
如果想探索脚本的某一部分正在做什么,可以将脚本复制下来并在函数外使用它。这是彻底理解它的唯一方法。
利用刚才创造的一切在这些步骤之后,还可以想出一个简单的循环来使用刚创造的函数,同时使其持续运行。完成四个“花式”提示,写下城市和日期(输入)。因为测试时不想每次都输入这些变量,需要的时候可以使用以下这个清楚的方式进行替换。
如果已经做到了这一步,恭喜你!改进还有很多,比如与Twilio集成,发送文本消息而不是邮件。也可以使用VP*或更加难懂的方式同时从多个服务器上研究搜索结果。还有就是验证码的问题,验证码会时不时地跳出来,但对此类问题还是有解决办法的。不过,能走到这里已经是有很牢固的基础了,你可以尝试添加一些额外的要素。
使用脚本运行测试的示例
留言 点赞 关注
我们一起分享AI学习与发展的干货
欢迎关注全平台AI垂类自媒体 “读芯术”