爬取深圳航空航线相关数据

最近在找工作,说多了都是泪,自己挺喜欢写爬虫的,所以想找一份爬虫的职业,无奈是转行并且学历大专并不够硬,以至现在还是没能如愿,爬取航空数据这是其中一家面试公司给的面试题,给了7天的时间去完成,用了三天的时间已经完成了,结果也已经交付了,再等通知,希望能过,不过感觉还是希望不大,只能继续加油了,写这份代码的时候走了不少弯路,所以写下这篇博客记录下来
1、目标地址:深圳航空机票预订页面http://www.shenzhenair.com/szair_B2C/flightsearch.action?hcType=DC&orgCity=%E5%8C%97%E4%BA%AC&orgCityCode=PEK&dstCity=%E6%B7%B1%E5%9C%B3&dstCityCode=SZX&orgDate=2019-03-08&dstDate=2019-03-08
在这里插入图片描述
从这个页面可以看到航班信息的数据,所有航班的价格都在所有价格里面,点开可以看到
2、我们查看一下网页源代码是没有任何我们要找的数据的,因为查询航班需要提交表单,提交表单常用的方式就是post,所以我们就可以判断这是通过异步加载出来的数据,具体的数据我就不找了,这是一个json格式的数据,里面的数据大家感兴趣可以自己找找
在这里插入图片描述
3、在network里面可以看到一个post方式传送的链接,打开之后可以看到每个航班的数据都在 flightInfoList 中
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
4、接下来我们分析这个网站的反爬机制,在每次刷新页面或者切换其他日期是在Cookie中的 PV对应的值 会 加 1,所以在程序中也需要在每次请求之后需要对这个值进行加1操作,初始值可以随意设置,建议20以内, 另外 Cookie有过期时间,时间过期之后需要更新程序中的Cookie,并且每隔一段时间之后,session也会过期,此时也需要更新Cookie值,并且Seeion更新之后,PV对应的值也会重 1 开始累加,最后还有一点,每次我们刷新页面时,会需要延迟一点时间,页面才会加载出来,此时就需要在程序里面请求一次最好睡眠一两秒的时间
在这里插入图片描述
6、再返回来看一下post方式提交的数据,在form_data里面可以看到,每次查看不同日期的数据时,日期也会随之改变,所以在程序里面,我用了time模块,读取了当前的日期并且格式化form_data日期的格式,每次请求时传递进去,响应完数据处理之后进行加1,为下一次请求赋值,这样就可以请求到不同日期的数据了(这还有个BUG,因为请求日期大于这个月最大日期后就会报错,如:20190332>20190331,这个bug大家可以自行解决,我暂时没做处理)
在这里插入图片描述
6、最后附上所有的代码
# coding=gbk

'''
反爬机制: 检测当前IP + 请求头 + cookie
    判断cookie:有过期时间, 过期后更新  self.AlteonP  self.sign_flight
    判断sessionid:sessionid过期 更新 整个cookies 或者 JSsessionid
    每请求一次  cookie中 PV值 加 1
'''
import requests, time, random, json,logging

class ShenZhenAir:
    def __init__(self):

        self.url = 'http://www.shenzhenair.com/szair_B2C/flightSearch.action'

        # 日期的请求时添加  并且方便下一次更新调用
        self.form_data = {
            'condition.orgCityCode': 'PEK',
            'condition.dstCityCode': 'SZX',
            'condition.hcType': 'DC',
        }
        # referer 信息也在请求时添加,需要更新 post 传递参数,User-Agent不能修改,因为User-agent绑定cookie+IP
        self.headers = {
            'Accept': 'application/json, text/javascript, */*; q=0.01',
            'Accept-Encoding': 'gzip, deflate',
            'Accept-Language': 'zh-CN,zh;q=0.9',
            'Content-Length': '129',
            'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8',
            'Host': 'www.shenzhenair.com',
            'Origin': 'http://www.shenzhenair.com',
            'Proxy-Connection': 'keep-alive',
            'X-Requested-With': 'XMLHttpRequest',
            'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.102 Safari/537.36',
        }
        # cookie值 值取到 PV: 因为每次请求需要 加1 操作
        self.cookie = '自己的cookie值pv:'

        # refer值 也需要拼接,所以只取到中间一部分 日期后面的部分在请求时拼接进去
        self.refer = 'http://www.shenzhenair.com/szair_B2C/flightsearch.action?orgCityCode=PEK&dstCityCode=SZX&orgDate='


    def getJson(self):
        # print(self.headers)
        n = 1
        p = 18
        n_time = time.localtime()
        base_time = int(time.strftime('%Y%m%d', n_time))
        try:
            while n<=7:
                # 时间更新用
                date = str(base_time)[0:4] + '-' + str(base_time)[4:6] + '-' + str(base_time)[6:]

                dstDate = base_time + 1
                conditiondstDate = str(dstDate)[0:4] + '-' + str(dstDate)[4:6] + '-' + str(dstDate)[6:]
                # 更新 传递的 data
                self.form_data['condition.orgDate'] = date
                self.form_data['condition.dstDate'] = conditiondstDate
                # 更新 请求头  信息
                self.headers['Referer'] = self.refer + date + '&hcType=DC'
                self.headers['Cookie'] = self.cookie + str(p)

                print('正在获取%s号信息' % date)
                # 发起请求获取数据
                res = requests.post(self.url, headers=self.headers, data=self.form_data)
                time.sleep(5)
                print(res.request.headers['Cookie'])
                # print(res.cookies)
                # res.encoding = 'utf-8'
                html = json.loads(res.text)
                print('==' * 30)

                # 对获取的数据进行解析
                self.parseJson(html)

                # 数值更新
                n += 1
                p += 1
                base_time += 1
                time.sleep(0.5)
        except json.decoder.JSONDecodeError:
            print('后续处理')

    def parseJson(self, html):
        '''
        对获取的 Json数据进行解析
        :param html:
        :return:
        '''
        if len(html):
            info = html['flightSearchResult']['flightInfoList']
            for i in info:
                flightno = i['flightNo']
                orgdate = i['orgDate']
                orgtime = i['orgTime']
                dsttime = i['dstTime']
                orgcitych = i['orgCityCH']
                dstcitych = i['dstCityCH']

                print('去程: '+orgcitych +'-'+dstcitych + ' '+'机型: {}, 起飞日期: {}, 起飞时间: {}, 落地时间: {}'.format(flightno, orgdate, orgtime, dsttime))
                classinfolist = i['classInfoList']
                for j in classinfolist:
                    class_type = j['classCode']
                    class_price = j['classPrice']
                    print(class_type + '舱' + ': ' + class_price + '元')
                print()
            time.sleep(0.5)
        else:
            print('抱歉,该日期无座位或航班')

    def main(self):
        self.getJson()

if __name__ == '__main__':
    app = ShenZhenAir()
    app.main()
7、注意:说一下我的一些经验,因为在爬取这个网站时,没特别注意cookie的值,所以,而且可能传递的参数也有问题,所以请求之后返回的数据只是html,并不是json数据,一开始我以为是数据加密了,所以就想着从公众号的接口获取数据,代码也写完了,但是最多也只能获取两天的数据,我还以为是反爬机制比较狠,所以通过更换IP来解决,但是更换IP之后还是没有解决,我又以为是IP不好用,又买了动态转发,结果还是不如意,最后没办法,还是回到最初静下心来去研究网页版的反爬机制,当我成功获取到连续的数据才发现自己真的有点傻,反爬机制原来就这么简单,我却走了这么多弯路,不够这次就当是对自己的一个教训了,以后还是能先研究明白网站的反爬机制,再去对症下药吧
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 202,723评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,080评论 2 379
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 149,604评论 0 335
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,440评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,431评论 5 364
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,499评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,893评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,541评论 0 256
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,751评论 1 296
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,547评论 2 319
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,619评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,320评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,890评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,896评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,137评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,796评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,335评论 2 342

推荐阅读更多精彩内容