爬取携程网机票价格并提供搜索功能

要爬取的数据是最近一段时间的飞机航班的最低价,并提供搜索功能。
利用谷歌浏览器的检查来获取最近一段时间飞机航班最低价json数据的url。
爬取携程网机票价格并提供搜索功能_第1张图片
打开之后:
爬取携程网机票价格并提供搜索功能_第2张图片
注意这里我们并不能用json模块将数据转换为json格式。如果转换为json格式会造成:

不能获取价格,日期是变化的,因此如果要用text.get('Prices').get('date')获取价格是不可能的。

那么只能用正则表达式分别匹配日期和价格,构造键值对,日期为键,价格为值:

'''
    L获取日期,L2获取价格。价格在匹配时会把2017以及2018也匹配到,因此删掉
    '''
    L = re.findall(r'[0-9]{4}\-[0-9]{2}\-[0-9]{2}', lowerprice_html)
    L1 = re.findall(r'\d{3,4}', lowerprice_html)
    L2 = []
    min = 500
    '''
    设置一个最小价格
    '''
    for i in range(len(L1)):
        if int(L1[i]) == 2017 or int(L1[i]) == 2018:
            pass
        else:
            L2.append(L1[i])
    '''
    构造键值对
    '''
    for i in range(len(L)):
        InsertDict(D2, L[i], L2[i])
    '''
    爬取的价格与min值进行比较,如果比min的值小,更新min的值
    '''
    for k in D2:
        if int(D2[k]) < int(min):
            min = D2[k]
        else:
            pass
    '''
    获取日期
    '''
    for k in D2:
        if D2[k] == min:
            print('最低票价为: %s 日期为: %s' %(D2[k], k))
            return k

这样便获取了最低票价以及日期。
如何提供搜索功能?
观察存放最低票价json数据的url:
http://flights.ctrip.com/domestic/ajax/Get90DaysLowestPrice?dcity=WUH&acity=BJS&ddate=2017-10-26&searchType=S&isDirect=T&r=0.8178801383025491
可以看到出发地武汉被编码成了WUH并赋值给了dcity,目的地北京被编码成了BJS并赋值给了acity,日期被赋值给了ddate。
如果想要提供搜索功能,把想要搜索的行程的出发地,目的地,日期分别赋值给dcity,acity,ddate。
但是携程网对城市缩写有它自己的命名方式。比如北京的缩写被命名了BSJ,武汉的缩写被命名了WUH。并不是简单地对拼音进行缩写。
幸运的是,携程网对于每个城市以及携程自己定义的城市名缩写都放在了一个js文件中。
爬取携程网机票价格并提供搜索功能_第3张图片
打开文件:
爬取携程网机票价格并提供搜索功能_第4张图片
看着挺像json格式,其实并不是。因此要用正则表达式把城市名以及城市名缩写(如北京(BJS)提取出来:

s = re.findall(r'[\u4e00-\u9fa5]+\([A-Z]+\)', citycode_html)
'''
    举个例子,例如北京(BJS)
    字符串替代功能
    s0 = ['北京', 'BJS)']
    s1 = '北京'
    s2 = 'BJS'
    s1为键,s2为值构建字典
    '''
    for i in range(len(s)):
        s0 = s[i].split('(')
        s1 = s0[0]
        s2 = s0[1].replace(')', '')
        Insertict(D1, s1, s2)

这样就把城市名以及城市名缩写构造成了字典,方便进行搜索。

def GetCitycode(original_city, D):
    for k in D:
        if original_city == k:
            return D[k]
        else:
            pass

搜索完成后,就要拼接url了,把dcity,acity,ddate换成我们想要搜索的城市的缩写以及日期就行了。

import re
import urllib.request
import json

def InsertDict(D, key, value):
    D.setdefault(key)
    D[key] = value

def GetHtml(url):
    response = urllib.request.urlopen(url)
    text = response.read().decode('gbk')
    return text

def GetDict(s, D1):
    for i in range(len(s)):
        s0 = s[i].split('(')
        s1 = s0[0]
        s2 = s0[1].replace(')', '')
        InsertDict(D1, s1, s2)


def GetCitycode(original_city, D):
    for k in D:
        if original_city == k:
            return D[k]
        else:
            pass

def UrlJoin(original_city_code, target_city_code, t):
    return 'http://flights.ctrip.com/domestic/ajax/Get90DaysLowestPrice?dcity=%s&acity=%s&ddate=%s&searchType=S&r=0.18035678380179632' % (original_city_code, target_city_code, t)

def GetLowestprice(lowerprice_html, D2):
    data = json.loads(lowerprice_html)
    L = re.findall(r'[0-9]{4}\-[0-9]{2}\-[0-9]{2}', lowerprice_html)
    L1 = re.findall(r'\d{3,4}', lowerprice_html)
    L2 = []
    min = 1500
    for i in range(len(L1)):
        if int(L1[i]) == 2017 or int(L1[i]) == 2018:
            pass
        else:
            L2.append(L1[i])
    for i in range(len(L)):
        InsertDict(D2, L[i], L2[i])
    for k in D2:
        if int(D2[k]) < int(min):
            min = D2[k]
        else:
            pass
    for k in D2:
        if D2[k] == min:
            print('最低票价为: %s 日期为: %s' %(D2[k], k))
            return k

D1 = {}
D2 = {}
get_citycode_url = 'http://webresource.c-ctrip.com/code/cquery/resource/address/flight/flight_new_poi_gb2312.js?releaseno=?CR_2016_03_07_22_18_26'
citycode_html = GetHtml(get_citycode_url)
s = re.findall(r'[\u4e00-\u9fa5]+\([A-Z]+\)', citycode_html)
GetDict(s, D1)
original_city = input('请输入出发地:')
target_city = input('请输入目的地:')
t = input('请输入时间:')
original_city_code = GetCitycode(original_city, D1)
target_city_code = GetCitycode(target_city, D1)
get_lowerprice_url = UrlJoin(original_city_code, target_city_code, t)
print(get_lowerprice_url)
lowerprice_html = GetHtml(get_lowerprice_url)
k = GetLowestprice(lowerprice_html, D2)
target_url = 'http://flights.ctrip.com/booking/%s-%s-day-1.html?DDate1=%s' % (original_city_code, target_city_code, k)
print(target_url)

运行结果:

请输入出发地:上海
请输入目的地:北京
请输入时间:2017-10-26
http://flights.ctrip.com/domestic/ajax/Get90DaysLowestPrice?dcity=SHA&acity=BJS&ddate=2017-10-26&searchType=S&r=0.18035678380179632
最低票价为: 250 日期为: 2017-12-02
http://flights.ctrip.com/booking/SHA-BJS-day-1.html?DDate1=2017-12-02

对于拼接完的url,我们可以利用Selenium库进行打开。有些可能会搜索不到,并且数据变化的比较快,所以当看到网页上的价钱不一样时也不要惊讶。

你可能感兴趣的:(python爬虫)