到目前为止,我们有一个函数来加载更多的结果,还有一个函数来抓取这些结果。我可以在这里结束这篇文章,您仍然可以手动使用这些工具,并在您自己浏览的页面上使用抓取功能,但我确实提到了一些关于向您自己发送电子邮件和其他信息的内容!这都在下一个功能里面。
它要求你填写城市和日期。从那里,它将打开kayak字符串中的地址,该字符串直接进入“最佳”结果页排序。在第一次刮取之后,我顺利地得到了价格最高的矩阵。它将用于计算平均值和最小值,与Kayak的预测一起在电子邮件中发送(在页面中,它应该在左上角)。这是在单一日期搜索中可能导致错误的原因之一,因为那里没有矩阵元素。
1def start_kayak(city_from, city_to, date_start, date_end):
2"""City codes - it's the IATA codes!
3Date format - YYYY-MM-DD"""
4
5kayak = ('https://www.kayak.com/flights/' + city_from + '-' + city_to +
6'/' + date_start + '-flexible/' + date_end + '-flexible?sort=bestflight_a')
7driver.get(kayak)
8sleep(randint(8,10))
9
10# sometimes a popup shows up, so we can use a try statement to check it and close
11try:
12xp_popup_close = '//button[contains(@id,"dialog-close") and contains(@class,"Button-No-Standard-Style close ")]'
13driver.find_elements_by_xpath(xp_popup_close)[5].click()
14except Exception as e:
15pass
16sleep(randint(60,95))
17print('loading more.....')
18
19# load_more()
20
21print('starting first scrape.....')
22df_flights_best = page_scrape()
23df_flights_best['sort'] = 'best'
24sleep(randint(60,80))
25
26# Let's also get the lowest prices from the matrix on top
27matrix = driver.find_elements_by_xpath('//*[contains(@id,"FlexMatrixCell")]')
28matrix_prices = [price.text.replace('$','') for price in matrix]
29matrix_prices = list(map(int, matrix_prices))
30matrix_min = min(matrix_prices)
31matrix_avg = sum(matrix_prices)/len(matrix_prices)
32
33print('switching to cheapest results.....')
34cheap_results = '//a[@data-code = "price"]'
35driver.find_element_by_xpath(cheap_results).click()
36sleep(randint(60,90))
37print('loading more.....')
38
39# load_more()
40
41print('starting second scrape.....')
42df_flights_cheap = page_scrape()
43df_flights_cheap['sort'] = 'cheap'
44sleep(randint(60,80))
45
46print('switching to quickest results.....')
47quick_results = '//a[@data-code = "duration"]'
48driver.find_element_by_xpath(quick_results).click()
49sleep(randint(60,90))
50print('loading more.....')
51
52# load_more()
53
54print('starting third scrape.....')
55df_flights_fast = page_scrape()
56df_flights_fast['sort'] = 'fast'
57sleep(randint(60,80))
58
59# saving a new dataframe as an excel file. the name is custom made to your cities and dates
60final_df = df_flights_cheap.append(df_flights_best).append(df_flights_fast)
61final_df.to_excel('search_backups//{}_flights_{}-{}_from_{}_to_{}.xlsx'.format(strftime("%Y%m%d-%H%M"),
62city_from, city_to,
63date_start, date_end), index=False)
64print('saved df.....')
65
66# We can keep track of what they predict and how it actually turns out!
67xp_loading = '//div[contains(@id,"advice")]'
68loading = driver.find_element_by_xpath(xp_loading).text
69xp_prediction = '//span[@class="info-text"]'
70prediction = driver.find_element_by_xpath(xp_prediction).text
71print(loading+'\n'+prediction)
72
73# sometimes we get this string in the loading variable, which will conflict with the email we send later
74# just change it to "Not Sure" if it happens
75weird = '¯\\_(ツ)_/¯'
76if loading == weird:
77loading = 'Not sure'
78
79username = 'YOUREMAIL@hotmail.com'
80password = 'YOUR PASSWORD'
81
82server = smtplib.SMTP('smtp.outlook.com', 587)
83server.ehlo()
84server.starttls()
85server.login(username, password)
86msg = ('Subject: Flight Scraper\n\n\
87Cheapest Flight: {}\nAverage Price: {}\n\nRecommendation: {}\n\nEnd of message'.format(matrix_min, matrix_avg, (loading+'\n'+prediction)))
88message = MIMEMultipart()
89message['From'] = 'YOUREMAIL@hotmail.com'
90message['to'] = 'YOUROTHEREMAIL@domain.com'
91server.sendmail('YOUREMAIL@hotmail.com', 'YOUROTHEREMAIL@domain.com', msg)
92print('sent email.....')
我使用Outlook帐户(hotmail.com)测试了这一点。虽然我没有使用Gmail帐户来测试它来发送电子邮件,但是您可以搜索许多替代方法,我前面提到的那本书也有其他的方法来实现这一点。如果您已经有一个Hotmail帐户,那么您替换您的详细信息,它应该可以工作。
如果您想探索脚本的某些部分正在做什么,请复制它并在函数之外使用它。只有这样你才能完全理解。
在所有这些之后,我们还可以想出一个简单的循环来开始使用我们刚刚创建的函数并使它们保持忙碌。完成四个“花式”提示,让你实际写下城市和日期(输入)。因为当我们进行测试时,我们不希望每次都输入这些变量,在需要的时候用下面的显式方法替换它。
1city_from = input('From which city? ')
2city_to = input('Where to? ')
3date_start = input('Search around which departure date? Please use YYYY-MM-DD format only ')
4date_end = input('Return when? Please use YYYY-MM-DD format only ')
5
6# city_from = 'LIS'
7# city_to = 'SIN'
8# date_start = '2019-08-21'
9# date_end = '2019-09-07'
10
11for n in range(0,5):
12start_kayak(city_from, city_to, date_start, date_end)
13print('iteration {} was complete @ {}'.format(n, strftime("%Y%m%d-%H%M")))
14
15# Wait 4 hours
16sleep(60*60*4)
17print('sleep finished.....')
如果你做到了这一步,恭喜你!我能想到的改进有很多,比如与Twilio集成,向您发送文本消息而不是电子邮件。您还可以使用V**或更模糊的方法同时从多个服务器上研究搜索结果。有验证码的问题,可能会不时出现,但有解决这类问题的方法。我认为您在这里有一些非常可靠的基础,我鼓励您尝试添加一些额外的特性。也许您希望Excel文件作为附件发送。我总是欢迎建设性的反馈,所以请随时在下面发表评论。
使用脚本的测试运行示例
如果您想了解更多关于web抓取的知识,我强烈推荐您使用python进行web抓取。我真的很喜欢这些例子和对代码如何工作的清晰解释。
End