
初学 python 。
近期公司由于业务原因,需要想办法获取到携程与去哪儿的机票信息。 于是我尝试用 python+urllib 对这两个网站上的信息进行抓取。
去哪儿的爬虫代码如下:(初学 python 。代码有很多不合理之处。望海涵。)
# -*- coding:utf-8 -*- import urllib from urllib import request class QunaerSpider: __query_flights_base_url = 'http://flight.qunar.com/twelli/longwell?' __user_agent = 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/51.0.2704.103' __referer_base_url = 'http://flight.qunar.com/site/interroundtrip_compare.htm?' __referer_end_url = '&from=fi_re_search&lowestPrice=null&isInter=true&favoriteKey=&showTotalPr=null' def create_flights_query_url(self, from_city, from_date, to_city, to_date): """根据用户传参,返回组装好的机票请求用 String 格式的 url 数据 Args: from_city: 出发城市 from_date: 出发日期 to_city: 抵达城市 to_date: 抵达日期 Returns: 返回组装好的机票请求用 String 格式的 url 数据. Raise: None """ from_city_encoded = urllib.request.quote(from_city.encode('utf-8')) from_date_encoded = urllib.request.quote(from_date) to_city_encoded = urllib.request.quote(to_city.encode('utf-8')) to_date_encoded = urllib.request.quote(to_date) url = QunaerSpider.__query_flights_base_url # 初始化参数对象 parameter_dict = {} parameter_dict['from'] = 'qunarindex' parameter_dict['fromCity'] = from_city_encoded parameter_dict['fromDate'] = from_date_encoded parameter_dict['isInter'] = 'true' parameter_dict['prePay'] = 'true' parameter_dict['locale'] = 'zh' parameter_dict['mergeFlag'] = '0' parameter_dict['nextNDays'] = '0' parameter_dict['op'] = '1' parameter_dict['reset'] = 'true' parameter_dict['searchLangs'] = 'zh' parameter_dict['searchType'] = 'RoundTripFlight' parameter_dict['toCity'] = to_city_encoded parameter_dict['toDate'] = to_date_encoded parameter_dict['version'] = 'thunder' parameter_dict['http://www.travelco.com/searchArrivalAirport'] = to_city_encoded parameter_dict['http://www.travelco.com/searchDepartureAirport'] = from_city_encoded parameter_dict['http://www.travelco.com/searchDepartureTime'] = from_date_encoded parameter_dict['http://www.travelco.com/searchReturnTime'] = to_date_encoded # f+时间戳 parameter_dict['xd'] = 'f1469358871776' parameter_dict['www'] = 'true' parameter_dict['wyf'] = '0P8HfQ5%2F%2FYA%2FWldSERAyfudSERU0dUd0ERPj%3D%3D%3D%3D%7C1441321882698' parameter_dict['departureCity'] = from_city_encoded parameter_dict['arrivalCity'] = to_city_encoded parameter_dict['departureDate'] = from_date_encoded parameter_dict['returnDate'] = to_date_encoded # token.加不加暂时看不出来什么影响 parameter_dict['_token'] = '6455' # 拼装 query_rul for k, v in parameter_dict.items(): url = url + '&' + k + '=' + v print('请求字符串为\n%s' % url) return url def create_referer_url(self, from_city, from_date, to_city, to_date): from_city_encoded = urllib.request.quote(from_city.encode('utf-8')) from_date_encoded = urllib.request.quote(from_date) to_city_encoded = urllib.request.quote(to_city.encode('utf-8')) to_date_encoded = urllib.request.quote(to_date) url = QunaerSpider.__referer_base_url # 初始化参数对象 parameter_dict = {} parameter_dict['from'] = 'qunarindex' parameter_dict['fromCity'] = from_city_encoded parameter_dict['fromDate'] = from_date_encoded parameter_dict['toCity'] = to_city_encoded parameter_dict['toDate'] = to_date_encoded # TODO 暂时写死 parameter_dict['fromCode'] = 'CTU' parameter_dict['toCode'] = 'TYO' # 拼装 query_rul for k, v in parameter_dict.items(): url = url + '&' + k + '=' + v url += QunaerSpider.__referer_end_url print('Referer 为\n%s' % url) return url def query_flights(self, url, referer_url): """根据用户传参,返回组装好的机票请求用 String 格式的 url 数据 Args: url: 机票接口 Returns: 封装好的机票数据 Raise: None """ req = request.Request(url) req.add_header('Host', 'flight.qunar.com') req.add_header('Accept', '*/*') req.add_header('User-Agent', unaerSpider.__user_agent) req.add_header('Connection', 'keep-alive') req.add_header('Accept-Encoding', 'gzip, deflate, sdch') req.add_header('Content-Type', 'application/json') req.add_header('Accept-Language', 'zh-CN,zh;q=0.8') req.add_header('Referer', referer_url) with request.urlopen(req) as f: # 读取数据 data = f.read() print(f.status, f.reason) print('Data:', data.decode('utf-8')) qunaerSpider = QunaerSpider() referer_url = qunaerSpider.create_referer_url('成都', '2016-08-20', '东京', '2016-09-11') url = qunaerSpider.create_flights_query_url('成都', '2016-08-20', '东京', '2016-09-11') qunaerSpider.query_flights(url, referer_url) 去哪儿网遇到的问题
爬虫返回的信息为
200 OK Data: {isLimit:true}
使用同样的 url ,通过浏览器却能正常访问。想知道原因以及修正办法。
携程网遇到的问题
携程网的爬虫代码还没开始写。不过大概分析了下,携程网是 post 请求。 并且每次请求时会验证“ SearchKey ”与“ TransNo ”。关于这两个参数,有有经验的同学知道是在哪里,通过什么方式获取到的吗?附上携程的请求参数列表。
{ "FlightWay": "D", "SegmentList": [{ "DCityCode": "CTU", "ACityCode": "TYO", "DCity": "Chengdu|成都(CTU)|28|CTU|480", "ACity": "Tokyo|东京(TYO)|228|TYO|540", "DepartDate": "2016-8-1" }, { "DCityCode": "TYO", "ACityCode": "CTU", "DCity": "Tokyo|东京(TYO)|228|TYO|480", "ACity": "Chengdu|成都(CTU)|28|CTU|540", "DepartDate": "2016-9-10" }], "TransferCityID": 0, "Quantity": 1, // 每次请求发生变化,携程会验证此 key "TransNo": "5516072421000033701", "SearchRandomKey": "", "IsAsync": 1, "RecommendedFlightSwitch": 1, // 每次请求发生变化。携程会验证此 key "SearchKey": "BEBFB6F8C0C56B8561A9B435AE822DF4D499B75C2FFA74D481318741A7F9537EFB59C5327342DE0D1A11D1E626A03C6C843FE6E311D4819F", "MultiPriceUnitSwitch": 1, "TransferCitySwitch": false, "EngineScoreABTest": "B", "AdjacentDateKey": "", "SearchStrategySwitch": 1, "MaxSearchCount": 3, "TicketRemarkSwitch": 1, "RowNum": "1500", "TicketRemarkChannels": ["GDS-WS", "ZY-WS"], "AddSearchLogOneByOne": true, "TFAirlineQTE": "AA", "IsWifiPackage": 0 } 谢谢各位。
1 sivacohan PRO 公司业务的原因,我建议你别研究了。 去哪得二三十人在研究爬虫和反爬虫。 给你 islimit 这算给面子了,告诉你,小伙子要知难而退。 去哪反扒的大招是接口正常返回,但数据都是错的。。。 |
2 xxwar 2016-07-24 22:58:45 +08:00 楼上真是大招,无解 |
3 GlobalNPC 2016-07-24 23:04:58 +08:00 via iPhone 携程有白名单,谢谢。 |
4 v2gba 2016-07-24 23:21:28 +08:00 大招有点刺激啊 |
5 linuxchild 2016-07-24 23:32:36 +08:00 via Android 长见识啦 |
6 mikulch OP 最神奇的是这两家网站,国际航班和国内航班的爬取难度完全不同 国内的航班很轻松就爬到信息了。 但是国际航班各种反爬手段。。。。。 |
7 Jolly23 2016-07-25 02:41:55 +08:00 via iPhone 爬到的数据全是假的,人家玩你 |
8 20150517 2016-07-25 03:24:14 +08:00 via Android 我认识一个人,爬了携程去哪儿大量机票信息,应该有上 gb 数据,你公司就说出钱来买 |
9 wojiaodaxiaxia 2016-07-25 03:58:05 +08:00 http://www.v4.cc/News-1749172.html 这个视频有点意思,原链接找不到,带视频的只有这个,将就看下咯 |
10 wojiaodaxiaxia 2016-07-25 04:04:35 +08:00 @mikulch 上面那条是我的锅,花五毛补上 原链接:https://segmentfault.com/a/1190000005840672 视频:http://v.qq.com/x/page/j0308hykvot.html |
11 googlebot 2016-07-25 05:42:20 +08:00 via Android qunar 数据在实时变化,根本没爬的意义 |
12 redhatping 2016-07-25 08:11:19 +08:00 via iPhone 人家问代码的 |
13 rale 2016-07-25 08:31:28 +08:00 要爬机票的信息去各大航空公司官网,这才是源头, qunar , ctrip 只是相当于一个中介而已 |
14 holajamc 2016-07-25 08:58:30 +08:00 Selenium + PhantomJS 正儿八经开个浏览器~所以觉得楼上的问题应该不存在了~ |
15 manoon 2016-07-25 09:07:06 +08:00 via iPhone |
16 jugelizi 2016-07-25 10:25:14 +08:00 "初学 python 。 近期公司由于业务原因" 我就笑了 小伙子掉坑里了 |
18 est 2016-07-25 10:34:41 +08:00 唉。卧槽。协程和去哪儿其实他们本来就是爬别人的。就是自动化了航空公司的自动下单选座系统。 |
19 mornlight 2016-07-25 10:41:28 +08:00 如果是为了学习,建议换别的站点,果是业务需要,走别的路子。 这两家的反爬虫策略很恶心, PhantomJS 也没用。你以为你拿到了一堆数据,结果是真假数据混合在一起,偶尔还被携程的人嘲讽。 |
23 Weixiao0725 2016-07-25 12:57:10 +08:00 @manoon 正解,我一个同学就在中航信上班,他就是写接口给第三方调用获取航班信息的 |
24 manoon 2016-07-25 12:59:59 +08:00 @Weixiao0725 哈哈,说明我虽然老了,但记忆力是不错的。 |
25 krizex 2016-07-25 13:17:24 +08:00 https://github.com/krizex/ATP 我去年用 py 写的抓 qunar 上国内航班的数据,然而并没有觉得返回给我的数据是假的。 |
26 gimp 2016-07-25 13:32:00 +08:00 防爬有一个阈值的,当爬虫和真实用户没什么区别的时候,网站方是不敢塞给你假数据的。 |
29 shakespaces 2016-07-25 14:02:41 +08:00 via Android @cszhiyue 有反爬虫的,正常用户浏览肯定和爬虫获取有种种不同 |
30 cszhiyue 2016-07-25 14:07:06 +08:00 @shakespaces 用户的浏览行为完全可以伪造。种种不同可不可以举例一下。 |
31 shakespaces 2016-07-25 14:23:23 +08:00 via Android @cszhiyue 比如速度,你确实可以模拟用户几十秒几分钟获取一次,但是时间成本太高了吧。分布式又增加了服务器成本,不计成本确实能够完全模拟用户 |
33 cszhiyue 2016-07-25 14:34:32 +08:00 @shakespaces 大概理解了。速度不加以限制的话,频率过高,服务不是拒绝,而是以返回假数据这种形式来欺骗爬虫? 速度的话可以通过切换代理 ip 的形式。爬虫还是不能完全杜绝,反爬是提高爬虫的成本 |
34 KotiyaSanae 2016-07-25 14:46:11 +08:00 @mikulch 因为国际接口请求是收费的。而且不低。所以甄别是否是爬虫很重要。 |
35 mikulch OP @krizex 去哪儿的国内航班的数据倒是相对好抓一点,反爬措施和国际机票的不太一样。 我现在直接用 postman 请求去哪儿的国际机票 postman 的参数和浏览器设置成完全一样,反不回来数据。 但是用 postman 请求国内的机票就没问题。 |
36 realpg PRO 老老实实去航信买数据就是了…… |
37 killerv 2016-07-25 15:25:41 +08:00 就像楼上说的,反爬并不能完全杜绝,只是提高抓取成本。 |
38 krizex 2016-07-25 22:56:55 +08:00 @mikulch 我当时的需求就是抓下国内的航班看看价格趋势好买机票。国际的倒是没搞过,不过既然是国际航班了,为什么不用 google 的数据呢。每天前 50 次查询免费,搞个几千个账号应该能满足你每天的查询次数了吧? https://developers.google.com/qpx-express/v1/prereqs |
40 nightspirit 2016-07-26 16:02:09 +08:00 反爬虫趋势无法杜绝,如果设置的过滤条件过高,就会有误杀 |
41 bdbai 2016-08-01 19:03:03 +08:00 via Android 携程的两个 key 在查询页面顶部有写,但 searchkey 被 js 处理过。 |
42 bdbai 2016-08-06 00:02:42 +08:00 via Android append: 携程抓手机版无压力 |