Python 并发编程系列--2、并发方式的选择

上一篇直通车 Python 并发编程系列–1、浅谈GIL历史及对多线程的影响

前言

前面说了下GIL的历史,现在站在接受GIL的角度谈何时选择多线程、何时选择多进程的问题(不接受GIL那你用Jython呐2333)。

选择因素1–问题类型

简单的说,就是看你要解决问题属于什么类型。这块大体上分为两类–CPU密集型和I/O密集型,换句话说就是偏重于计算还是侧重输入输出。例如要进行科学计算,计算量很大,那就属于CPU密集型,因为对CPU的需求占据了主体。再比如写一个爬虫程序,其中大部分时间都花在从服务器读取数据的过程中,显然是I/O密集型。

选择因素2–多线程和多进程性能比对

关于性能比对,网上有很多比对多线程和多进程速度的例子,这里就不重复造轮子了。下面给出几个相关的链接,可以参考一下他们的测试结果。
这里直接给出多线程和多进程的对比结果:

  • 对于CPU密集型,效率关系:多进程>单进程(单线程)>多线程
  • 对于I/O密集型,效率关系:多线程>多进程>单进程(单线程)

    总结

    从以上结果不难看出,对于规模较大的问题,单进程(单线程)处理起来性能无法满足需要时就需要考虑并发了。CPU密集型的任务,用多进程;I/O密集型的任务,用多线程。

    下一篇直通车 Python 并发编程系列–3、多线程编程方法

Python 并发编程系列--1、浅谈GIL历史及对多线程的影响

前言

为了提高程序的运行速度,我们除了修改程序逻辑改善算法,另一个角度就是采取并发的策略。并发有两种,一种是进程的并发,另一种是线程的并发,两者有很多区别,最主要的区别:进程之间是无共享资源的,因而比较耗费内存资源,优点则是更好的安全性;而线程因为共享资源,所以相对于进程更加轻量级,缺点则是对共享数据的访问需要人为管理,即存在“线程安全”问题。

何为线程安全

线程安全是多线程编程里面的独有概念(从名字上也能看出来^_^),下面看一下wikipedia上面的解释:

Thread safety is a computer programming concept applicable in the context of multi-threaded programs. A piece of code is thread-safe if it functions correctly during simultaneous execution by multiple threads. In particular, it must satisfy the need for multiple threads to access the same shared data, and the need for a shared piece of data to be accessed by only one thread at any given time.

简言之,线程安全可以保证在多个线程同时执行的情况下程序可以正确执行,并且对于共享数据在任何时候只能有一个线程进行读取(我们知道产生线程死锁的一个必要条件就是互斥访问,这里面对于共享数据就是互斥访问的)。

如何保证线程安全

保证线程线程安全可以参照进程间对于临界资源的处理方式,加锁是比较简单的做法。为了做到线程安全,不同的编程语言采取不同的加锁方式,大体有两个级别的:细粒度的锁,仅在需要的时候才加,因为编程语言不知道你什么时候需要加锁,所以这个任务就要给编程人员去掌控,java就是采取这种策略,jython(Python 的java实现)也是采用的这个方式;粗粒度的锁,为了绝对的保证线程的安全,采取全局加锁的策略,这个由编程语言直接管理,编程人员不用操心,典型的是CPython(我们说的Python默认就是CPython)。简单的说前一种更安全,后一种更方便,作为一个手懒、饭都懒得吃的人,我比较喜欢后一种方式,把哪些琐碎的事交给编程语言去做吧。

Python的GIL

前面交代过了,正是由于全局的加锁的想法,CPython的作者(当然就是正统的Python的创造者)Guido在Python引入了GIL(Global Interpreter Lock)。每一个interperter进程,任何时候都只能有一个线程来执行,获得锁并使用资源。这种方式避免了多个线程的并发执行,因而保证了线程的安全。但是线程都无法并发执行了,那还叫多线程吗?⊙﹏⊙‖∣
所以对于GIL始终有两种声音:一种可以接受GIL(只是能接受,未必很喜欢),另一种认为应该去掉GIL。认为能接受的原因由两个:一、自从Python出现后,后面太多的模块都使用了Python的GIL来编写,一旦去掉GIL,这些模块都得重写,那些复杂的多线程逻辑得由程序员自己编写,代价很大;二、去掉GIL对于单线程程序会有性能的降低(在1999年就试过,移除了GIL导致单线程执行速度下降了2倍多)。认为该移除的原因主要也有两个:一、去掉GIL才能发挥多核处理器的优势。二、去掉GIL可以加快多线程程序的执行速度,实现真正的多线程。

总结

GIL方案确实不够好(从多线程并发的角度),但是单纯的移除GIL并非完美的对策:不仅把烂摊子给了程序员,而且损失了单线程的运行速度。尤其对于Python,简单和优雅是它一贯的特色,移除GIL会是多线程问题变得复杂,也没了优雅。如果真的对性能要求高,那就用Python的多进程吧,呵呵。

下一篇直通车 Python 并发编程系列–2、并发方式的选择

Python操作excel的几种方式--xlrd、xlwt、openpyxl

在处理excel数据时发现了xlwt的局限性–不能写入超过65535行、256列的数据(因为它只支持Excel 2003及之前的版本,在这些版本的Excel中行数和列数有此限制),这对于实际应用还是不够的。为此经过一番寻找发现了一个支持07/10/13版本Excel的openpyxl,虽然功能很强大,但是操作起来感觉没有xlwt方便。下面分别说下几个模块的常用操作。

xlrd

xlrd是用来从Excel中读写数据的,但我平常只用它进行读操作,写操作会遇到些问题。用xlrd进行读取比较方便,流程和平常手动操作Excel一样,打开工作簿(Workbook),选择工作表(sheets),然后操作单元格(cell)。下面举个例子,例如要打开当前目录下名为”data.xlsx”的Excel文件,选择第一张工作表,然后读取第一行的全部内容并打印出来。Python代码如下:

1
2
3
4
5
6
7
8
9
10
11
#打开excel文件
data=xlrd.open_workbook('data.xlsx')
#获取第一张工作表(通过索引的方式)
table=data.sheets()[0]
#data_list用来存放数据
data_list=[]
#将table中第一行的数据读取并添加到data_list中
data_list.extend(table.row_values(0))
#打印出第一行的全部数据
for item in data_list:
print item

上面的代码中读取一行用table.row_values(number),类似的读取一列用table.column_values(number),其中number为行索引,在xlrd中行和列都是从0开始索引的,因此Excel中最左上角的单元格A1是第0行第0列。
xlrd中读取某个单元格用table.cell(row,col)即可,其中row和col分别是单元格对应的行和列。
下面简单归纳一下xlrd的用法

xlrd用法总结

  • 打开Excel工作簿

    1
    data=xlrd.open_workbook(filename)
  • 查看工作簿中所有sheet的名称

    1
    data.sheet_names()
  • 选择某一个工作表(通过索引或表名称)

    1
    2
    3
    4
    5
    6
    7
    8
    #获取第一个工作表
    table=data.sheets()[0]

    #通过索引获取第一个工作表
    table=data.sheet_by_index(0)

    #通过表名称选择工作表
    table=data.sheet_by_name(u'哈哈')
  • 获取表格的行数和列数

    1
    2
    nrows=table.nrows
    ncols=table.ncols
  • 获取整行和整列的值

    1
    2
    table.row_values(number)
    table.column_values(number)
  • 通过循环读取表格的所有行

    1
    2
    for rownum in xrange(table.nrows):
    print table.row_values(rownum)
  • 获取单元格的值

    1
    2
    3
    4
    5
    cell_A1=table.row(0)[0].value
    #或者像下面这样
    cell_A1=table.cell(0,0).value
    #或者像下面这样通过列索引
    cell_A1=table.col(0)[0].value

写操作自己很少用,所以就不归纳了。

xlwt

如果说xlrd不是一个单纯的Reader(如果把xlrd中的后两个字符看成Reader,那么xlwt后两个字符类似看成Writer),那么xlwt就是一个纯粹的Writer了,因为它只能对Excel进行写操作。xlwt和xlrd不光名字像,连很多函数和操作格式也是完全相同。下面简要归纳一下常用操作。

xlwt常用操作

新建一个Excel文件(只能通过新建写入)

1
data=xlwt.Workbook()

新建一个工作表

1
table=data.add_sheet('name')

写入数据到A1单元格

1
table.write(0,0,u'呵呵')

注意:如果对同一个单元格重复操作,会引发overwrite Exception,想要取消该功能,需要在添加工作表时指定为可覆盖,像下面这样

1
table=data.add_sheet('name',cell_overwrite_ok=True)

保存文件

1
data.save('test.xls')

这里只能保存扩展名为xls的,xlsx的格式不支持

xlwt支持一定的样式,操作如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#初始化样式
style=xlwt.XFStyle()

#为样式创建字体
font=xlwt.Font()

#指定字体名字
font.name='Times New Roman'

#字体加粗
font.bold=True

#将该font设定为style的字体
style.font=font

#写入到文件时使用该样式
sheet.write(0,1,'just for test',style)

openpyxl

该模块支持最新版的Excel文件格式,对Excel文件具有响应的读写操作,对此有专门的Reader和Writer两个类,便于对Excel文件的操作。虽然如此,但我一般还是用默认的workbook来进行操作。常用操作归纳如下:

openpyxl常用操作

读取Excel文件

1
2
3
from openpyxl.reader.excel import load_workbook

wb=load_workbook(filename)

显示工作表的索引范围

1
wb.get_named_ranges()

显示所有工作表的名字

1
wb.get_sheet_names()

取得第一张表

1
2
sheetnames = wb.get_sheet_names()  
ws = wb.get_sheet_by_name(sheetnames[0])

获取表名

1
ws.title

获取表的行数

1
ws.get_highest_row()

获取表的列数

1
ws.get_highest_column()

单元格的读取,此处和xlrd的读取方式很相近,都是通过行和列的索引来读取

1
2
#读取B1单元格中的内容
ws.cell(0,1).value

当然也支持通过Excel坐标来读取数据,代码如下

1
2
#读取B1单元格中的内容
ws.cell("B1").value

写文件,只有一种操作方式,就是通过坐标。例如要向单元格C1写数据,就要用类似ws.cell(“C1”).value=something这样的方式。
一般推荐的方式是用openpyxl中的Writer类来实现。代码类似下面这样:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
from openpyxl.workbook import Workbook 

#ExcelWriter,里面封装好了对Excel的写操作
from openpyxl.writer.excel import ExcelWriter

#get_column_letter函数将数字转换为相应的字母,如1-->A,2-->B
from openpyxl.cell import get_column_letter

#新建一个workbook
wb = Workbook()

#新建一个excelWriter
ew = ExcelWriter(workbook = wb)

#设置文件输出路径与名称
dest_filename = r'empty_book.xlsx'

#第一个sheet是ws
ws = wb.worksheets[0]

#设置ws的名称
ws.title = "range names"

#向某个单元格中写入数据
ws.cell("C1").value=u'哈哈'

#最后保存文件
ew.save(filename=dest_filename)

向某个单元格内写文件时要先知道它对应的行数和列数,这里注意行数是从1开始计数的,而列则是从字母A开始,因此第一行第一列是A1,这实际上是采用坐标方式操作Excel。例如,想向表格的第三行第一列插入一个数值1.2,用xlwt写就是table.write(2,0,1.2),因为xlwt中行列索引都从0开始;而如果用openpyxl写就是ws.cell(“A3”).value=1.2。一般对于一个较大的列数,需要通过get_column_letter函数得到相应的字符,然后再调用cell函数写入。
下面是我之前写的一个代码的一部分,可以用来演示将多位数组保存到Excel文件中。为了体现多维数组,这里用到了numpy,另外这里为了简化过程,没有用ExcelWriter。代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#coding:utf-8

from openpyxl import Workbook
from openpyxl.cell import get_column_letter

import numpy as np
#生成一个对角阵
a=np.diag([1,2,3,4,5])

#新建一个工作簿
wb=Workbook()
#使用当前激活的工作表(默认就是Excel中的第一张表)
ws=wb.active
#下面是对a的遍历,注意cell中行和列从1开始,a中索引从0开始。
for row in xrange(1,a.shape[0]+1):
for col in xrange(1,a.shape[1]+1):
col_letter=get_column_letter(col)
ws.cell('%s%s'%(col_letter,row)).value=a[row-1,col-1]
wb.save('test.xlsx')

暂时介绍这么多,基本够用了。

总结

读取Excel时,选择openpyxl和xlrd差别不大,都能满足要求
写入少量数据且存为xls格式文件时,用xlwt更方便
写入大量数据(超过xls格式限制)或者必须存为xlsx格式文件时,就要用openpyxl了。

除以上几个模块外,还有Win32com等模块,但没有用过,就不说了。

用Python抓取携程网机票信息 过程纪实(下篇)

上篇回顾

上篇中我们使用Python对json格式的航班数据进行了处理,因此只要能够构造出正确的URL,就可以实现对航班信息的查询。而构造URL时有三个参数需要查看js代码才可以搞定,这也正是本篇博客要处理的内容。

从主页面找切入点

无论是静态页面还是动态页面,最终获得的数据都要交给主页面来显示,因此从主页面中一定能得到线索。下面看一下主页面对应的html文件。
主页面
切换右侧选项到“消息头”,可以看到该网页的请求网址和浏览器中看到的请求网址相同,可以证明它确实是主页面。
主页面验证

r值的获取

找到了主页面,下面找一下主页面中涉及到那三个参数的代码。为了参照方便,下面贴一下主页面的html代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Cache-Control" content="no-transform " />
<meta http-equiv="Content-Type" content="text/html; charset=gb2312" />
<meta name="description" content="携程旅行网为您提供哈尔滨到上海特价机票以及哈尔滨到上海航班查询。携程旅行网于2003年在美国纳斯达克上市,拥有覆盖全国的服务网络。提供国内国际各大航空公司的航线航班,安全支付值得信赖,是您网上订购哈尔滨到上海机票的首选。免费咨询800-820-6666。" />
<meta name="keywords" content="哈尔滨到上海特价,哈尔滨到上海机票预订,哈尔滨到上海航班查询,携程机票" />
<title>哈尔滨到上海机票预订 - 哈尔滨到上海特价机票 - 哈尔滨到上海航班查询预订 - 携程国内机票预订</title>

<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" />
<link rel="dns-prefetch" href="//webresource.c-ctrip.com" />
<link rel="dns-prefetch" href="//pic.c-ctrip.com" />
<link rel="dns-prefetch" href="//images3.c-ctrip.com" />
<link rel="dns-prefetch" href="//crm.ws.ctrip.com" />
<link rel="dns-prefetch" href="//s.c-ctrip.com" />
<link rel="dns-prefetch" href="//www.google-analytics.com" />
<link rel="canonical" href="http://flights.ctrip.com/booking/hrb-sha-day-1.html"/>
<link href="http://webresource.c-ctrip.com/ResFlightOnline/R1/Booking/css/fltdomestic111027/searchresult_v2.1.css?ReleaseNo=CR_2016_05_10_19_57_18" type="text/css" rel="stylesheet" />

</head>
<body>

<script type="text/javascript">
var url = "http://flights.ctrip.com/domesticsearch/search/SearchFirstRouteFlights?DCity1=HRB&ACity1=SHA&SearchType=S&DDate1=2016-05-13&IsNearAirportRecommond=0&CK=36B05DD175F36398546F66CA5EFD07DE";
var _searchCount_c = 0;

function ajaxRequest(n,t){var i=null,e,f,l,o,s,r,c,u,h;if(typeof XMLHttpRequest!="undefined")i=new XMLHttpRequest;else if(typeof ActiveXObject!="undefined"){if(typeof arguments.callee.aciveXString!="string")for(e=["MSXML2.XMLHttp.6.0","MSXML2.XMLHttp.3.0","MSXML2.XMLHttp"],f=0,l=e.length;f<l;f++)try{i=new ActiveXObject(e[f]);arguments.callee.activeXString=e[f];break}catch(a){}i==null&&(i=new ActiveXObject(arguments.callee.activeXString))}i.onreadystatechange=function(){try{if(i.readyState==4)if(i.status>=200&&i.status<300||i.status==304){var r=eval("("+i.responseText+")");if(_searchCount_c==0&&r&&r.Error&&r.Error.Code==104&&(r.Error.Message==""||!r.Error.Message)){_searchCount_c++;setTimeout(function(){var i=n.split("&");i.pop();ajaxRequest(i.join("&")+"&rt="+Math.random()*1e3,t)},1e3);return}jsonCallback.done(r)}else i.status!=0&&jsonCallback.onError()}catch(u){jsonCallback.onError()}};window.location.hash&&(o=window.location.hash.match(/DDate1=\d{4}-\d{2}-\d{2}/),o&&o.length>0&&(n=n.replace(/DDate1=(\d{4}-\d{2}-\d{2})/ig,o[0])),s=window.location.hash.match(/DDate2=\d{4}-\d{2}-\d{2}/),s&&s.length>0&&(n=n.replace(/DDate2=(\d{4}-\d{2}-\d{2})/ig,s[0])));r=n.replace(/^[\s\xA0]+|[\s\xA0]+$/g,"");(r.indexOf("ClassType=CF")==-1||r.indexOf("ClassType=&")!=-1)&&(r+=getStorage("FD_SearchPage_onlyCf")=="CF"?"&ClassType=CF":"");_searchCount_c>0&&(c=t.split(".")[1],t="0."+c.substring(1,c.length-1));u=r.split("&");h=r.indexOf("rk=")>=0||r.indexOf("rt=")>=0?u.splice(u.length-2,1)[0]:u.pop();u.push("CK=");h=h.split("=")[1];var fn=(function(u,r,k,t){var M48=1,N48M=1;M48=M48-=parseInt(Math.log(8) * 0xa);M48=M48-=parseInt(Math.sin(8) * 0xa);if(M48<0)M48=-M48; while(M48>30)M48=M48%10;N48M=N48M+=parseInt(Math.exp(6) * 0xa);N48M=N48M+=parseInt(Math.sin(6) * 0xa);N48M=N48M+=parseInt(Math.log(6) * 0xa);if(N48M<0)N48M=-N48M; while(N48M>30)N48M=N48M%10;(function(r,u,x,y,t,k){if(!window.location.href){return;}var l=r.split(''); var c=l.splice(y,1);l.splice(x,0,c);t.open('GET', u.join('&')+l.join('') + '&r=' + k, !0);t.send(null);})(r,u,M48,N48M,t,k)});fn(u,h,t,i)}var jsonCallback={isError:!1,isReady:!1,data:{},readyList:[],errorList:[],ready:function(n){this.isReady==!1?this.readyList.push(n):n(this.data)},done:function(n){this.isReady=!0;this.data=n;for(var t=0;this.readyList[t];)this.readyList[t](n),t++},error:function(n){this.isError==!1?this.errorList.push(n):n()},onError:function(){this.isError=!0;for(var n=0;this.errorList[n];)this.errorList[n](),n++}},getStorage=function(n){var i,r,t;try{if(i="{}",window.localStorage)i=localStorage.getItem("jStorage");else if(window.globalStorage)i=window.globalStorage[window.location.hostname];else{r=document.head||document.getElementsByTagName("head")[0];t=document.createElement("link");t.style.behavior="url(#default#userData)";r.appendChild(t);try{t.load("jStorage")}catch(u){t.setAttribute("jStorage","{}");t.save("jStorage");t.load("jStorage")}i=t.getAttribute("jStorage")||"{}";r.removeChild(t)}return!i||i=="{}"?"":eval("("+i+")")[n]}catch(f){return""}}



var searchRouteIndex = "0";
ajaxRequest(url + '&rk=' + Math.random()*10+'071048','0.1735286780048523741211');
</script>


<input type="hidden" id="CorrelationId" name="CorrelationId" value="3480328985819705290"/><link href="http://webresource.c-ctrip.com/ResCRMOnline/R1/pageheader/css/PageHeader_v2.css?temp=20160510" rel="stylesheet" />

<div class="cui_hd_cont">
<div id="cui_hd" class="cui_hd"><input type="hidden" id="_searchboxNo_" value="ws_www20140409"><input type="hidden" id="_newHeaderFlag_" value="true"><div class="ctriplogo"><a href="http://www.ctrip.com" title="携程旅行网">携程旅行网</a></div>
<div class="nav-bar">
<ul class="language">
<li><a href="http://www.ctrip.com/" rel="nofollow" class="selected" id="cui_lang_cn" onmouseover="this.className= 'selected language_current';document.getElementById('cui_lang_list').parentNode.style.display='block';" onmouseout="this.className= 'selected';document.getElementById('cui_lang_list').parentNode.style.display='none';"><span><em class="ico-langgb"></em>简体中文<b class="arrow"></b></span></a><div class="language_wrap drowndrop" style="display: none;" onmouseover="document.getElementById('cui_lang_cn').className= 'selected language_current';this.style.display='block';" onmouseout="document.getElementById('cui_lang_cn').className= 'selected';this.style.display='none';">
<ul class="language_list" id="cui_lang_list">
<li class="first"><a id="ctrip_hk" class="language_hk" href="http://www.ctrip.com.hk?language=HK#from=click_hk">香港(繁体)</a></li>
<li><a id="ctrip_hk_en" class="language_hk" href="http://www.ctrip.com.hk/?language=EN#from=click_hken">Hong Kong(English)</a></li>
<li><a id="ctrip_eng" class="language_en" href="http://english.ctrip.com/#from=click_en">English</a></li>
<li><a id="ctrip_jap" class="language_jap" href="http://jp.ctrip.com/#from=click_jp">日语版</a></li>
<li><a id="ctrip_korea" class="language_korea" href="http://www.ctrip.co.kr/#from=click_kr">韩语版</a></li>
<li><a id="ctrip_sg" class="language_sg" href="http://www.ctrip.sg/#from=click_sg">Singapore</a></li>
<li><a id="ctrip_id" class="language_id" href="http://www.ctrip.co.id/#from=click_id">Bahasa Indonesia</a></li>
<li><a id="ctrip_my" class="language_my" href="http://www.ctrip.my/#from=click_my">Bahasa Malaysia</a></li>
<li><a id="ctrip_th" class="language_th" href="http://www.ctrip.co.th/#from=click_th">&#xE20;&#xE32;&#xE29;&#xE32;&#xE44;&#xE17;&#xE22;</a></li>
<li><a id="ctrip_fr" class="language_fr" href="http://fr.ctrip.com/#from=click_fr">Fran&#xE7;ais</a></li>
<li><a id="ctrip_de" class="language_de" href="http://de.ctrip.com/#from=click_de">Deutsch</a></li>
<li><a id="ctrip_es" class="language_es" href="http://es.ctrip.com/#from=click_es">Espa&#xF1;ol</a></li>
<li class="last"><a id="ctrip_ru" class="language_ru" href="http://ru.ctrip.com/#from=click_ru">Русский</a></li>
</ul>
</div>
</li>
</ul>
<ul class="cui_service">
<li><a target="_blank" rel="nofollow" href="http://kefu.ctrip.com">客服中心
</a></li>
</ul>
<ul class="cui_service service_1180">
<li><a href="#" class="service_tel" id="cui_service_cn" onmouseover="this.className= 'service_tel service_current';document.getElementById('cui_service_tel_list').style.display='block';" onmouseout="this.className= 'service_tel';document.getElementById('cui_service_tel_list').style.display='none';"><span title="免境内长话费">
国内:<em class="service_telnum">1010-6666</em><b class="arrow"></b></span></a><div class="service_wrap drowndrop" id="cui_service_tel_list" onmouseover="document.getElementById('cui_service_cn').className= 'service_tel service_current';this.style.display='block';" onmouseout="document.getElementById('cui_service_cn').className= 'service_tel';document.getElementById('cui_service_tel_list').style.display='none';">
<ul class="service_list">
<li>
<dl>
<dd><span style="color:#999">(或)</span><em>400-820-6666</em></dd>
<dd>
香港:<em>+852-3069-9966</em></dd>
<dd>
海外:<em>+86-21-3406-4888</em></dd>
</dl>
</li>
</ul>
</div>
</li>
</ul>
<ul class="cui_wireless" id="head_float_level">
<li><a href="http://app.ctrip.com" class="wireless wireless_link" target="_blank" rel="nofollow" id="linkid"><i class="cui_ico_app"></i></a><div id="head_float_box_app" class="cui_wireless_box" style="display: none;"><i class="cui_ico_chatarrow" style="right:40px;"></i><div class="cui_wireless_inbox">
<dl class="cui_wireless_type">
<dt>手机扫码快速下载</dt>
<dd><img src="//pic.c-ctrip.com/platform/online/home/er_ctrip_app.jpg" alt=""></dd>
</dl><a href="http://app.ctrip.com" class="cui_link_app">携程旅行手机版<i>&gt;</i></a></div>
</div>
</li>
<li><a href="##" class="wireless wireless_nolink" id="nolinkid"><i class="cui_ico_wechat"></i></a><div id="head_float_box_weixin" class="cui_wireless_box" style="display: none;"><i class="cui_ico_chatarrow"></i><div class="cui_wireless_inbox">
<dl class="cui_wireless_type">
<dt>携程订阅号:helloctrip</dt>
<dd><img src="//pic.c-ctrip.com/platform/online/home/er_ctrip_wechat.jpg" alt=""></dd>
</dl>
扫一扫,领旅行福利
</div>
</div>
</li>
</ul>
</div>
</div>
</div>
<div class="" id="ctrip_doodle"></div>
<div id="cui_nav">
<div class="base_nav">
<ul id="cui_nav_ul" class="cui_nav cui_content">
<li id="cui_nav_home"><a titledec="首页" class="cui_nav_non" id="c_ph_hp" href="http://www.ctrip.com">首页</a></li>
<li class="divider"></li>
<li id="cui_nav_hotel"><a id="a_hotelLink" titledec="酒店" class="cui_nav_hotel cui_nav_has" href="http://hotels.ctrip.com">酒店
<i class="cui_ico_triangle"></i><span class="point"></span></a><div class="cui_subnav_wrap">
<ul class="cui_sub_nav" id="div_hotel">
<li><a titledec="国内酒店" id="c_ph_hotel_h" href="http://hotels.ctrip.com">国内酒店
</a></li>
<li class="divider"></li>
<li><a titledec="海外酒店" id="c_ph_hoteli_h" href="http://hotels.ctrip.com/international/">海外酒店
</a></li>
<li class="divider"></li>
<li><a titledec="海外民宿+短租" id="c_ph_apartment_h" href="http://hotels.ctrip.com/apartment">海外民宿+短租<span class="label-en"><em>NEW</em><i class="triangle"></i></span></a></li>
<li class="divider"></li>
<li><a titledec="团购" id="c_ph_tuan_h" href="http://tuan.ctrip.com">团购
</a></li>
<li class="divider"></li>
<li><a titledec="特价酒店" id="c_ph_hotsale_h" href="http://hotels.ctrip.com/hotsale">特价酒店
</a></li>
<li class="divider"></li>
<li><a rel="nofollow" titledec="途家公寓" id="c_ph_tujia_h" href="http://hotels.ctrip.com/tujia/">途家公寓
</a></li>
<li class="divider"></li>
<li><a titledec="酒店+景点" id="c_ph_taocanj_v" href="http://taocan.ctrip.com/sh/HotelDefault.aspx?fluxentrance=10405&amp;FromMenu=hotel">酒店+景点
</a></li>
<li class="divider"></li>
<li><a titledec="客栈民宿" id="c_ph_inn_h" href="http://inn.ctrip.com">客栈民宿
</a></li>
<li class="divider"></li>
<li><a titledec="会场+团队房" id="c_ph_meeting_h" href="http://meeting.ctrip.com">会场+团队房
</a></li>
</ul><a class="cui_ico_order" rel="nofollow" href="http://my.ctrip.com/Home/Order/HotelOrderList.aspx"><i class="cui-icon-hotel"></i>酒店订单 &gt;
</a></div>
</li>
<li class="divider"></li>
<li id="cui_nav_vac"><a id="a_vacationLink" titledec="旅游" class="cui_nav_vac cui_nav_has" href="http://vacations.ctrip.com">旅游
<i class="cui_ico_triangle"></i><span class="point"></span></a><div class="cui_subnav_wrap">
<ul class="cui_sub_nav" id="div_vacation">
<li><a titledec="旅游首页" id="c_ph_vacations_v" href="http://vacations.ctrip.com">旅游首页
</a></li>
<li class="divider"></li>
<li><a titledec="周末游" id="c_ph_around_v" href="http://you.ctrip.com/around/">周末游
</a></li>
<li class="divider"></li>
<li><a titledec="跟团游" id="c_ph_vacationsd_v" href="http://vacations.ctrip.com/grouptravel/">跟团游
</a></li>
<li class="divider"></li>
<li><a titledec="自由行" id="c_ph_taocan_v" href="http://taocan.ctrip.com">自由行
</a></li>
<li class="divider"></li>
<li><a titledec="邮轮" id="c_ph_cruise_v" href="http://cruise.ctrip.com/">邮轮
</a></li>
<li class="divider"></li>
<li><a titledec="酒店+景点" id="c_ph_taocanj_v" href="http://taocan.ctrip.com/sh/">酒店+景点<span class="label-cn"><em>自驾游</em><i class="triangle"></i></span></a></li>
<li class="divider"></li>
<li><a titledec="当地玩乐" id="c_ph_huodong_v" href="http://huodong.ctrip.com/">当地玩乐
</a></li>
<li class="divider"></li>
<li><a titledec="主题游" id="c_ph_zhutiyou_v" href="http://vacations.ctrip.com/themetravel/">主题游<span class="label-en"><em>NEW</em><i class="triangle"></i></span></a></li>
<li class="divider"></li>
<li><a titledec="定制&#x2022;包团" id="c_ph_baotuan_v" href="http://vacations.ctrip.com/dingzhi">定制&#x2022;包团
</a></li>
<li class="divider"></li>
<li><a titledec="游学" id="c_ph_youxue_v" href="http://vacations.ctrip.com/youxue">游学
</a></li>
<li class="divider"></li>
<li><a titledec="签证" id="c_ph_visa_v" href="http://vacations.ctrip.com/visa">签证
</a></li>
<li class="divider"></li>
<li><a titledec="企业会奖" id="c_ph_mice_v" href="http://vacations.ctrip.com/mice">企业会奖
</a></li>
<li class="divider"></li>
<li><a titledec="顶级游" href="http://www.hhtravel.com/#ctm_ref=hh_ct_thp_nav" target="_blank" rel="nofollow" id="c_ph_hh_v">顶级游</a></li>
<li class="divider"></li>
<li><a titledec="爱玩户外" id="c_ph_golf_v" href="http://pages.ctrip.com/ctt/marketing/">爱玩户外
</a></li>
<li class="divider"></li>
<li><a titledec="保险" id="c_ph_insurance_v" href="http://vacations.ctrip.com/insurance">保险
</a></li>
<li class="divider"></li>
<li><a titledec="特卖汇" id="c_ph_deals_v" href="http://vacations.ctrip.com/deals">特卖汇
</a></li>
</ul><a class="cui_ico_order" rel="nofollow" href="http://my.ctrip.com/Home/Order/PkgOrderList.aspx"><i class="cui-icon-vacations"></i>旅游订单 &gt;
</a></div>
</li>
<li class="divider"></li>
<li id="cui_nav_flight" class="cui_nav_current"><a id="a_flightLink" titledec="机票" class="cui_nav_flight cui_nav_has" href="http://flights.ctrip.com">机票
<i class="cui_ico_triangle"></i><span class="point"></span></a><div class="cui_subnav_wrap">
<ul id="div_flight" class="cui_sub_nav">
<li><a titledec="国内机票" id="c_ph_flights_f" class="cui_sub_current" href="http://flights.ctrip.com">国内机票
</a></li>
<li class="divider"></li>
<li><a titledec="国际机票" id="c_ph_flightsi_f" href="http://flights.ctrip.com/international/">国际机票
</a></li>
<li class="divider"></li>
<li><a titledec="机+酒" id="c_ph_taocan_f" href="http://taocan.ctrip.com">机+酒
</a></li>
<li class="divider"></li>
<li><a titledec="航班动态" id="c_ph_flightstoolbox_f" href="http://flights.ctrip.com/actualtime">航班动态
</a></li>
<li class="divider"></li>
<li><a rel="nofollow" titledec="值机选座" id="c_ph_bookseat_f" href="http://flights.ctrip.com/domestic/checkinseat/index">值机选座
</a></li>
<li class="divider"></li>
<li><a rel="nofollow" titledec="退票改签" id="c_ph_flightorderlist_f" href="http://my.ctrip.com/Home/Order/FlightOrderList.aspx">退票改签
</a></li>
<li class="divider"></li>
<li><a rel="nofollow" titledec="机场攻略" id="c_ph_airportguides_f" href="http://flights.ctrip.com/booking/airport-guides.html">机场攻略
</a></li>
<li class="divider"></li>
<li><a titledec="机场巴士" id="c_ph_airbus_f" href="http://airbus.ctrip.com#ctm_ref=arb_hp_flt_nang">机场巴士
</a></li>
<li class="divider"></li>
<li><a titledec="公务员通道" id="c_ph_gwytd_f" href="http://flights.ctrip.com/Domestic/Civs">公务员通道<span class="label-en"><em>NEW</em><i class="triangle"></i></span></a></li>
</ul><a class="cui_ico_order" rel="nofollow" href="http://my.ctrip.com/Home/Order/FlightOrderList.aspx"><i class="cui-icon-flight"></i>机票订单 &gt;
</a></div>
</li>
<li class="divider"></li>
<li id="cui_nav_trains"><a titledec="火车" class="cui_nav_has" id="c_ph_train" href="http://trains.ctrip.com">火车
<i class="cui_ico_triangle"></i><span class="point"></span></a><div class="cui_subnav_wrap">
<ul class="cui_sub_nav">
<li><a titledec="国内火车票" id="c_ph_train_t" href="http://trains.ctrip.com">国内火车票
</a></li>
<li class="divider"></li>
<li><a titledec="国际&#x2022;台湾火车票" id="c_ph_traino_t" href="http://rails.ctrip.com">国际&#x2022;台湾火车票
</a></li>
</ul><a class="cui_ico_order" rel="nofollow" href="http://my.ctrip.com/Home/Order/RailwayOrderList.aspx"><i class="cui-icon-train"></i>火车票订单 &gt;
</a></div>
</li>
<li class="divider"></li>
<li id="cui_nav_destination"><a titledec="汽车票" class="cui_nav_has" id="c_ph_bus" href="http://Bus.ctrip.com">汽车票
<i class="cui_ico_triangle"></i><span class="point"></span></a><div class="cui_subnav_wrap">
<ul class="cui_sub_nav">
<li><a titledec="汽车票" id="c_ph_bus_t" href="http://Bus.ctrip.com">汽车票
</a></li>
<li class="divider"></li>
<li><a titledec="机场巴士" id="c_ph_airbus_t" href="http://airbus.ctrip.com#ctm_ref=arb_hp_bus_nang">机场巴士
</a></li>
<li class="divider"></li>
<li><a titledec="船票" id="c_ph_ship_t" href="http://Bus.ctrip.com/ship">船票<span class="label-en"><em>NEW</em><i class="triangle"></i></span></a></li>
</ul><a class="cui_ico_order" rel="nofollow" href="http://my.ctrip.com/Home/Order/QicheOrderlist.aspx"><i class="cui-icon-bus"></i>汽车票订单 &gt;
</a></div>
</li>
<li class="divider"></li>
<li id="cui_nav_car"><a titledec="用车" href="http://car.ctrip.com/#ctm_ref=chp_var_txt" class="cui_nav_hotel cui_nav_has" id="c_ph_car">用车
<i class="cui_ico_triangle"></i><span class="point"></span></a><div class="cui_subnav_wrap">
<ul class="cui_sub_nav">
<li><a titledec="用车首页" id="c_ph_car_c" href="http://car.ctrip.com#ctm_ref=chp_var_txt">用车首页
</a></li>
<li class="divider"></li>
<li><a titledec="国际租车" id="c_ph_hwzj_c" href="http://car.ctrip.com/hwzijia#ctm_ref=chp_var_txt">国际租车<span class="label-cn"><em>特惠</em><i class="triangle"></i></span></a></li>
<li class="divider"></li>
<li><a titledec="国际接送机" id="c_ph_hwdaijia_c" href="http://car.ctrip.com/hwdaijia#ctm_ref=chp_var_txt">国际接送机
</a></li>
<li class="divider"></li>
<li><a titledec="国内租车" id="c_ph_zj_c" href="http://car.ctrip.com/zijia#ctm_ref=chp_var_txt">国内租车
</a></li>
<li class="divider"></li>
<li><a titledec="国内接送机/火车" id="c_ph_daijia_c" href="http://car.ctrip.com/daijia#ctm_ref=chp_var_txt">国内接送机/火车
</a></li>
<li class="divider"></li>
<li><a titledec="日租包车" id="c_ph_rizu_c" href="http://car.ctrip.com/dayweb">日租包车<span class="label-en"><em>NEW</em><i class="triangle"></i></span></a></li>
</ul><a class="cui_ico_order" rel="nofollow" href="http://my.ctrip.com/Home/Order/CarOrderList.aspx"><i class="cui-icon-car"></i>用车订单 &gt;
</a></div>
</li>
<li class="divider"></li>
<li id="cui_nav_ticket"><a titledec="门票" class="cui_nav_ticket cui_nav_has" id="c_ph_piao" href="http://piao.ctrip.com">门票
<i class="cui_ico_triangle"></i><span class="point"></span></a><div class="cui_subnav_wrap">
<ul class="cui_sub_nav">
<li><a titledec="国内门票" id="c_ph_piao_p" href="http://piao.ctrip.com/?clear=t#ctm_ref=tkt_home_tab_inland">国内门票
</a></li>
<li class="divider"></li>
<li><a titledec="海外门票" id="c_ph_piaooversea_p" href="http://piao.ctrip.com/oversea#ctm_ref=tkt_home_tab_oversea">海外门票
</a></li>
<li class="divider"></li>
<li><a titledec="当地玩乐" id="c_ph_huodong_p" href="http://huodong.ctrip.com#ctm_ref=ctr_hp_ttd">当地玩乐<span class="label-en"><em>NEW</em><i class="triangle"></i></span></a></li>
<li class="divider"></li>
<li><a titledec="出境WiFi" id="c_ph_wifi_p" href="http://huodong.ctrip.com/wifi#ctm_ref=ctr_hp_wifi">出境WiFi
</a></li>
<li class="divider"></li>
<li><a titledec="周末游" id="c_ph_around_p" href="http://you.ctrip.com/around#ctm_ref=gs-990123-290801-0-02-M001|0|0">周末游
</a></li>
<li class="divider" style="display:none"></li>
<li><a titledec="迪士尼" id="c_ph_disney_p" style="display:none" href="http://pages.c-ctrip.com/commerce/promote/201603/vacation/disney/online.html">迪士尼
</a></li>
</ul><a class="cui_ico_order" rel="nofollow" href="http://my.ctrip.com/Home/Order/PiaoOrderlist.aspx"><i class="cui-icon-ticket"></i>门票订单 &gt;
</a></div>
</li>
<li class="divider"></li>
<li id="cui_nav_tuan"><a class="cui_nav_has" id="c_ph_tuan" href="http://tuan.ctrip.com">团购
<i class="cui_ico_triangle"></i><span class="point"></span></a><div class="cui_subnav_wrap">
<ul class="cui_sub_nav">
<li><a titledec="团购首页" id="c_ph_tuan_tu" href="http://tuan.ctrip.com">团购首页
</a></li>
<li class="divider"></li>
<li><a titledec="酒店" id="c_ph_tuanhotel_tu" href="http://tuan.ctrip.com/hotel/">酒店
</a></li>
<li class="divider"></li>
<li><a titledec="门票" id="c_ph_tuanticket_tu" href="http://tuan.ctrip.com/ticket/">门票
</a></li>
<li class="divider"></li>
<li><a titledec="旅游" id="c_ph_tuantravel_tu" href="http://tuan.ctrip.com/travel/">旅游
</a></li>
<li class="divider"></li>
<li><a titledec="美食" id="c_ph_tuanlife_tu" href="http://tuan.ctrip.com/life/">美食
</a></li>
</ul><a class="cui_ico_order" rel="nofollow" href="http://my.ctrip.com/Home/Order/GroupOrderList.aspx"><i class="cui-icon-tuan"></i>团购订单 &gt;
</a></div>
</li>
<li class="divider"></li>
<li id="cui_nav_destination01"><a titledec="攻略" class="cui_nav_non" id="c_ph_you" href="http://you.ctrip.com">攻略</a></li>
<li class="divider"></li>
<li id="cui_nav_g"><a titledec="全球购" class="cui_nav_has" id="c_ph_go" href="http://g.ctrip.com">全球购
<i class="cui_ico_triangle"></i><span class="point"></span></a><div class="cui_subnav_wrap">
<ul class="cui_sub_nav" id="div_global">
<li><a titledec="名店购" id="c_ph_mdg_g" href="http://g.ctrip.com">名店购
</a></li>
<li class="divider"></li>
<li><a titledec="退税" id="c_ph_ts_g" href="http://tax.ctrip.com/?bid=2&amp;cid=1&amp;pid=1">退税
</a></li>
<li class="divider"></li>
<li><a titledec="刷卡奖励" id="c_ph_skjl_g" href="http://card.ctrip.com/#ctm_ref=ctr_bid_0_cid_1_pid_1">刷卡奖励
</a></li>
</ul>
</div>
</li>
<li class="divider"></li>
<li id="cui_nav_lpk"><a class="cui_nav_has" id="c_ph_lipin" href="http://lipin.ctrip.com">礼品卡
<i class="cui_ico_triangle"></i><span class="point"></span></a><div class="cui_subnav_wrap">
<ul class="cui_sub_nav">
<li><a titledec="礼品卡" id="c_ph_lipin_l" href="http://lipin.ctrip.com">礼品卡首页
</a></li>
<li class="divider"></li>
<li><a titledec="礼品卡套餐" id="c_ph_xcb_l" href="http://lipin.ctrip.com/xcb">礼品卡套餐
</a></li>
<li class="divider"></li>
<li><a titledec="存款证明" id="c_ph_ckzm_l" href="http://jr.ctrip.com/deposit/deposit/index">存款证明
</a></li>
</ul><a class="cui_ico_order" rel="nofollow" href="http://my.ctrip.com/Home/Order/TicketOrderList.aspx"><i class="cui-icon-card"></i>礼品卡订单 &gt;
</a></div>
</li>
<li class="divider"></li>
<li id="cui_nav_sl"><a titledec="商旅" class="cui_nav_has" id="c_ph_crptravel" href="http://ct.ctrip.com">商旅
<i class="cui_ico_triangle"></i><span class="point"></span></a><div class="cui_subnav_wrap">
<ul class="cui_sub_nav" id="div_crptravel">
<li><a titledec="商旅首页" id="c_ph_slsy_s" href="http://ct.ctrip.com">商旅首页
</a></li>
<li class="divider"></li>
<li><a titledec="企业差旅平台" id="c_ph_chl_s" href="http://ct.ctrip.com/crptravel/default/landing">企业差旅平台<span class="label-en"><em>HOT</em><i class="triangle"></i></span></a></li>
<li class="divider"></li>
<li><a titledec="会议旅游" id="c_ph_hj_s" href="http://mice.ctrip.com">会议旅游
</a></li>
</ul>
</div>
</li>
<li class="divider divider_spec"></li>
<li id="cui_nav_cruise"><a titledec="邮轮" class="cui_nav_non" id="c_ph_youlun" href="http://cruise.ctrip.com">邮轮</a></li>
<li class="divider divider_spec"></li>
<li id="cui_nav_cruise_skysea"><a titledec="天海邮轮" class="cui_nav_non" id="c_ph_skysea" href="http://cruise.ctrip.com/skysea">天海邮轮</a></li>
<li class="divider"></li>
<li id="cui_nav_more"><a rel="nofollow" id="a_moreLink" titledec="更多" class="cui_nav_more cui_nav_has" href="http://jifen.ctrip.com/rewards">更多
<i class="cui_ico_triangle"></i><span class="point"></span></a><div class="cui_subnav_wrap">
<ul class="cui_sub_nav" id="div_more">
<li><a titledec="积分商城" rel="nofollow" id="c_ph_rewards_m" href="http://jifen.ctrip.com/rewards">积分商城
</a></li>
<li class="divider"></li>
<li><a titledec="合作卡" rel="nofollow" id="c_ph_cards_m" href="http://cards.ctrip.com">合作卡
</a></li>
</ul>
</div>
</li>
<li id="loginDivLi" class="cui_nav_myctrip cui_content">
<ul class="cui_myctrip_log" style="display:block;" id="ulCTFullMC">
<li class="userLogin" id="div_User"></li>
<li class="myctrip" style="margin-top:0;"><span id="div_MyCtrip"></span><ul class="cui_account cui_account_login" id="loginDiv" style="display:none;">
<li>
<div id="div_Loginbtn"></div>
</li>
<li class="cui_account_info"><a rel="nofollow" href="http://my.ctrip.com/home/Order/AllOrder.aspx#ctm_ref=ssc_hp_myctrip_allorders_a">全部订单
</a></li>
<li class="divider"></li>
<li class="account_order">
<ul>
<li><a rel="nofollow" href="http://my.ctrip.com/Home/Order/FlightOrderList.aspx#ctm_ref=ssc_hp_myctrip_flightorders_a">机票订单
</a></li>
<li><a rel="nofollow" href="http://my.ctrip.com/Home/Order/HotelOrderList.aspx#ctm_ref=ssc_hp_myctrip_hotelorders_a">酒店订单
</a></li>
<li><a rel="nofollow" href="http://my.ctrip.com/Home/Order/PkgOrderList.aspx#ctm_ref=ssc_hp_myctrip_tourorders_a">旅游订单
</a></li>
<li><a rel="nofollow" href="http://my.ctrip.com/Home/Order/RailwayOrderList.aspx#ctm_ref=ssc_hp_myctrip_trainorders_a">火车票订单
</a></li>
<li><a rel="nofollow" class="gray" href="http://my.ctrip.com/home/FastOrder/OrderSearch.aspx#ctm_ref=ssc_hp_myctrip_phoneorders_a">手机号查订单
</a></li>
</ul>
</li>
<li class="divider"></li>
<li><a rel="nofollow" href="https://secure.ctrip.com/Payment-Base-PaymentPwd/Wallet/View/MyWalletIndex.aspx#ctm_ref=ssc_hp_myctrip_wallet_a">携程钱包
</a></li>
<li><a rel="nofollow" href="http://my.ctrip.com/FavoriteOnline/hotel/hotellist.aspx#ctm_ref=ssc_hp_myctrip_collect_a">收藏
</a></li>
<li><a rel="nofollow" href="https://smarket.ctrip.com/Promocode/zh-cn/Promocode.aspx#ctm_ref=ssc_hp_myctrip_integral_a">票券与积分
</a></li>
<li><a rel="nofollow" href="http://my.ctrip.com/Home/Passenger/PassengerList.aspx#ctm_ref=ssc_hp_myctrip_info_a">常用信息
</a></li>
</ul>
</li>
<li class="message" id="div_MyCTMessages"></li>
</ul>
<ul class="cui_myctrip_log" style="display:none;" id="ulCTMinMC">
<li class="userLogin" id="div_User"></li>
<li class="myctrip" style="margin-top:0;clear:left;"><span id="div_MyCtrip"></span><ul class="cui_account cui_account_login" id="loginDiv" style="display:none;">
<li>
<div id="div_Loginbtn"></div>
</li>
<li class="cui_account_info"><a rel="nofollow" href="http://my.ctrip.com/home/Order/AllOrder.aspx#ctm_ref=ssc_hp_myctrip_allorders_a">全部订单
</a></li>
<li><a rel="nofollow" class="gray" href="http://my.ctrip.com/home/FastOrder/OrderSearch.aspx#ctm_ref=ssc_hp_myctrip_phoneorders_a">手机号查订单
</a></li>
</ul>
</li>
<li class="message" id="div_MyCTMessages"></li>
</ul>
</li>
</ul>
</div>
<div id="nav_bh" class="cui_nav_behind" style="display:none;height:0px;"></div>
</div><input type="hidden" id="popfloating_isshow" value="0"><input type="hidden" id="siteDomainHeadFloat" value="ctrip"><input type="hidden" id="bsType" value="0"><script>
/**
* Ctrip JavaScript Code
* http://www.ctrip.com/
* Copyright(C) 2008 - 2015, Ctrip All rights reserved.
* Version: 151217
* Date: 2015-12-17
*/
;window.replace=function(){return ''};window.replace=function(){return""};
!function(){window.replace=function(){return""};(function(){var h=document,c=function(a){return h.getElementById(a)},k=null,l=null,m=0,d=[c("cui_nav_destination"),c("cui_nav_hotel"),c("cui_nav_vac"),c("cui_nav_flight"),c("cui_nav_more"),c("cui_nav_car"),c("cui_nav_trains"),c("cui_nav_tuan"),c("cui_nav_lpk"),c("cui_nav_ticket"),c("cui_nav_sl"),c("cui_nav_g")],g={onmouseenter:function(a,b){(h.all?a.onmouseenter=b:a.onmouseover=function(a){(null==a.relatedTarget?b():this!==a.relatedTarget&&20!=this.compareDocumentPosition(a.relatedTarget)&&
b())})},onmouseout:function(a,b){(h.all?a.onmouseleave=b:a.onmouseout=function(a){(null==a.relatedTarget?b():this!==a.relatedTarget&&20!=this.compareDocumentPosition(a.relatedTarget)&&b())})},addEvent:function(a,b,f){(a.addEventListener?a.addEventListener(b,f,!1):(a.attachEvent?a.attachEvent("on"+b,f):a["on"+b]=f))}},e={setTime:function(){g.onmouseenter(c("cui_nav"),function(){setTimeout(function(){m=150},30)});g.onmouseout(c("cui_nav"),function(){m=0})},initEvent:function(){for(var a=0,b=d.length;b>a;a++)(function(){var b=
a;g.onmouseenter(d[b],function(){e.interFn(d[b])});g.onmouseout(d[b],function(){e.outerFn(d[b])})})(a)},reset:function(){for(var a=0,b=d.length;b>a;a++)d[a].className=(-1<d[a].className.indexOf("cui_nav_current")?"cui_nav_current":"")},padReset:function(a){for(var b=0,f=d.length;f>b;b++)(-1<d[b].className.indexOf("cui_nav_current")?d[b].className="cui_nav_current":b!==a&&(d[b].className=""))},interFn:function(a){for(var b=document.getElementById("cui_nav").getElementsByTagName("li"),f="",d=0;d<b.length;d++)b[d].className.match((/cui_nav_current/))&&
(f=b[d]);null!=l&&(clearTimeout(l),l=null);k=setTimeout(function(){e.reset();(-1<a.className.indexOf("cui_nav_current")?f.className="cui_nav_current":(a.className="cui_nav_o",f.className="cui_nav_current cui_nav_unhover"))},m)},outerFn:function(a){for(var b=document.getElementById("cui_nav").getElementsByTagName("li"),d="",c=0;c<b.length;c++)b[c].className.match((/cui_nav_current/))&&(d=b[c]);null!=k&&(clearTimeout(k),k=null);l=setTimeout(function(){e.reset();(-1<a.className.indexOf("cui_nav_current")?
d.className="cui_nav_current":(a.className="",d.className="cui_nav_current"))},250)},initMobile:function(){for(var a=0,b=d.length;b>a;a++)(function(){var b=a,c=d[b].getElementsByTagName("A")[0];c.href="###";c.onmousedown=function(){e.padReset(b);-1===d[b].className.indexOf("cui_nav_current")&&((-1<d[b].className.indexOf("cui_nav_o")?(d[b].className="",document.getElementsByClassName("cui_nav_current")[0].className="cui_nav_current",c.style.visibility="hidden",setTimeout(function(){c.style.visibility=
"visible"},10)):(d[b].className="cui_nav_o",document.getElementsByClassName("cui_nav_current")[0].className="cui_nav_current",document.getElementsByClassName("cui_nav_current")[0].className+=" cui_nav_unhover")))}})(a)},contains:function(a){for(var b=0,c=d.length;c>b;b++)if(0<d[b].compareDocumentPosition(a)-19)return!0;return!1}};c("headStyleId")&&c("headStyleId").parentNode.removeChild(c("headStyleId"));((/ip(hone|od)|ipad/i).test(navigator.userAgent)?(e.initMobile(),g.addEvent(h.body,"click",function(a){e.contains(a.target||
a.srcElement)||e.reset()})):(e.setTime(),e.initEvent()))})()}();

</script>

<div id="base_bd">

<div class="head_crumb clearfix">
<a class="search_flthotel" id="flthotelLink" onclick="AirHotel.redirectToPackageAction();" href="javascript:void(0);">机+酒</a> <a href="http://flights.ctrip.com/">国内机票</a> &gt; 哈尔滨到上海机票(单程)
</div>

<form id="reSearchForm">
<div id="search_form" class="search_form clearfix">
<div class="flight_way">
<select id="FlightSearchType">
<option value="S">单程</option>
<option value="D">往返</option>
<option value="M">联程</option>
</select>
</div>
<div class="flight_attribute">
<ul>
<li>
<strong class="multiway" style="display: none;">第一程:</strong> 出发城市 <input type="text" id="DCityName1" name="DCityName1" mod="address|notice" mod_address_tpl="on" mod_address_reference="DCity1" placeholder="中文/拼音" mod_address_source="flight_new" autocomplete="off" />
<a class="swapcity ico_change2" title="互换出发到达城市" href="javascript:void(0);"></a><span class="lblACity">到达城市</span> <input type="text" id="ACityName1" name="ACityName1" mod_address_reference="ACity1" mod_address_tpl="on" mod="address|notice" mod_address_source="flight_new" placeholder="中文/拼音" autocomplete="off" />
出发日期 <input id="DDate1" name="DDate1" type="text" value="" mod="calendar|notice" placeholder="yyyy-mm-dd" autocomplete="off" />
<span class="returndate">返回日期 <input type="text" id="ReturnDate1" name="ReturnDate1" mod="calendar|notice" placeholder="yyyy-mm-dd" autocomplete="off" />
</span>
</li>
<li class="search_m second_line" style="display: none;">
<span><strong>第二程:</strong> 中转城市 <input type="text" disabled="disabled" id="DCityName2" autocomplete="off" /></span> <span>到达城市 <input type="text" id="ACityName2" name="ACityName2" mod_address_tpl="on" mod_address_focusnext="true" mod_address_reference="ACity2" mod="address|notice" mod_address_source="flight_new" placeholder="中文/拼音" autocomplete="off" /></span> <span>出发日期 <input type="text" id="DDate2" name="DDate2" mod="calendar|notice" placeholder="yyyy-mm-dd" autocomplete="off" />
</span>
</li>
</ul>
<div class="type_number_line" id="advanceOption" style="display: none;">
<span style="padding-left: 24px; text-align: right;">人数</span>
<select id="PassengerQuantity" name="PassengerQuantity">
<option value="1" selected="selected">1</option>
<option value="2">2</option>
<option value="3">3</option>
<option value="4">4</option>
<option value="5">5</option>
<option value="6">6</option>
<option value="7">7</option>
<option value="8">8</option>
<option value="9">9</option>
</select>
<span id="passengerType_label">乘客类型</span>
<select id="PassengerType" name="PassengerType">
<option value="ADU" selected="selected">成人</option>
<option value="CHI">儿童(2-12周岁)</option>
<option value="BAB">婴儿(2周岁以下)</option>
</select>
<span>舱位等级</span>
<select id="ClassType" name="ClassType">
<option value="">经济舱</option>
<option value="CF">公务舱/头等舱</option>
</select>
</div>
</div>
<div class="search_tools clearfix" id="searchBtns">
<input type="button" data-ubt="ReSearch" value="重新搜索" style="display:" class="btn_search" id="btnReSearch" />
<a rel="nofollow" data-ubt="AdvanceSearch" id="advancedSearch" style="display:" class="arrow_down" href="javascript:void(0);">高级搜索<b></b></a>
</div>
<input id="DCity1" name="DCity1" type="hidden" />
<input id="ACity1" name="ACity1" type="hidden" />
<input id="DCity2" name="DCity2" type="hidden" />
<input id="ACity2" name="ACity2" type="hidden" />
</div>
</form>

<div id="searchHistory_box">
</div>
<div class="base_main" id="baseMain">
<div id="J_ADBanner"></div>


<div id="J_Announcement" style="display:none">
</div>
<div id="J_filterAlert" style="display:none">
</div>
<div id="J_alertInfo" style="display:none">
</div>

<div id="searchLoading" style="height: 160px; text-align: center;">
<p style="color: #333; padding: 5px 0;">正在为您搜索航班信息...</p>
<i class="ico_loading"></i>
<p style="color: #999; padding: 5px 0;">携程在手,说走就走</p>
</div>
<div id="J_searchError">
</div>


<div id="J_selectedFlight" style="display:none">
</div>
<div style="display: none" id="jmp_table2">
${txt1}
</div>
<div id="J_searchPannel" style="display: none;">
<div class="searchresult_content choose_type_m" id="J_searchResultList">
<div id="J_controlPannel">
<div class="calendar_tab calendar_panel clearfix" style="overflow: hidden;">
<div id="prevDate" class="prev_date">
<a class="arrow_left_disable" rel="nofollow" data-ubt="ChangeDate_Left" href="javascript:void(0);"><b></b></a>
</div>
<div style="position: relative;" class="calendar_tab_list">
<ul id="J_lowestPriceDateList" class="calendar_ul clearfix" style="position: relative;
left: 0;">
</ul>

</div>
<div id="nextDate" class="next_date">
<a class="arrow_right" rel="nofollow" data-ubt="ChangeDate_Right" href="javascript:void(0)"><b></b></a>
</div>
<div class="panel_link">
<a id="lowestPriceLink" href="javascript:void(0);" class="days90" target="_blank">
</a>
</div>
</div>

<div class="search_filter clearfix">
<div id="J_flightFilter">
</div>
<div style='display: none;' id="J_filterBar" class="filter_choosen clearfix">
<h4>
筛选条件:
</h4>
<a href="javascript:void(0);" data-ubt="Filter_Delete" id='filterClear'>清除</a>
</div>
</div>
<div class="sort-controls clearfix">
<ul class="sorts">
<li><a id="default_sort" data-ubt="Sort_All" ascdesc="综合" descdesc="综合" original="综合" field="default" cmd="sort" sort="ASC" href="javascript:void(0);" class="default">综合</a></li>
<li class="current">
<a id="dtime_sort" data-ubt="Sort_DepartTime" ascdesc="起飞时间从早到晚" descdesc="起飞时间从晚到早" original="起飞时间"
field="dtime" cmd="sort" href="javascript:void(0);" sort="ASC">起飞时间从早到晚<i class="ico ico-sort"></i></a>

</li>
<li>
<a id="price_sort" data-ubt="Sort_Price" ascdesc="价格从低到高" descdesc="价格从高到低" original="价格" field="price"
cmd="sort" href="javascript:void(0);">价格<i class="ico"></i></a>

</li>
<li>
<a href="javascript:void(0);" data-ubt="OnTimeRate" descdesc="准点率从高到低" original="准点率" field="punctuality"
cmd="sort">准点率</a>

</li>
</ul>
<a href="javascript:;" data-ubt="Governer" class="government-btn" onclick="Ctrip.Flight.Moudule.Other.civilSearch()">公务员通道</a>
<h3>
<strong id="flightCount">0</strong>条航班信息
</h3>
<div class="filter_side filter_mileage">
<label>
<input type="checkbox" data-ubt="Mile" id="filterMileage" class="input_checkbox" />显示里程累积
</label>
</div>
</div>
</div>

<div class="flight-list-content" style="position: relative; z-index: 1">
<div id="J_flightlist1">
</div>
<div id="J_flightlist2">
</div>
</div>
</div>
<div id="flightTransitRound" class="recommend_transit_box" style="display: none;">
<h3 class="recommend_transit_hd">
往返中转推荐</h3>
</div>
<div id="jmp_text" style="display: none">
<div class="jmp_bd">
${txt0}</div>
</div>
<div id="jmp_text_nopadding" style="display: none">
${txt0}
</div>
<div id="recommendProducts">
<div id="J_transit">
</div>
<div id="J_specialOffer">
</div>
<div id="J_near">
</div>
</div>
<div class="recommend_box">
<h3>有低价早知道</h3>
<p class="lowcost_remind">价格还不够低?订阅低价提醒,率先掌握低价信息。<input id="btn_remind" data-ubt="LowestSubscribe" onclick="window.open($(this).attr('url'))" type="button" value="立刻订阅" class="btn_white"></p>
</div>

<div class="disclaimer">
<h3>航班信息免责声明:</h3>
<p>携程旅行网提供的各类航班相关的信息,包括但不限于舱位价格、餐食、起降准点率等,来源于中国航信、全国各大机场、航空公司及相关部门公布数据。由于这些信息可能随时变化,以及网络传输问题,携程提供的此类信息可能并非最新或存在误差,因此<b>仅供旅客作为一般参考</b>,任何公司或个人不能将此作为携程做出任何承诺或做出任何保证的依据。</p>
</div>

<div class="base_crumb">
<a href="http://flights.ctrip.com">国内机票查询</a>&nbsp;| <a href="http://flights.ctrip.com/booking/hrb-HAERBIN-flights.html">哈尔滨</a>&nbsp;| <a href="http://flights.ctrip.com/booking/HRB-SHA-day-1.html">哈尔滨到上海</a>&nbsp;|
<span>哈尔滨到上海5月13日</span>
</div>
<div class="data_travelsky">
<span></span>数据信息由<br />
中国民航信息网络股份有限公司提供
</div>

</div>
<div id="noresult_seo" style="display:none;">
<div class="none_seo">
<div class="title">
国内热门机票</div>
<p class="link">
<a href="http://flights.ctrip.com/booking/CTU-SHA-day-1.html" title="成都到上海机票" target="_blank">成都到上海机票</a>
<a href="http://flights.ctrip.com/booking/BJS-CTU-day-1.html" title="北京到成都机票" target="_blank">北京到成都机票</a>
<a href="http://flights.ctrip.com/booking/BJS-SZX-day-1.html" title="北京到深圳机票" target="_blank">北京到深圳机票</a>
<a href="http://flights.ctrip.com/booking/CTU-BJS-day-1.html" title="成都到北京机票" target="_blank">成都到北京机票</a>
<a href="http://flights.ctrip.com/booking/CAN-BJS-day-1.html" title="广州到北京机票" target="_blank">广州到北京机票</a>
<a href="http://flights.ctrip.com/booking/TAO-SHA-day-1.html" title="青岛到上海机票" target="_blank">青岛到上海机票</a>
<a href="http://flights.ctrip.com/booking/XMN-SHA-day-1.html" title="厦门到上海机票" target="_blank">厦门到上海机票</a>
<a href="http://flights.ctrip.com/booking/SIA-BJS-day-1.html" title="西安到北京机票" target="_blank">西安到北京机票</a>
<a href="http://flights.ctrip.com/booking/CAN-HGH-day-1.html" title="广州到杭州机票" target="_blank">广州到杭州机票</a>
<a href="http://flights.ctrip.com/booking/CKG-SHA-day-1.html" title="重庆到上海机票" target="_blank">重庆到上海机票</a>
<a href="http://flights.ctrip.com/booking/SIA-SHA-day-1.html" title="西安到上海机票" target="_blank">西安到上海机票</a>
<a href="http://flights.ctrip.com/booking/TSN-SHA-day-1.html" title="天津到上海机票" target="_blank">天津到上海机票</a>
<a href="http://flights.ctrip.com/booking/BJS-KMG-day-1.html" title="北京到昆明机票" target="_blank">北京到昆明机票</a>
<a href="http://flights.ctrip.com/booking/HET-BJS-day-1.html" title="呼和浩特到北京机票" target="_blank">呼和浩特到北京机票</a>
<a href="http://flights.ctrip.com/booking/SHA-KHN-day-1.html" title="上海到南昌机票" target="_blank">上海到南昌机票</a>
<a href="http://flights.ctrip.com/booking/HFE-CAN-day-1.html" title="合肥到广州机票" target="_blank">合肥到广州机票</a>
<a href="http://flights.ctrip.com/booking/NKG-CAN-day-1.html" title="南京到广州机票" target="_blank">南京到广州机票</a>
<a href="http://flights.ctrip.com/booking/ZUH-SHA-day-1.html" title="珠海到上海机票" target="_blank">珠海到上海机票</a>
<a href="http://flights.ctrip.com/booking/SYX-SHA-day-1.html" title="三亚到上海机票" target="_blank">三亚到上海机票</a>
</p>
</div>
</div>

</div>
<div class="base_side rightcolumn" id="demo_side">
<div id="J_roundLowestPrice">
</div>
<div id="J_searchHistory">
</div>
<div class="mb10" style="display:none">
<a target="_blank" href="http://events.ctrip.com/flight/jiesongjihuodongpc.html#ctm_ref=Fld_sr_rec_carcoup" class="send_hotel_coupon"></a>
</div>
<div id="J_airlineLowestPrice">
</div>
<div id="J_rcmAirlineLowestPrice">
</div>
<div id="J_NearFlightRecommend">
</div>
<div class="mod_box mb10">
<a class="btn-block moment_icon1" data-ubt="FlightCalendar" href="http://flights.ctrip.com/schedule/HRB.SHA.html#ctm_ref=fld_sr_fsch_def_i_1" target="_blank">
<i></i>航班时刻表</a></div>
<div class="mod_box mb10">
<a class="btn-block information_icon1" data-ubt="FlightInfo" href="http://flights.ctrip.com/actualtime/HRB-SHA#ctm_ref=fld_sr_ftl_def_i_1" target="_blank">
<i></i>航班动态查询</a></div>


<div class="whyctrip2">
<h3>为什么选携程?</h3>
<div class="whyctrip2_main">
<a href="http://pages.ctrip.com/commerce/promote/201410/flight/jp/index.html#fld_sr_slg_def_t_1" data-ubt="SafeService" target="_blank">
<img data-ubt="SafeService" src="http://pic.c-ctrip.com/fltdomestic111027/choose_search.png">
</a>
</div>
</div>

</div>
<div class="seo_footer_new">
<div class="title">
携程网提供<a href="http://flights.ctrip.com/">特价机票</a>,<a href="http://flights.ctrip.com/schedule/">航班时刻表</a>,<a href="http://flights.ctrip.com/actualtime/">航班动态查询</a>:
</div>
<p class="p_text">携程机票为您提供<a href="http://flights.ctrip.com/booking/lowprice-HRB-SHA----adu-1/">哈尔滨到上海特价机票</a>,以及<a href="http://flights.ctrip.com/booking/china-city-flights-sitemap.html">飞机票价格查询</a>,<a href="http://flights.ctrip.com/booking/top">机票排行榜</a>,<a href="http://flights.ctrip.com/hot-flights.html">热门机票</a>,<a href="http://flights.ctrip.com/hot-airport.html">机场查询</a>.现在<a rel="nofollow" href="https://accounts.ctrip.com/member/emailregist.aspx" target="_blank">注册</a>携程会员即可获得1200积分和1300元消费券! </p>
<p><strong>哈尔滨到上海相关</strong> <a href="http://flights.ctrip.com/booking/HRB-SHA-day-1.html">哈尔滨到上海机票</a> <a href="http://flights.ctrip.com/schedule/HRB.SHA.html">哈尔滨到上海航班</a> <a href="http://flights.ctrip.com/actualtime/HRB-SHA/">哈尔滨到上海航班动态</a> <a href="http://flights.ctrip.com/booking/SHA-HRB-day-1.html">上海到哈尔滨机票</a> <a href="http://m.ctrip.com/html5/flight/HRB-SHA-day-1.html">哈尔滨到上海机票手机版</a></p>
<p><strong>旅行助手</strong> <a href="http://flights.ctrip.com/booking/hrb-haerbin-flights.html">哈尔滨特价机票</a> <a href="http://flights.ctrip.com/schedule/hrb..html">哈尔滨航班时刻表</a> <a href="http://flights.ctrip.com/actualtime/depart-hrb/">哈尔滨航班动态</a>
<a href="http://flights.ctrip.com/booking/airport-taiping/">太平国际机场</a>
<a href="http://flights.ctrip.com/actualtime/booking/top/city-hrb">哈尔滨机票排行榜</a> <a href="http://trains.ctrip.com/TrainBooking/haerbin/">哈尔滨火车票</a> <a href="http://trains.ctrip.com/TrainSchedule/haerbin/">哈尔滨火车时刻表</a> <a href="http://hotels.ctrip.com/hotel/haerbin5">哈尔滨酒店预订</a>

</p>
<p><strong>机票工具箱</strong><a href="http://flights.ctrip.com/booking/china-city-flights-sitemap.html" title="打折机票">打折机票</a> <a href="http://flights.ctrip.com/schedule/" title="航班查询时刻表">航班时刻表查询</a> <a href="http://flights.ctrip.com/actualtime/" title="航班实时起降查询">航班动态查询</a> <a href="http://flights.ctrip.com/hot-airport.html" title="热门机场">机场查询</a> <a href="http://flights.ctrip.com/booking/top" title="机票排行榜">机票排行榜</a> <a href="http://flights.ctrip.com/booking/hot-city-flights-sitemap.html" title="机票地图">机票地图</a> <a href="http://m.ctrip.com/html5/Flight/" title="机票手机版">机票手机版</a> <a href="http://www.skysea.com/" title="天海游轮">天海游轮</a> <a href="http://flights.ctrip.com/domestic/checkinseat/index" title="值机">值机</a></p>
<p><strong>打折机票</strong>
<a href="http://flights.ctrip.com/booking/sha-Shanghai-flights.html">上海特价机票</a>
<a href="http://flights.ctrip.com/booking/bjs-Beijing-flights.html">北京特价机票</a>
<a href="http://flights.ctrip.com/booking/can-Guangzhou-flights.html">广州特价机票</a>
<a href="http://flights.ctrip.com/booking/szx-Shenzhen-flights.html">深圳特价机票</a>
<a href="http://flights.ctrip.com/booking/ckg-Chongqing-flights.html">重庆特价机票</a>
<a href="http://flights.ctrip.com/booking/ctu-Chengdu-flights.html">成都特价机票</a>
<a href="http://flights.ctrip.com/booking/kmg-Kunming-flights.html">昆明特价机票</a>
<a href="http://flights.ctrip.com/booking/xmn-Xiamen-flights.html">厦门特价机票</a>
<a href="http://flights.ctrip.com/booking/syx-Sanya-flights.html"> 三亚特价机票</a>
<a href="http://flights.ctrip.com/booking/dlc-Dalian-flights.html"> 大连特价机票</a>
<a href="http://flights.ctrip.com/booking/ljg-Lijiang-flights.html">丽江特价机票</a>
<a href="http://flights.ctrip.com/booking/tsn-Tianjin-flights.html">天津特价机票</a>
<a href="http://flights.ctrip.com/booking/foc-Fuzhou-flights.html">福州特价机票</a>
<a href="http://flights.ctrip.com/booking/she-Shenyang-flights.html">沈阳特价机票</a>
<a href="http://flights.ctrip.com/booking/cgo-Zhengzhou-flights.html"> 郑州特价机票</a>
<a href="http://flights.ctrip.com/booking/tao-Qingdao-flights.html">青岛特价机票</a>
<a href="http://flights.ctrip.com/booking/sia-Xian-flights.html">西安特价机票</a>
<a href="http://flights.ctrip.com/booking/nkg-Nanjing-flights.html">南京特价机票</a>
<a href="http://flights.ctrip.com/booking/wuh-Wuhan-flights.html">武汉特价机票</a>
<a href="http://flights.ctrip.com/booking/hgh-Hangzhou-flights.html">杭州特价机票</a>
<a href="http://flights.ctrip.com/booking/china-city-flights-sitemap.html">更多特价机票</a>
</p>

</div>
<div id="ApplyProductWaitTimeTips" class="pop_v2_bd" style="display:none;">
<p style="padding: 10px 20px; text-align: center;">该机票我愿意从<span class="base_price">05月11日</span>等到:</p>
<p style="padding: 10px 20px; text-align: center;">
<label class="base_label" id="apChoose24">
<input type="radio" name="ApplyProductChoose" value="24" class="input_radio" />
24小时内
</label>
<label class="base_label" id="apChoose72" style="margin-right: 10px;">
<input type="radio" name="ApplyProductChoose" value="72" class="input_radio" />
72小时内
</label>
<label class="base_label" id="apChooseAll">
<input type="radio" name="ApplyProductChoose" value="0" class="input_radio" />
起飞前2小时</label>
</p>
<div style="padding: 10px; text-align: center;">
<input type="button" value="申 请" class="base_btns2" id="ApplyProductBtn" />
</div>
</div>

<input id="PackageItems1" type="hidden" value="" />
<input id="SmCorpFeeType1" type="hidden" value="" />
<input id="SmCorpData1" type="hidden" value="" />
<input id="SmCorpData" type="hidden" />
<input type="hidden" id="ab_testing_tracker" value="M:83,150323_fld_hltcp:E;M:58,160223_fld_bs3x:C;M:23,160303_fld_hscp:B;M:32,160225_fld_tsrec:B;M:58,160304_fld_pcbs:A;M:20,160316_fld_close:C;M:32,160225_fld_tsrec:B;" />
<input id="page_id" type="hidden" value="wait" />
<input id="RouteLowestPriceList" type="hidden" value='' />
<input id="RouteLowestPriceListSecond" type="hidden" />
<input id="ubtLog1" type="hidden" value="" />
<input id="commonKeyForUbt" name="flt_inland_search_click" type="hidden" value="flt_inland_search_click" />

<input id="isSingleToRound" type="hidden" value="" />
<script type="text/javascript">
var $$ = {module: { jmpInfo: { array: {} } } };
var RootUrl="http://flights.ctrip.com/domestic/";
var SEORootUrl="http://flights.ctrip.com/booking/";
var BookRootUrl="http://flights.ctrip.com/Book/";
var SearchRootUrl = "http://flights.ctrip.com/domesticsearch/search/";
var ProcessRootUrl = 'http://flights.ctrip.com/Process';
var IsQuickBooking="";
</script>


<div id="comfortable_jmp_text" style="display: none">
${txt0}
</div>


</div>
<script type="text/javascript">
window.ReleaseNo = "CR_2016_05_10_19_57_18";

window.onresize=window.onload = function () {
setFullScreen();
}
var pageWidth;

function setFullScreen() {
pageWidth = window.innerWidth;
if (typeof pageWidth != "number") {
if (document.compatMode == "CSS1Compat") {
pageWidth = document.documentElement.clientWidth;
} else {
pageWidth = document.body.clientWidth;
}
}
var body = document.getElementsByTagName("body")[0];
if (pageWidth <= 1250) {
if (/msie/i.test(navigator.userAgent)&&body.className.indexOf("width_change") == -1) {
body.className = "width_change";
}
//X档案前
if (document.getElementById("cui_nav_ul")) {
document.getElementById("cui_nav_ul").style.width = "980px";
document.getElementById("cui_hd").style.width = "980px";
}
//X档案后
//低价日历的宽度
var lowestPrice = document.getElementById("J_lowestPriceDateList");
if (lowestPrice != null) {
var par = lowestPrice.parentNode;
while (par.nodeType != 1) {
par = par.parentNode;
}
par.style.width = "748px";
if (window["moudule_init"]) {
Ctrip.Flight.Moudule.PriceCalendar.resetPosition();
}
}

//历史查询
var searchHistory = document.getElementById("searchHistory");
if (searchHistory != null && document.getElementById("searchHistory_box")!=null) {
document.getElementById("searchHistory_box").appendChild(searchHistory);
}
//相邻航线特惠 J_specialOffer
var nearFlightRecommend = document.getElementById("NearFlightRecommend");
if (nearFlightRecommend != null && document.getElementById("J_specialOffer")!=null) {
document.getElementById("J_specialOffer").appendChild(nearFlightRecommend);
}

}
else {
if (/msie/i.test(navigator.userAgent)&&body.className.indexOf("width_change") > -1) {

body.className = "";
}
//X档案前
if (document.getElementById("cui_nav_ul")) {
document.getElementById("cui_nav_ul").style.width = "1180px";
document.getElementById("cui_hd").style.width = "1180px";
}
//X档案后
//低价日历
var lowestPrice = document.getElementById("J_lowestPriceDateList");
if (lowestPrice != null) {
var par = lowestPrice.parentNode;
while (par.nodeType != 1) {
par = par.parentNode;
}
par.style.width = "728px";
if (window["moudule_init"]) {
Ctrip.Flight.Moudule.PriceCalendar.resetPosition();
}
}
//历史查询searchHistory
var searchHistory = document.getElementById("searchHistory");
if (searchHistory != null && document.getElementById("J_searchHistory")!=null) {
document.getElementById("J_searchHistory").appendChild(searchHistory);
}
//相邻航线特惠
var nearFlightRecommend=document.getElementById("NearFlightRecommend");
if (nearFlightRecommend != null && document.getElementById("J_NearFlightRecommend")!=null) {
document.getElementById("J_NearFlightRecommend").appendChild(nearFlightRecommend);
}
}
}
</script>

<script src="http://webresource.c-ctrip.com/code/cquery/LABjs/LAB.js" charset="utf-8" type="text/javascript"></script>

<script type="text/javascript">
var SearchCondition={"SearchType":"S","SearchRouteIndex":0,"DCity1":"HRB","DCityId1":5,"ACityId1":2,"ACityId2":0,"DCityName1":"哈尔滨","DPort1":"","ACity1":"SHA","ACityName1":"上海","APort1":"","ACity2":"","ACityName2":"","APort2":"","DDate1":"2016-05-13","DDate2":"","Quantity":1,"ClassType":"","PassengerType":"ADU","AirlineCode":"","AirlineName":"","DTimeRange":"","VipGrade":0,"DontDownloadData":false,"IsCivil":false,"DirectChannel":null,"IsSortByPrice":false,"CPCityId":5,"CK":"36B05DD175F36398546F66CA5EFD07DE","SaleChannel":"FlightOnline","IsShowOneNoCarAd":false,"HotelsCouponAbtestVersionInsuranceId":"C2C30","FlightXAdditionalProductsFlag":0,"IsRoundTrip":false,"IsNearAirportRecommond":"0","LogToken":"bab2b06f320f42898800a2cbf778a17a","ABTestInfo":[{"TestCode":"160304_fld_pcbs","TestVersion":"D"},{"TestCode":"160225_fld_tsrec","TestVersion":"B"}]};
var SelectedFlight1=null;
var pageConfig={
needSearch:true,
displayMode:0,
isRecommendTransit:true,
isOpenPOIAddress:true,
flightTemplate:[{"Key":"Icon_3USalePromotion","Content":"川航特卖季:订直销,享特价","ABTest":""},{"Key":"Icon_3USalePromotionType","Content":"特卖","ABTest":""}],
MD5UserID:"",
isOpenSearchRoundRecommend:true,
isSeparateShowRecommend:false ,
IsPromotionInfo: false,
isCivil:"",
isAirTrain:false,
isPreferetial:false,
vehicleType:"",
autosearchflightminute:10,
handlerIndex:"86,13-14,02-04-03",
airTrainDisplayMode:"1",
IsShowCoupon: true,
IsSearchRoundLowestPriceMore:true,
reTransitCount:5,
from:"",
isOpenFreeTravel:"T",
isOpenClassYPriceMarkup:"T",
IsShowMileage:"True",
TgqDetailAirlines:"CA,MU,FM,CZ,HU,SC",
ShowTgqDetailSubClass:"CA,MU,FM,CZ,HU,SC",
IsOpenTravelPrompt:"T",
TravelPromptType:"T",
TravelPromptMs:70,
AirLineConfig:"CA,MU,CZ,SC,JD,MF,FM,PN,AQ,KY,8L,GX,ZH,HO,QW,HU,GJ,FU,DZ,GS,3U,Y8,CN",
IsShowApplyTicketSuccessRate:true,
IsOpenRoundTripSpecial: true,
IsOpenRoundTripMultiReturn: true,
IsShowComfortable:false,
DirectSpread:0,
IsOpenDirectSpread:"T",
ApplyTicketMinSuccessRate:0.98,
HotelsCoupon:{HotelsCoupon:0,Insurance:1,HoteCoupon:2,HotelsCouponConfig:{n:"酒店优惠券",num:1,t:"HotelsCoupon",description:"<h5>酒店优惠券使用说明:</h5><ul class=\"decimal\"><li>包含1张100元酒店优惠券</li><li>适用于单价大于300元的国内酒店房型(含港澳台)</li><li>100元现金将在酒店订单成交后3个工作日内返还至您的携程账户</li><li>优惠券自发放之日起30天内有效</li><li>具体使用规则详见我携优惠券使用说明</li></ul>",originalPrice:100,p:25}},
VipGrade: "0|",
OrientThrow: true,
isFull:"",
RoundTripFlightLine:'',
RoundTripFlightNo:'',
RoundTripPrice:0,
TravelPackageAndRentCarHoverMessage:"适用产品:1)预订频道:携程用车-国内接送机频道;2)适用产品:产品左上角带有“专享”标签的国内接送机产品;3)使用限制:用车时间不限,支持网站及手机预订使用,每张订单优惠{{printprice}}元,优惠券自发券日起90天内预订使用有效;|||",
IsShowComfortableMessage:false,
DefaultSortSwitcher:true,
IpCityCheckSwitcher:false,
IpCityCheckTimeRange:"07:00-22:30",
ReroundExceptAirlines:"CZ",
ShowPackageShopExceptAirlines:"CZ",
GiftActivitiesRoutePopupMessage:'',
HideTicketMinSuccessRate:0.5,
ReplaceAirLineMarketingInsurance:'<ul class="decimal"><li style="font-size: 12px;font-family: Arial,Tahoma,simsun;">保险名称:中航三星航意险30</li><li style="font-size: 12px;font-family: Arial,Tahoma,simsun;">份数限制:购买上限5份;</li><li style="font-size: 12px;font-family: Arial,Tahoma,simsun;">保险有效期:指被保险人每次以乘客身份,乘坐电子保单载明的合法商业运营的客运飞机班次,并遵守承运人关于安全乘坐的规定,自持有效机票检票并进入所乘客运飞机客舱时起至抵达机票载明的终点离开所乘客运飞机客舱的期间内遭受意外伤害所导致的保险责任;</li><li style="font-size: 12px;font-family: Arial,Tahoma,simsun;">保险费:&yen;30/份; </li><li style="font-size: 12px;font-family: Arial,Tahoma,simsun;">保额:航空意外伤害保险责任&yen;120万,航空意外伤害医疗责任最高可赔付&yen;5万元</li><li style="font-size: 12px;font-family: Arial,Tahoma,simsun;">售出可退(乘机日之前)</li><li style="font-size: 12px;font-family: Arial,Tahoma,simsun;">年龄:出生30天(含)至100周岁</li><li style="font-size: 12px;font-family: Arial,Tahoma,simsun;">保险公司将委托携程在各地有资质的服务商为有需要的客户提供保险定额发票以作报销。保险定额发票仅作报销凭证,不是保单凭证;</li><li style="font-size: 12px;font-family: Arial,Tahoma,simsun;">数据电文是合法的合同表现形式,电子保单与纸质保单具有同等法律效力,请妥善保存。电子保单可在保险公司网站上查询和下载;</li><li style="font-size: 12px;font-family: Arial,Tahoma,simsun;">产品详细条款可致电中航三星人寿热线400-810-1888或登录http://www.ssac.com.cn/进行垂询。</li></ul>',
IsShowSharedFlight:true,
IsOpenSendFSR:true,
IsShowUpgradeClass:true,
AirLineMarketingConfig:"AQ,PN,KN",
ShowAvatarOfAirlineMarketing:true,
UpgradeClassDescription:{ZH:"<p>购买深航超值经济舱:</p><ul ><li>&#183;保证<strong style=color:#f60;>100%</strong>免费升级至尊鹏头等舱。</li><li>&#183;享受机场贵宾休息室、空中专属服务等全程礼遇。</li><li>&#183;免费行李额40KG,按200%比例累积里程。</li><li>&#183;报销凭证为升舱后头等舱行程单。</li></ul>"},
IsShowFlightAgent:false,
IgnoreFreeTravelAirline:"9C",
IsOpenAnnouncement:"T",
AirLineInsuranceConfig:"CA,1200000",
SichuanAirlinesConfig:"CTU",
IsOpenAsyncGetTGQ:true,
isTopAMT:true,
topAMTCode:"cz,sc,mu,ca,jd,mf,fm,pn,aq,ky,8l,gx,zh,ho,qw,hu,gj,fu,dz,gs,3u,y8,cn",
strictMKTAirline:"CZ|AirLineMarketing,CZ|AvatarOfAirlineMarketing|CZ|BusinessPriority,CZ|TravelPackage,CZ|PriorityPackage,CZ|BusinessProduct,CZ|BusinessPackage,CA|AirLineMarketing,CA|AvatarOfAirlineMarketing,MU|AirLineMarketing,MU|AvatarOfAirlineMarketing,FM|AirLineMarketing,FM|AvatarOfAirlineMarketing,HU|AirLineMarketing,HU|AvatarOfAirlineMarketing,3U|AirLineMarketing,3U|AvatarOfAirlineMarketing,8C|AirLineMarketing,8C|AvatarOfAirlineMarketing,8L|AirLineMarketing,8L|AvatarOfAirlineMarketing,9C|AirLineMarketing,9C|AvatarOfAirlineMarketing,A6|AirLineMarketing,A6|AvatarOfAirlineMarketing,AQ|AirLineMarketing,AQ|AvatarOfAirlineMarketing,BK|AirLineMarketing,BK|AvatarOfAirlineMarketing,CN|AirLineMarketing,CN|AvatarOfAirlineMarketing,DR|AirLineMarketing,DR|AvatarOfAirlineMarketing,DZ|AirLineMarketing,DZ|AvatarOfAirlineMarketing,EU|AirLineMarketing,EU|AvatarOfAirlineMarketing,FU|AirLineMarketing,FU|AvatarOfAirlineMarketing,G5|AirLineMarketing,G5|AvatarOfAirlineMarketing,GJ|AirLineMarketing,GJ|AvatarOfAirlineMarketing,GS|AirLineMarketing,GS|AvatarOfAirlineMarketing,GX|AirLineMarketing,GX|AvatarOfAirlineMarketing,GY|AirLineMarketing,GY|AvatarOfAirlineMarketing,HO|AirLineMarketing,HO|AvatarOfAirlineMarketing,JD|AirLineMarketing,JD|AvatarOfAirlineMarketing,JR|AirLineMarketing,JR|AvatarOfAirlineMarketing,KN|AirLineMarketing,KN|AvatarOfAirlineMarketing,KY|AirLineMarketing,KY|AvatarOfAirlineMarketing,MF|AirLineMarketing,MF|AvatarOfAirlineMarketing,NS|AirLineMarketing,NS|AvatarOfAirlineMarketing,OQ|AirLineMarketing,OQ|AvatarOfAirlineMarketing,PN|AirLineMarketing,PN|AvatarOfAirlineMarketing,QW|AirLineMarketing,QW|AvatarOfAirlineMarketing,RY|AirLineMarketing,RY|AvatarOfAirlineMarketing,SC|AirLineMarketing,SC|AvatarOfAirlineMarketing,TV|AirLineMarketing,TV|AvatarOfAirlineMarketing,UQ|AirLineMarketing,UQ|AvatarOfAirlineMarketing,VD|AirLineMarketing,VD|AvatarOfAirlineMarketing,Y8|AirLineMarketing,Y8|AvatarOfAirlineMarketing,YI|AirLineMarketing,YI|AvatarOfAirlineMarketing,ZH|AirLineMarketing,ZH|AvatarOfAirlineMarketing,CA|PriorityPackage,CA|TravelPackage,MU|PriorityPackage,MU|TravelPackage,FM|PriorityPackage,FM|TravelPackage,HU|PriorityPackage,HU|TravelPackage,3U|PriorityPackage,3U|TravelPackage,8C|PriorityPackage,8C|TravelPackage,8L|PriorityPackage,8L|TravelPackage,9C|PriorityPackage,9C|TravelPackage,A6|PriorityPackage,A6|TravelPackage,AQ|PriorityPackage,AQ|TravelPackage,BK|PriorityPackage,BK|TravelPackage,CN|PriorityPackage,CN|TravelPackage,DR|PriorityPackage,DR|TravelPackage,DZ|PriorityPackage,DZ|TravelPackage,EU|PriorityPackage,EU|TravelPackage,FU|PriorityPackage,FU|TravelPackage,G5|PriorityPackage,G5|TravelPackage,GJ|PriorityPackage,GJ|TravelPackage,GS|PriorityPackage,GS|TravelPackage,GX|PriorityPackage,GX|TravelPackage,GY|PriorityPackage,GY|TravelPackage,HO|PriorityPackage,HO|TravelPackage,JD|PriorityPackage,JD|TravelPackage,JR|PriorityPackage,JR|TravelPackage,KN|PriorityPackage,KN|TravelPackage,KY|PriorityPackage,KY|TravelPackage,MF|PriorityPackage,MF|TravelPackage,NS|PriorityPackage,NS|TravelPackage,OQ|PriorityPackage,OQ|TravelPackage,PN|PriorityPackage,PN|TravelPackage,QW|PriorityPackage,QW|TravelPackage,RY|PriorityPackage,RY|TravelPackage,SC|PriorityPackage,SC|TravelPackage,TV|PriorityPackage,TV|TravelPackage,UQ|PriorityPackage,UQ|TravelPackage,VD|PriorityPackage,VD|TravelPackage,Y8|PriorityPackage,Y8|TravelPackage,YI|PriorityPackage,YI|TravelPackage,ZH|PriorityPackage,ZH|TravelPackage",
UpgradeClass:false,
PackageCouponConfig1:'1.可用于携程国内旅游和出境游产品(不参加优惠券活动的产品除外);<br/>2.购买旅游度假产品订单满<dfn>&yen;</dfn><strong class="base_price">5000</strong><dfn>&yen;</dfn><strong class="base_price">100</strong>、满<dfn>&yen;</dfn><strong class="base_price">10000</strong><dfn>&yen;</dfn><strong class="base_price">200</strong>、满<dfn>&yen;</dfn><strong class="base_price">15000</strong><dfn>&yen;</dfn><strong class="base_price">300</strong>、满<dfn>&yen;</dfn><strong class="base_price">20000</strong><dfn>&yen;</dfn><strong class="base_price">400</strong>、满<dfn>&yen;</dfn><strong class="base_price">50000</strong><dfn>&yen;</dfn><strong class="base_price">1000</strong>,每订单每个优惠券限用一次。不适用于签证、欧铁、用车、顶级游、门票、景点+酒店套餐及不参与优惠券活动的特例产品。优惠券不可与其他优惠活动同时使用。请登陆后输入代码确认可否使用。(有效期至${EffectDate});<br/>注:本产品特供网络及手机客户端用户专享',
PackageCouponConfig2:'1.可用于携程国内旅游和出境游产品(不参加优惠券活动的产品除外);<br/>2.购买旅游度假产品订单满<dfn>&yen;</dfn><strong class="base_price">5000</strong><dfn>&yen;</dfn><strong class="base_price">100</strong>、满<dfn>&yen;</dfn><strong class="base_price">10000</strong><dfn>&yen;</dfn><strong class="base_price">200</strong>、满<dfn>&yen;</dfn><strong class="base_price">20000</strong><dfn>&yen;</dfn><strong class="base_price">400</strong>、满<dfn>&yen;</dfn><strong class="base_price">50000</strong><dfn>&yen;</dfn><strong class="base_price">1000</strong>、满<dfn>&yen;</dfn><strong class="base_price">100000</strong><dfn>&yen;</dfn><strong class="base_price">2000</strong>,每订单每个优惠券限用一次。不适用于签证、欧铁、用车、顶级游、门票、景点+酒店套餐及不参与优惠券活动的特例产品。优惠券不可与其他优惠活动同时使用。请登陆后输入代码确认可否使用。(有效期至${EffectDate});<br/>注:本产品特供网络及手机客户端用户专享',
CXTAirlinesConfig:[{"alc":"G5","sts":"ALL","ste":"ALL","dts":"2015-12-01 00:00:00","dte":"2015-12-31 23:59:59","tt":"华夏航特惠","te":"本产品由华夏航提供,专享0元火车票","cs":"ALL","fns":"ALL","transits":"CKG","routes":[{"dcc":"ALL","acc":"ALL"}]},{"alc":"-3U","sts":"2016-01-04 00:00:00","ste":"2016-01-17 23:59:59","dts":"ALL","dte":"ALL","tt":"重庆飞特惠","te":"本产品由重庆机场特别提供火车票减免优惠","cs":"ALL","fns":"ALL","transits":"CKG","routes":[{"dcc":"ALL","acc":"ALL"}]},{"alc":"3U","sts":"ALL","ste":"ALL","dts":"2015-12-01 00:00:00","dte":"2015-12-31 23:59:59","tt":"川行通特惠","te":"本产品由四川航空 “ 川行通 ” 特别提供","cs":"ALL","fns":"ALL","transits":"ALL","routes":[{"dcc":"ALL","acc":"ALL"}]},{"alc":"PN","sts":"ALL","ste":"ALL","dts":"ALL","dte":"ALL","tt":"西航“欢天·喜地”","te":"本优惠产品由西部航空特别提供","cs":"ALL","fns":"ALL","transits":"ALL","routes":[{"dcc":"ALL","acc":"ALL"}]}],
pcCodeAirlineName:{CA:"国航",KY:"昆明航空",ZH:"深航","3U":"川航"},
freeAdditionalProducts:[{"Id":0,"Type":7,"OrderType":16,"OrderProductType":256,"ProductType":5,"Name":"酒店优惠券","SubTitle":"抵用<dfn>&yen;</dfn>100","Count":1,"PrintPrice":100,"SalePrice":0,"OrderDescription":"<div><strong>酒店优惠券使用说明:</strong><br />1.包含1张100元酒店优惠券。<br />2.适用于单价大于500元的国内酒店(含港澳台)房型(旅行社、团购、小时房、特价房除外)。<br />3.使用优惠券成功预订并入住、在订单成交后3个工作日内,100元将返还至您的携程账户。<br />4.每张优惠券限用一次,每张订单限用一张优惠券,优惠券不得转赠他人。<br />5.优惠券自发放之日起14天内有效。<br />6.订单取消后,优惠券将实时退还到账户(实际未入住用户除外)。<br />7.该优惠券不可退。</div>","Description":"<strong>酒店优惠券使用说明:</strong><br />1.包含1张100元酒店优惠券。<br />2.适用于单价大于500元的国内酒店(含港澳台)房型(旅行社、团购、小时房、特价房除外)。<br />3.使用优惠券成功预订并入住、在订单成交后3个工作日内,100元将返还至您的携程账户。<br />4.每张优惠券限用一次,每张订单限用一张优惠券,优惠券不得转赠他人。<br />5.优惠券自发放之日起14天内有效。<br />6.订单取消后,优惠券将实时退还到账户(实际未入住用户除外)。<br />7.该优惠券不可退。","BookDescription":"","ProductCode":"","ExpiryMonths":3,"ExpiryStartTime":"2016-05-11 07:10:48","IsSelected":false,"XProductType":0,"CssName":"combo_icon5","Index":0,"SelectMode":0,"Fields":null,"RuleId":0},{"Id":0,"Type":8,"OrderType":17,"OrderProductType":128,"ProductType":5,"Name":"接送机券","SubTitle":"抵用<dfn>&yen;</dfn>70","Count":1,"PrintPrice":70,"SalePrice":0,"OrderDescription":"<div><strong>接送机券使用说明:</strong><br />1.可用于携程用车-国内接送机频道中带有“专享”标签的国内接送机产品;<br />2.用车时间不限,支持网站及手机预订使用,每张订单优惠70元,优惠券自发券日起90天内预订使用有效;<br />3.该优惠券不可退。</div>","Description":"<strong>接送机券使用说明:</strong><br />1.可用于携程用车-国内接送机频道中带有“专享”标签或“机票特权”国内接送机产品;<br />2.用车时间不限,支持网站及手机预订使用,每张订单优惠70元,优惠券自发券日起90天内预订使用有效;<br />3.该优惠券不可退。","BookDescription":"","ProductCode":"","ExpiryMonths":3,"ExpiryStartTime":"2016-05-11 07:10:48","IsSelected":false,"XProductType":0,"CssName":"combo_icon5","Index":0,"SelectMode":0,"Fields":null,"RuleId":0}],
additionalProducts:[{"Id":0,"Type":5,"OrderType":9,"OrderProductType":9,"ProductType":1,"Name":"酒店优惠券","SubTitle":"抵用<dfn>&yen;</dfn>100","Count":1,"PrintPrice":100,"SalePrice":25,"OrderDescription":"<div><strong>酒店优惠券使用说明:</strong><br />1.包含1张100元酒店优惠券。<br />2.适用于单价大于300元的国内酒店(含港澳台)房型(旅行社、团购、小时房、特价房除外)。<br />3.100元现金将在酒店订单成交后3个工作日内返还至您的携程账户。<br />4.优惠券自发放之日起30天内有效。<br />5.每张优惠券限用一次,每张订单限用一张优惠券,优惠券不得转赠他人。<br />6.订单取消后,优惠券将实时退还到账户(实际未入住用户除外)。<br />7.优惠券不支持单独退订;已使用或已过期优惠券的套餐订单若发生退订,需在支付退订费时退还相应优惠券金额。</div>","Description":"<strong>酒店优惠券使用说明:</strong><br />1.包含1张100元酒店优惠券。<br />2.适用于单价大于300元的国内酒店(含港澳台)房型(旅行社、团购、小时房、特价房除外)。<br />3.100元现金将在酒店订单成交后3个工作日内返还至您的携程账户。<br />4.优惠券自发放之日起30天内有效。<br />5.每张优惠券限用一次,每张订单限用一张优惠券,优惠券不得转赠他人。<br />6.订单取消后,优惠券将实时退还到账户(实际未入住用户除外)。<br />7.优惠券不支持单独退订;已使用或已过期优惠券的套餐订单若发生退订,需在支付退订费时退还相应优惠券金额。","BookDescription":"","ProductCode":"33","ExpiryMonths":3,"ExpiryStartTime":"2016-05-11 07:10:48","IsSelected":true,"XProductType":0,"CssName":"combo_icon5","Index":0,"SelectMode":0,"Fields":null,"RuleId":0},{"Id":0,"Type":1,"OrderType":0,"OrderProductType":0,"ProductType":3,"Name":"航空意外险","SubTitle":"最高赔付&yen;320万","Count":1,"PrintPrice":30,"SalePrice":30,"OrderDescription":"","Description":"<ul><li>1、保险责任:指被保险人持有效机票检票并进入保单载明的合法商业运营的客运飞机客舱时起至抵达机票载明的终点离开客运飞机客舱的期间内遭受意外伤害所导致的保险责任;</li><li>2、保额:航空意外伤害保险责任320万元/航段;选择国航直连订单保险责任变更为120万元/航段,由中银三星承保;</li><li>3、保险费:30元/航段,计划起飞时间之前退票可退保;</li><li>4、本产品由太平洋寿险、中国人寿、阳光人寿、众安在线、天安财险、华夏人寿、国华人寿、新华人寿、中银三星、太平养老、大都会人寿等保险公司承保,销售服务方为携程保险代理有限公司 </li></ul>","BookDescription":"","ProductCode":"C2C30","ExpiryMonths":3,"ExpiryStartTime":"2016-05-11 07:10:48","IsSelected":false,"XProductType":0,"CssName":"combo_icon3","Index":0,"SelectMode":0,"Fields":null,"RuleId":0},{"Id":0,"Type":6,"OrderType":18,"OrderProductType":18,"ProductType":1,"Name":"门票礼包","SubTitle":"抵用<dfn>&yen;</dfn>100","Count":1,"PrintPrice":50,"SalePrice":30,"OrderDescription":"<div><strong>【50元门票优惠券】</strong><br />1.本优惠券可用于抵扣部分预付类国内门票产品,订单满200元减50元。<br />2.有效期内每张优惠券仅限使用一次,不能和其他优惠共享。<br />3.如发现恶意盗刷优惠券等行为,携程有权收回该行为涉及的优惠券,并取消所购产品。<br />4.该优惠券不可退。<br /><strong>【50元玩乐优惠券】</strong><br />1.本优惠券可用于抵扣部分当地玩乐频道预付类国内一日游产品,订单满200元减50元。<br />2.有效期内每张优惠券仅限使用一次,不能和其他优惠共享。<br />3.如发现恶意盗刷优惠券等行为,携程有权收回该行为涉及的优惠券,并取消所购品。<br />4.该优惠券不可退。</div>","Description":"<strong>【50元门票优惠券】</strong><br />1.本优惠券可用于抵扣部分预付类国内门票产品,订单满200元减50元。<br />2.有效期内每张优惠券仅限使用一次,不能和其他优惠共享。<br />3.如发现恶意盗刷优惠券等行为,携程有权收回该行为涉及的优惠券,并取消所购产品。<br />4.该优惠券不可退。<br /><strong>【50元玩乐优惠券】</strong><br />1.本优惠券可用于抵扣部分当地玩乐频道预付类国内一日游产品,订单满200元减50元。<br />2.有效期内每张优惠券仅限使用一次,不能和其他优惠共享。<br />3.如发现恶意盗刷优惠券等行为,携程有权收回该行为涉及的优惠券,并取消所购品。<br />4.该优惠券不可退。","BookDescription":"","ProductCode":"34","ExpiryMonths":3,"ExpiryStartTime":"2016-05-11 07:10:48","IsSelected":false,"XProductType":0,"CssName":"combo_icon4","Index":0,"SelectMode":0,"Fields":null,"RuleId":0}],
YPlusProducts:[{"Id":0,"Type":1,"OrderType":0,"OrderProductType":0,"ProductType":14,"Name":"抢票保障金","SubTitle":"抢票失败退一赔一","Count":1,"PrintPrice":300,"SalePrice":300,"OrderDescription":"","Description":"<strong>抢票保障金说明</strong><br />1、购买抢票保证金可提高抢票成功率至90%。<br />2、抢票保障金在抢票成功后不予退还。<br />3、抢票保障金在抢票失败后不予退还,票价(不含税)退一赔一。<br />4、抢票结果最晚起飞前${PromiseMinutes}告知。","BookDescription":"","ProductCode":"","ExpiryMonths":3,"ExpiryStartTime":"2016-05-11 07:10:48","IsSelected":false,"XProductType":0,"CssName":"combo_icon3","Index":0,"SelectMode":0,"Fields":null,"RuleId":0},{"Id":0,"Type":2,"OrderType":0,"OrderProductType":0,"ProductType":0,"Name":"抢票保障金","SubTitle":"抢票成功率${SuccessRate}%","Count":1,"PrintPrice":0,"SalePrice":0,"OrderDescription":"","Description":"<strong>抢票保障金说明</strong><br />1、购买抢票保证金可提高抢票成功率至90%。<br />2、抢票保障金在抢票成功后不予退还。<br />3、抢票保障金在抢票失败后不予退还,票价(不含税)退一赔一。<br />4、抢票结果最晚起飞前${PromiseMinutes}告知。","BookDescription":"","ProductCode":"","ExpiryMonths":3,"ExpiryStartTime":"2016-05-11 07:10:48","IsSelected":false,"XProductType":0,"CssName":"combo_icon3","Index":0,"SelectMode":0,"Fields":null,"RuleId":0}],
additionalProductsReplaceRules:[{"Filter":{"AirlineCode":"^(CA){1}$","SaleType":"^(AirLineMarketing|AvatarOfAirlineMarketing){1}$"},"ReplaceRule":{"1":{"Id":0,"Type":2,"OrderType":0,"OrderProductType":0,"ProductType":3,"Name":"航空意外险","SubTitle":"最高赔付<dfn>&yen;</dfn>120万","Count":1,"PrintPrice":30,"SalePrice":30,"OrderDescription":"","Description":"<ul class=\"decimal\"><li style=\"font-size: 12px;font-family: Arial,Tahoma,simsun;\">保险责任:指被保险人持有效机票检票并进入保单载明的合法商业运营的客运飞机客舱时起至抵达机票载明的终点离开客运飞机客舱的期间内遭受意外伤害所导致的保险责任;</li><li style=\"font-size: 12px;font-family: Arial,Tahoma,simsun;\">保额:航空意外伤害保险责任120万元/航段;</li><li style=\"font-size: 12px;font-family: Arial,Tahoma,simsun;\">保险费:30元/航段,计划起飞时间之前退票可退保;</li><li style=\"font-size: 12px;font-family: Arial,Tahoma,simsun;\">发票:提供保险定额发票作为报销凭证; </li><li style=\"font-size: 12px;font-family: Arial,Tahoma,simsun;\">保单验真:<a href=\"http://www.ssac.com.cn/Online/FlightInsQuery.aspx?ColumnId=131\" target=\"_blank\">http://www.ssac.com.cn/Online/FlightInsQuery.aspx?ColumnId=131</a></li><li style=\"font-size: 12px;font-family: Arial,Tahoma,simsun;\">本产品由中银三星承保,销售服务方为携程保险代理有限公司;</li></ul>","BookDescription":"","ProductCode":"C2C30","ExpiryMonths":3,"ExpiryStartTime":"2016-05-11 07:10:48","IsSelected":false,"XProductType":0,"CssName":"combo_icon3","Index":0,"SelectMode":1,"Fields":null,"RuleId":0}}},{"Filter":{"ExtensionFlag":"512"},"ReplaceRule":{"1":{"Id":0,"Type":4,"OrderType":7,"OrderProductType":8,"ProductType":1,"Name":"景酒优惠券","SubTitle":"抵用<dfn>&yen;</dfn>50","Count":1,"PrintPrice":50,"SalePrice":30,"OrderDescription":"<div><strong>景酒优惠券使用说明:</strong><br />1.包含1张50元优惠券,可用于抵扣携程旅游/酒店-酒店+景点频道下的旅游产品;<br />2.每张酒店+景点(自驾游)订单限用一张优惠券,满800-50元,每张优惠券限用1次(有效期自领券日起150天内出行预订有效)。<br />3.该优惠券不可退。</div>","Description":"<strong>景酒优惠券使用说明:</strong><br />1.包含1张50元优惠券,可用于抵扣携程旅游/酒店-酒店+景点频道下的旅游产品;<br />2.每张酒店+景点(自驾游)订单限用一张优惠券,满800-50元,每张优惠券限用1次(有效期自领券日起150天内出行预订有效)。<br />3.该优惠券不可退。","BookDescription":"","ProductCode":"35","ExpiryMonths":3,"ExpiryStartTime":"2016-05-11 07:10:48","IsSelected":false,"XProductType":0,"CssName":"combo_icon5","Index":0,"SelectMode":0,"Fields":null,"RuleId":0}}},{"Filter":{"ExtensionFlag":"4","ProductSource":"1"},"ReplaceRule":{"1":{"Id":0,"Type":4,"OrderType":7,"OrderProductType":8,"ProductType":1,"Name":"景酒优惠券","SubTitle":"抵用<dfn>&yen;</dfn>50","Count":1,"PrintPrice":50,"SalePrice":30,"OrderDescription":"<div><strong>景酒优惠券使用说明:</strong><br />1.包含1张50元优惠券,可用于抵扣携程旅游/酒店-酒店+景点频道下的旅游产品;<br />2.每张酒店+景点(自驾游)订单限用一张优惠券,满800-50元,每张优惠券限用1次(有效期自领券日起150天内出行预订有效)。<br />3.该优惠券不可退。</div>","Description":"<strong>景酒优惠券使用说明:</strong><br />1.包含1张50元优惠券,可用于抵扣携程旅游/酒店-酒店+景点频道下的旅游产品;<br />2.每张酒店+景点(自驾游)订单限用一张优惠券,满800-50元,每张优惠券限用1次(有效期自领券日起150天内出行预订有效)。<br />3.该优惠券不可退。","BookDescription":"","ProductCode":"35","ExpiryMonths":3,"ExpiryStartTime":"2016-05-11 07:10:48","IsSelected":false,"XProductType":0,"CssName":"combo_icon5","Index":0,"SelectMode":0,"Fields":null,"RuleId":0}}},{"Filter":{"ExtensionFlag":"4","ProductSource":"3"},"ReplaceRule":{"1":{"Id":0,"Type":4,"OrderType":7,"OrderProductType":8,"ProductType":1,"Name":"景酒优惠券","SubTitle":"抵用<dfn>&yen;</dfn>50","Count":1,"PrintPrice":50,"SalePrice":30,"OrderDescription":"<div><strong>景酒优惠券使用说明:</strong><br />1.包含1张50元优惠券,可用于抵扣携程旅游/酒店-酒店+景点频道下的旅游产品;<br />2.每张酒店+景点(自驾游)订单限用一张优惠券,满800-50元,每张优惠券限用1次(有效期自领券日起150天内出行预订有效)。<br />3.该优惠券不可退。</div>","Description":"<strong>景酒优惠券使用说明:</strong><br />1.包含1张50元优惠券,可用于抵扣携程旅游/酒店-酒店+景点频道下的旅游产品;<br />2.每张酒店+景点(自驾游)订单限用一张优惠券,满800-50元,每张优惠券限用1次(有效期自领券日起150天内出行预订有效)。<br />3.该优惠券不可退。","BookDescription":"","ProductCode":"35","ExpiryMonths":3,"ExpiryStartTime":"2016-05-11 07:10:48","IsSelected":false,"XProductType":0,"CssName":"combo_icon5","Index":0,"SelectMode":0,"Fields":null,"RuleId":0}}},{"Filter":{"SaleType":"^BusinessPackage$","AbTestValue":"150323_fld_hltcp:G"},"ReplaceRule":{"4":{"Id":0,"Type":5,"OrderType":9,"OrderProductType":9,"ProductType":1,"Name":"酒店优惠券","SubTitle":"抵用<dfn>&yen;</dfn>100","Count":1,"PrintPrice":100,"SalePrice":25,"OrderDescription":"<div><strong>酒店优惠券使用说明:</strong><br />1.包含1张100元酒店优惠券。<br />2.适用于单价大于300元的国内酒店(含港澳台)房型(旅行社、团购、小时房、特价房除外)。<br />3.100元现金将在酒店订单成交后3个工作日内返还至您的携程账户。<br />4.优惠券自发放之日起30天内有效。<br />5.每张优惠券限用一次,每张订单限用一张优惠券,优惠券不得转赠他人。<br />6.订单取消后,优惠券将实时退还到账户(实际未入住用户除外)。<br />7.优惠券不支持单独退订;已使用或已过期优惠券的套餐订单若发生退订,需在支付退订费时退还相应优惠券金额。</div>","Description":"<strong>酒店优惠券使用说明:</strong><br />1.包含1张100元酒店优惠券。<br />2.适用于单价大于300元的国内酒店(含港澳台)房型(旅行社、团购、小时房、特价房除外)。<br />3.100元现金将在酒店订单成交后3个工作日内返还至您的携程账户。<br />4.优惠券自发放之日起30天内有效。<br />5.每张优惠券限用一次,每张订单限用一张优惠券,优惠券不得转赠他人。<br />6.订单取消后,优惠券将实时退还到账户(实际未入住用户除外)。<br />7.优惠券不支持单独退订;已使用或已过期优惠券的套餐订单若发生退订,需在支付退订费时退还相应优惠券金额。","BookDescription":"","ProductCode":"33","ExpiryMonths":3,"ExpiryStartTime":"2016-05-11 07:10:48","IsSelected":false,"XProductType":0,"CssName":"combo_icon5","Index":0,"SelectMode":1,"Fields":null,"RuleId":0}}}],
additionalProductContentInfos:[{"ID":"1_0","SubTitle":"抵用<dfn>&yen;</dfn>${PrintPrice}","OrderDescription":"<div><strong>接送机券使用说明:</strong><br />1.可用于携程用车-国内接送机频道中产品左上角带有“专享”标签的国内接送机产品;<br />2.用车时间不限,支持网站及手机预订使用,每张订单优惠${PrintPrice}元,优惠券自发券日起90天内预订使用有效;<br />3.优惠券在有效期内未使用可随机票一起退订,若优惠券已使用或超过使用有效期限,订单发生退订时须返还相应优惠券金额。</div>","Description":"<strong>接送机券使用说明:</strong><br />1.可用于携程用车-国内接送机频道中带有“专享”标签或“机票特权”国内接送机产品;<br />2.用车时间不限,支持网站及手机预订使用,每张订单优惠${PrintPrice}元,优惠券自发券日起90天内预订使用有效;<br />3.优惠券在有效期内未使用可随机票一起退订,若优惠券已使用或超过使用有效期限,订单发生退订时须返还相应优惠券金额。","BookDescription":"<strong>接送机券使用说明:</strong><br />1.可用于携程用车-国内接送机频道中带有“专享”标签或“机票特权”国内接送机产品;<br />2.用车时间不限,支持网站及手机预订使用,每张订单优惠${PrintPrice}元,优惠券自发券日起90天内预订使用有效;<br />3.优惠券在有效期内未使用可随机票一起退订,若优惠券已使用或超过使用有效期限,订单发生退订时须返还相应优惠券金额。","ExpiryMonths":3},{"ID":"8_0","SubTitle":"抵用<dfn>&yen;</dfn>${PrintPrice}","OrderDescription":"<div><strong>接送机券使用说明:</strong><br />1.可用于携程用车-国内接送机频道中产品左上角带有“专享”标签的国内接送机产品;<br />2.用车时间不限,支持网站及手机预订使用,每张订单优惠${PrintPrice}元,优惠券自发券日起90天内预订使用有效。</div>","Description":"<strong>接送机券使用说明:</strong><br />1.可用于携程用车-国内接送机频道中带有“专享”标签或“机票特权”国内接送机产品;<br />2.用车时间不限,支持网站及手机预订使用,每张订单优惠${PrintPrice}元,优惠券自发券日起90天内预订使用有效。","BookDescription":"<strong>接送机券使用说明:</strong><br />1.可用于携程用车-国内接送机频道中带有“专享”标签或“机票特权”国内接送机产品;<br />2.用车时间不限,支持网站及手机预订使用,每张订单优惠${PrintPrice}元,优惠券自发券日起90天内预订使用有效。","ExpiryMonths":3},{"ID":"0_1","SubTitle":"抵用<dfn>&yen;</dfn>${PrintPrice}","OrderDescription":"<div><h4>${DepartCityName}${DepartPortName}贵宾休息室使用说明:</h4><ul><li>1)可提供<strong>免费餐饮、专属wifi、登机提醒</strong>等超值贵宾服务和更<strong>舒适的候机环境</strong>,具体服务不同机场可能存在不同;</li><li>2)使用时长2小时,航班起飞日起15天内有效;</li><li>3)2周岁以下婴儿免费 。</li></ul></div>","Description":"<h4>${DepartCityName}${DepartPortName}贵宾休息室使用说明:</h4><ul><li>1)可提供<strong>免费餐饮、专属wifi、登机提醒</strong>等超值贵宾服务和更<strong>舒适的候机环境</strong>,具体服务不同机场可能存在不同;</li><li>2)使用时长2小时,航班起飞日起15天内有效;</li><li>3)2周岁以下婴儿免费 。</li></ul>","BookDescription":"<h4>${DepartCityName}${DepartPortName}贵宾休息室使用说明:</h4><ul><li>1)可提供<strong>免费餐饮、专属wifi、登机提醒</strong>等超值贵宾服务和更<strong>舒适的候机环境</strong>,具体服务不同机场可能存在不同;</li><li>2)使用时长2小时,航班起飞日起15天内有效;</li><li>3)2周岁以下婴儿免费 。</li></ul>","ExpiryMonths":3},{"ID":"512_0","SubTitle":"抵用<dfn>&yen;</dfn>${PrintPrice}","OrderDescription":"<strong>酒店优惠券使用说明:</strong><br />1.包含1张100元酒店优惠券。<br />2.适用于单价大于300元的国内酒店(含港澳台)房型(旅行社、团购、小时房、特价房除外)。<br />3.使用优惠券成功预订并入住、在订单成交后3个工作日内,100元将返还至您的携程账户。<br />4.每张优惠券限用一次,每张订单限用一张优惠券,优惠券不得转赠他人。<br />5.优惠券自发放之日起30天内有效。<br />6.订单取消后,优惠券将实时退还到账户(实际未入住用户除外)。<br />7.该优惠券不可退。","Description":"<strong>酒店优惠券使用说明:</strong><br />1.包含1张100元酒店优惠券。<br />2.适用于单价大于300元的国内酒店(含港澳台)房型(旅行社、团购、小时房、特价房除外)。<br />3.使用优惠券成功预订并入住、在订单成交后3个工作日内,100元将返还至您的携程账户。<br />4.每张优惠券限用一次,每张订单限用一张优惠券,优惠券不得转赠他人。<br />5.优惠券自发放之日起30天内有效。<br />6.订单取消后,优惠券将实时退还到账户(实际未入住用户除外)。<br />7.该优惠券不可退。","BookDescription":"<strong>酒店优惠券使用说明:</strong><br />1.包含1张100元酒店优惠券。<br />2.适用于单价大于300元的国内酒店(含港澳台)房型(旅行社、团购、小时房、特价房除外)。<br />3.使用优惠券成功预订并入住、在订单成交后3个工作日内,100元将返还至您的携程账户。<br />4.每张优惠券限用一次,每张订单限用一张优惠券,优惠券不得转赠他人。<br />5.优惠券自发放之日起30天内有效。<br />6.订单取消后,优惠券将实时退还到账户(实际未入住用户除外)。<br />7.该优惠券不可退。","ExpiryMonths":3}],
IsOpenDirectChuanCoupon:true,
HXOptimizeSwitch:false,
comfortableConfig:'{"0-35":60,"35-45":65,"45-55":70,"55-65":75,"65-75":80,"75-85":85,"85-999":95}',
flightSearchAD:'{ "list": [] }',
loungeCouponName:"接送机+休息室",
isCombineSearch:true,
IsUseAjaxTGQAmountReturnText:false,
strictMKTNormalClassAirline:"CA|AirLineMarketing,CA|AvatarOfAirlineMarketing,CZ|AirLineMarketing,CZ|AvatarOfAirlineMarketing,MU|AirLineMarketing,MU|AvatarOfAirlineMarketing,FM|AirLineMarketing,FM|AvatarOfAirlineMarketing,HU|AirLineMarketing,HU|AvatarOfAirlineMarketing,3U|AirLineMarketing,3U|AvatarOfAirlineMarketing,8C|AirLineMarketing,8C|AvatarOfAirlineMarketing,8L|AirLineMarketing,8L|AvatarOfAirlineMarketing,9C|AirLineMarketing,9C|AvatarOfAirlineMarketing,A6|AirLineMarketing,A6|AvatarOfAirlineMarketing,AQ|AirLineMarketing,AQ|AvatarOfAirlineMarketing,BK|AirLineMarketing,BK|AvatarOfAirlineMarketing,CN|AirLineMarketing,CN|AvatarOfAirlineMarketing,DR|AirLineMarketing,DR|AvatarOfAirlineMarketing,DZ|AirLineMarketing,DZ|AvatarOfAirlineMarketing,EU|AirLineMarketing,EU|AvatarOfAirlineMarketing,FU|AirLineMarketing,FU|AvatarOfAirlineMarketing,G5|AirLineMarketing,G5|AvatarOfAirlineMarketing,GJ|AirLineMarketing,GJ|AvatarOfAirlineMarketing,GS|AirLineMarketing,GS|AvatarOfAirlineMarketing,GX|AirLineMarketing,GX|AvatarOfAirlineMarketing,GY|AirLineMarketing,GY|AvatarOfAirlineMarketing,HO|AirLineMarketing,HO|AvatarOfAirlineMarketing,JD|AirLineMarketing,JD|AvatarOfAirlineMarketing,JR|AirLineMarketing,JR|AvatarOfAirlineMarketing,KN|AirLineMarketing,KN|AvatarOfAirlineMarketing,KY|AirLineMarketing,KY|AvatarOfAirlineMarketing,MF|AirLineMarketing,MF|AvatarOfAirlineMarketing,NS|AirLineMarketing,NS|AvatarOfAirlineMarketing,OQ|AirLineMarketing,OQ|AvatarOfAirlineMarketing,PN|AirLineMarketing,PN|AvatarOfAirlineMarketing,QW|AirLineMarketing,QW|AvatarOfAirlineMarketing,RY|AirLineMarketing,RY|AvatarOfAirlineMarketing,SC|AirLineMarketing,SC|AvatarOfAirlineMarketing,TV|AirLineMarketing,TV|AvatarOfAirlineMarketing,UQ|AirLineMarketing,UQ|AvatarOfAirlineMarketing,VD|AirLineMarketing,VD|AvatarOfAirlineMarketing,Y8|AirLineMarketing,Y8|AvatarOfAirlineMarketing,YI|AirLineMarketing,YI|AvatarOfAirlineMarketing,ZH|AirLineMarketing,ZH|AvatarOfAirlineMarketing,CA|PriorityPackage,CA|TravelPackage,CZ|PriorityPackage,CZ|TravelPackage,MU|PriorityPackage,MU|TravelPackage,FM|PriorityPackage,FM|TravelPackage,HU|PriorityPackage,HU|TravelPackage,3U|PriorityPackage,3U|TravelPackage,8C|PriorityPackage,8C|TravelPackage,8L|PriorityPackage,8L|TravelPackage,9C|PriorityPackage,9C|TravelPackage,A6|PriorityPackage,A6|TravelPackage,AQ|PriorityPackage,AQ|TravelPackage,BK|PriorityPackage,BK|TravelPackage,CN|PriorityPackage,CN|TravelPackage,DR|PriorityPackage,DR|TravelPackage,DZ|PriorityPackage,DZ|TravelPackage,EU|PriorityPackage,EU|TravelPackage,FU|PriorityPackage,FU|TravelPackage,G5|PriorityPackage,G5|TravelPackage,GJ|PriorityPackage,GJ|TravelPackage,GS|PriorityPackage,GS|TravelPackage,GX|PriorityPackage,GX|TravelPackage,GY|PriorityPackage,GY|TravelPackage,HO|PriorityPackage,HO|TravelPackage,JD|PriorityPackage,JD|TravelPackage,JR|PriorityPackage,JR|TravelPackage,KN|PriorityPackage,KN|TravelPackage,KY|PriorityPackage,KY|TravelPackage,MF|PriorityPackage,MF|TravelPackage,NS|PriorityPackage,NS|TravelPackage,OQ|PriorityPackage,OQ|TravelPackage,PN|PriorityPackage,PN|TravelPackage,QW|PriorityPackage,QW|TravelPackage,RY|PriorityPackage,RY|TravelPackage,SC|PriorityPackage,SC|TravelPackage,TV|PriorityPackage,TV|TravelPackage,UQ|PriorityPackage,UQ|TravelPackage,VD|PriorityPackage,VD|TravelPackage,Y8|PriorityPackage,Y8|TravelPackage,YI|PriorityPackage,YI|TravelPackage,ZH|PriorityPackage,ZH|TravelPackage",
ALadingValue:"",
isBusinessPackageTag:true,
FreeGiftConfig:{"Lounge":{"Title":"赠休息室","Desc":"赠送价值¥200元的贵宾休息室一份<br><strong>贵宾休息室使用说明:</strong><br>1)携程贵宾休息室可提供免费餐饮等超值贵宾服务和更舒适的候机环境;<br>2)使用时长2小时,航班起飞当日有效;<br>3)2周岁以下婴儿免费。"}},
lightStyle:false,
AirlineMarketingAgencyIcons:null,
IsTravelPackageCloseFullInvoice:true,
UBTAirlineStoresConfig:"MU,CA,CZ,HU",
IsOpenBIRecResult:false,
strictHighFrequencyAirline:"ZH,DR",
FreeLuggageMaxAmount:20
};
var ssoInitLoginFlag = 'T';
function __SSO_submit(a, t) {
ssoInitLoginFlag = 'F';
if(a===null){
try{
if(SearchCondition.SearchType=="S"&&SearchBox){
SearchBox.reSearch();
}else{
location.href=location.href;
}
}catch(ex){}
return;
}
if ($("#" + a).length > 0) $("#" + a)[0].click();
}

</script>


<script type="text/javascript">
$globalPad = true;
var WebResourcePath = "http://webresource.c-ctrip.com/ResFlightOnline/R1/Booking";
$LAB.script({src:"http://webresource.c-ctrip.com/code/cquery/cQuery_110421.js?ReleaseNo=CR_2016_05_10_19_57_18",charset:"utf-8"}).wait().padScript({src:"http://webresource.c-ctrip.com/code/cquery/pad.js?ReleaseNo=CR_2016_05_10_19_57_18",charset:"utf-8"}).wait().script({src:"http://webresource.c-ctrip.com/code/js/resource/jmpinfo_tuna/CraftType_gb2312.js?ReleaseNo=CR_2016_05_10_19_57_18",charset:"gb2312"}).wait().script({src:"http://webresource.c-ctrip.com/ResFlightOnline/R1/Booking/release/dest/FlightSearchResult_XFile.min.js?ReleaseNo=CR_2016_05_10_19_57_18",charset:"utf-8"}).wait(LoadCallback);

function LoadCallback(){
if(typeof loadDomReady!="undefined"){
loadDomReady();
}
logTimer();
}

</script>

<script type="text/javascript" src="http://webresource.c-ctrip.com/ResCRMOnline/R6/member/common/js/mask_young.js?20140603"></script>
<div id="base_ft">
<p><a href="http://pages.ctrip.com/public/sitemap/sitemap.htm" target="_blank" title="网站导航">网站导航</a>&#xA0;|&#xA0;<a href="http://hotels.ctrip.com/jiudian/" target="_blank" title="宾馆索引">宾馆索引</a>&#xA0;|&#xA0;<a href="http://flights.ctrip.com/booking/hot-city-flights-sitemap.html " target="_blank" title="机票索引">机票索引</a>&#xA0;|&#xA0;<a href="http://pages.ctrip.com/public/sitemap/dj.html" title="旅游索引">旅游索引</a>&#xA0;|&#xA0;<a href="http://ct.ctrip.com/crptravel/sitemap.html" title="商旅索引">商旅索引</a>&#xA0;|&#xA0;<a title="攻略索引" href="http://you.ctrip.com/sitemap/">攻略索引</a>&#xA0;|&#xA0;<a rel="nofollow" href="http://pages.ctrip.com/public/ctripab/abctrip.htm" target="_blank" title="关于携程">关于携程</a>&#xA0;|&#xA0;<a rel="nofollow" target="_blank" href="http://pages.ctrip.com/commerce/promote/201201/other/qygm/index.html" title="企业公民">企业公民</a>&#xA0;|&#xA0;<a rel="nofollow" target="_blank" title="诚聘英才" href="http://job.ctrip.com/">诚聘英才
</a>&#xA0;|&#xA0;<a rel="nofollow" title="智慧旅游" href="http://you.ctrip.com/Intelligence.html">智慧旅游</a>&#xA0;
|&#xA0;<a rel="nofollow" target="_blank" href="http://u.ctrip.com/" title="分销联盟">分销联盟</a>&#xA0;|&#xA0;<a rel="nofollow" target="_blank" href="http://pages.ctrip.com/public/dlhz.htm" title="代理合作">代理合作</a>&#xA0;|&#xA0;<a target="_blank" href="http://ct.ctrip.com" title="企业商旅">企业商旅</a>&#xA0;|&#xA0;<a target="_blank" href="http://ct.ctrip.com/crptravel/default/landing" title="中小企业差旅">中小企业差旅</a>&#xA0;|&#xA0;<a rel="nofollow" target="_blank" href="http://pages.ctrip.com/public/ctripad/adyw.htm" title="广告业务">广告业务</a>&#xA0;|&#xA0;<a rel="nofollow" target="_blank" href="http://pages.ctrip.com/public/contact.htm" title="联系我们">联系我们</a></p>
<p><a rel="nofollow" href="http://hotels.ctrip.com/jiameng#ctm_ref=ctr_def_btm_hsu_n_1" target="_blank" title="酒店加盟">酒店加盟</a>&#xA0;|
<a rel="nofollow" href="http://pages.ctrip.com/commerce/promote/201501/destination/mdd/index.html">旅游局及景区合作</a>&#xA0;|&#xA0;
<a rel="nofollow" href="http://pages.ctrip.com/public/serve%20guideline.htm" target="_blank" title="服务说明">服务说明</a>&#xA0;|&#xA0;
<a rel="nofollow" target="_blank" href="http://pages.ctrip.com/public/diploma/company.htm">营业执照</a>&#xA0;|&#xA0;<a rel="nofollow" target="_blank" href="http://pages.ctrip.com/tour/ingroupline_pages.asp?folder=ingroup0904&amp;file=0177" title="旅游度假资质">旅游度假资质</a>&#xA0;|&#xA0;<a rel="nofollow" target="_blank" href="http://kefu.ctrip.com/insurance/index.aspx">保险代理</a>&#xA0;|&#xA0;<a target="_blank" href="http://pages.ctrip.com/public/link/ctrip_link.html">友情链接</a>&#xA0;|&#xA0;<a rel="nofollow" href="http://pages.ctrip.com/public/copyright.htm" id="copyright">Copyright&copy;</a>, <a href="http://www.ctrip.com/"> ctrip.com</a>. All rights reserved.&#xA0;|&#xA0;<a rel="nofollow" target="_blank" href="http://www.miibeian.gov.cn/">ICP证:沪B2-20050130</a></p>
<p class="gns"><a href="http://www.beian.gov.cn/portal/registerSystemInfo?recordcode=31010502000018"><i class="icon-gns"></i>沪公网备31010502000018号</a></p>
<div class="honour_wrap"><a href="http://www.itrust.org.cn/yz/pjwx.asp?wm=163178864X" title="网信编码:163178864X" class="honour1" target="_blank" rel="nofollow">信用评级</a><a href="http://www.sgs.gov.cn/lz/licenseLink.do?method=licenceView&amp;entyId=20110428175405415" title="工商亮照标识" class="honour2" target="_blank" rel="nofollow">上海工商</a><a href="http://search.cxwz.org/cert/l/CX20111018000615000623" title="诚信认证示范企业" class="honour3" target="_blank" rel="nofollow">诚信网站</a><a href="http://www.zx110.org/" class="honour4" target="_blank" rel="nofollow" title="征信网">网络社会征信网</a><a href="http://www.shjbzx.cn/" class="honour5" target="_blank" rel="nofollow" title="上海市互联网违法与违规信息举报中心">信息举报中心</a><a href="https://ss.knet.cn/verifyseal.dll?sn=e12061531010025926306977" class="honour6" target="_blank" rel="nofollow" title="可信网站">可信网站</a><a href="http://www.12377.cn/" class="honour8" title="违法和不良信息举报中心" target="_blank" rel="nofollow">违法和不良信息举报中心</a></div>
</div><config id="timespan" value="20160329"></config><!-- InstanceEnd name="position" --><script type="text/javascript">var globalConfig={H1:'https',H3:'my.ctrip.com',Lang:'gb2312',AjaxUrl:'accounts.ctrip.com'};</script><script type="text/javascript" src="http://webresource.c-ctrip.com/ResCRMOnline/R1/pageheader/js/PageHeadController.js?temp=20160510" charset="utf-8"></script>
<div class="comfort_bg_left" id="comfortableSortMessage" style="position: absolute;top:-1000px;left:0px;z-index:2002"></div><div class="mask_content" id="comfortableMessage" style="top:-1000px;left:0px;z-index:2002" ><div class="comfort_bg_right"></div><a class="btn" href="javascript:;" id="CloseComfortableMessage"></a></div>
</body>
</html>

从下图的代码处可以看到参数r的值
参数r

CK和rk参数值的获取(如果只想看最终结果请自行跳到下一节)

这两个参数就无法从主页面中直接获取到了,那么看一下主页面中执行的js文件吧,在主页面源代码的23-32行部分是显示数据的核心部分,在这里定义并且调用了ajaxRequest函数,把这个函数搞清楚那么CK和rk的值就弄清楚了。下面贴出来经过反向格式化的ajaxRequest函数代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
function ajaxRequest(n, t) {
var i = null,
e, f, l, o, s, r, c, u, h;
if (typeof XMLHttpRequest != "undefined") i = new XMLHttpRequest;
else if (typeof ActiveXObject != "undefined") {
if (typeof arguments.callee.aciveXString != "string") for (e = ["MSXML2.XMLHttp.6.0", "MSXML2.XMLHttp.3.0", "MSXML2.XMLHttp"], f = 0, l = e.length; f < l; f++) try {
i = new ActiveXObject(e[f]);
arguments.callee.activeXString = e[f];
break
} catch (a) {}
i == null && (i = new ActiveXObject(arguments.callee.activeXString))
}
i.onreadystatechange = function() {
try {
if (i.readyState == 4) if (i.status >= 200 && i.status < 300 || i.status == 304) {
var r = eval("(" + i.responseText + ")");
if (_searchCount_c == 0 && r && r.Error && r.Error.Code == 104 && (r.Error.Message == "" || !r.Error.Message)) {
_searchCount_c++;
setTimeout(function() {
var i = n.split("&");
i.pop();
ajaxRequest(i.join("&") + "&rt=" + Math.random() * 1e3, t)
}, 1e3);
return
}
jsonCallback.done(r)
} else i.status != 0 && jsonCallback.onError()
} catch (u) {
jsonCallback.onError()
}
};
window.location.hash && (o = window.location.hash.match(/DDate1=\d{4}-\d{2}-\d{2}/), o && o.length > 0 && (n = n.replace(/DDate1=(\d{4}-\d{2}-\d{2})/ig, o[0])), s = window.location.hash.match(/DDate2=\d{4}-\d{2}-\d{2}/), s && s.length > 0 && (n = n.replace(/DDate2=(\d{4}-\d{2}-\d{2})/ig, s[0])));
r = n.replace(/^[\s\xA0]+|[\s\xA0]+$/g, "");
(r.indexOf("ClassType=CF") == -1 || r.indexOf("ClassType=&") != -1) && (r += getStorage("FD_SearchPage_onlyCf") == "CF" ? "&ClassType=CF" : "");
_searchCount_c > 0 && (c = t.split(".")[1], t = "0." + c.substring(1, c.length - 1));
u = r.split("&");
h = r.indexOf("rk=") >= 0 || r.indexOf("rt=") >= 0 ? u.splice(u.length - 2, 1)[0] : u.pop();
u.push("CK=");
h = h.split("=")[1];
var fn = (function(u, r, k, t) {
var A1 = 1,
B1A = 1;
A1 = A1 *= parseInt(Math.tan(9) * 0xa);
A1 = A1 -= parseInt(Math.sqrt(9) * 0xa);
if (A1 < 0) A1 = -A1;
while (A1 > 30) A1 = A1 % 10;
B1A = B1A *= parseInt(Math.atan(5) * 0xa);
if (B1A < 0) B1A = -B1A;
while (B1A > 30) B1A = B1A % 10;
(function(r, u, x, y, t, k) {
if (!window.location.href) {
return;
}
var l = r.split('');
var c = l.splice(y, 1);
l.splice(x, 0, c);
t.open('GET', u.join('&') + l.join('') + '&r=' + k, !0);
t.send(null);
})(r, u, A1, B1A, t, k)
});
fn(u, h, t, i)
}
var jsonCallback = {
isError: !1,
isReady: !1,
data: {},
readyList: [],
errorList: [],
ready: function(n) {
this.isReady == !1 ? this.readyList.push(n) : n(this.data)
},
done: function(n) {
this.isReady = !0;
this.data = n;
for (var t = 0; this.readyList[t];) this.readyList[t](n), t++
},
error: function(n) {
this.isError == !1 ? this.errorList.push(n) : n()
},
onError: function() {
this.isError = !0;
for (var n = 0; this.errorList[n];) this.errorList[n](), n++
}
},
getStorage = function(n) {
var i, r, t;
try {
if (i = "{}", window.localStorage) i = localStorage.getItem("jStorage");
else if (window.globalStorage) i = window.globalStorage[window.location.hostname];
else {
r = document.head || document.getElementsByTagName("head")[0];
t = document.createElement("link");
t.style.behavior = "url(#default#userData)";
r.appendChild(t);
try {
t.load("jStorage")
} catch (u) {
t.setAttribute("jStorage", "{}");
t.save("jStorage");
t.load("jStorage")
}
i = t.getAttribute("jStorage") || "{}";
r.removeChild(t)
}
return !i || i == "{}" ? "" : eval("(" + i + ")")[n]
} catch (f) {
return ""
}
}

首先看函数的两个参数,第一个参数是字符串 “http://flights.ctrip.com/domesticsearch/search/SearchFirstRouteFlights?DCity1=HRB&ACity1=SHA&SearchType=S&DDate1=2016-05-13&IsNearAirportRecommond=0&CK=36B05DD175F36398546F66CA5EFD07DE&rk=Math.random()*10+'071048‘“
注意:由于这里面有一个random函数,所以上面的rk是一个0-9之间的一个16位长度的小数加上后面的071048,例如rk=7.248395953793079071048。
另一个参数是刚才给出的r的值,在函数内部这个参数名为t
接下来是变量定义和生成XMLHttpRequest对象,和与XMLHttpRequest监视的状态发生变化(即readystatechange)相关联的函数……这些都不是关注的重点,继续往下看。
第32行开始用正则对日期的格式进行了统一,并且去掉了多余的空格,变量o的值为DDate1所对应的时间,此处就是2016-05-13,
n中DDate值被替换为格式化后的值,其他位置保持不变;同理,DDate2也进行了类似的操作,
s中存放的就是格式化后的值。
局部变量r中存放的是url中去掉多余空格后的形式,在这里就是 “http://flights.ctrip.com/domesticsearch/search/SearchFirstRouteFlights?DCity1=HRB&ACity1=SHA&SearchType=S&DDate1=2016-05-13&IsNearAirportRecommond=0&CK=36B05DD175F36398546F66CA5EFD07DE&rk=Math.random()*10+'071048‘“ 这个字符串。
下面的c=t.split(“.”)[1]将变量t在”.”处分隔开,变成字符串数组[“0”,”1440474125154478474718”],然后将数组中的第二项赋值给c,因此此时c=”1440474125154478474718”;c.substring(1, c.length - 1)取得c的子串,去掉首位和末位,即“44047412515447847471”,执行过35行的语句后,t的值变为”0.44047412515447847471”。
第36行将r用”&”分隔开,得到变量u的值为 [ “http://flights.ctrip.com/domesticsearch/search/SearchFirstRouteFlights?DCity1=HRB“ , “ACity1=SHA” , “SearchType=S” , “DDate1=2016-05-13” , “IsNearAirportRecommond=0” , “CK=36B05DD175F36398546F66CA5EFD07DE” , “rk=7.248395953793079071048” ] ,
第37行从u中删除掉倒数第二项,即”CK=36B05DD175F36398546F66CA5EFD07DE”这一项,并将其赋值给h
第38行在u末尾添加了一项”CK=”,第39行h的值变为”36B05DD175F36398546F66CA5EFD07DE”,
第40-60行是fn函数的定义部分,61行调用了该函数,调用的形式为
fn([ “http://flights.ctrip.com/domesticsearch/search/SearchFirstRouteFlights?DCity1=HRB“ , “ACity1=SHA” , “SearchType=S” , “DDate1=2016-05-13” , “IsNearAirportRecommond=0” , “CK=36B05DD175F36398546F66CA5EFD07DE” , “rk=7.248395953793079071048” ] , “36B05DD175F36398546F66CA5EFD07DE” , “0.44047412515447847471” , i),
下面看下在fn内部进行的操作
定义变量A1=1,B1A=1,tan(9)的值为-0.452315659,第43行A1的值为-4,第49行执行完后A1的值为4,B1A的值为13,
接下来执行一个函数function(r, u, x, y, t, k),传进的参数为
( “36B05DD175F36398546F66CA5EFD07DE” , [ “http://flights.ctrip.com/domesticsearch/search/SearchFirstRouteFlights?DCity1=HRB“ , “ACity1=SHA” , “SearchType=S” , “DDate1=2016-05-13” , “IsNearAirportRecommond=0” , “rk=7.248395953793079071048” , “CK=” ] , 4 , 13 , i , “0.44047412515447847471” )
第54行l为 “36B05DD175F36398546F66CA5EFD07DE”被分割后的单个字符组成的数组。
第55行 将l中下标为13的元素删除并赋给变量c
第56行 将c插入到l中索引为5的位置
第57行 通过XMLHttpRequest对象获取json数据,方式为GET,访问的URL格式为:http://flights.ctrip.com/domesticsearch/search/SearchFirstRouteFlights?DCity1=HRB&ACity1=SHA&SearchType=S&DDate1=2016-05-13&IsNearAirportRecommond=0&rk=7.248395953793079071048&CK=336B05DD175F3698546F66CA5EFD07DE&r=0.44047412515447847471

三个参数取值结论

rk取值:16位长度的小数加上主页面传进来的6位长的字符串,因此rk长度为22位(不算小数点)
CK取值:主页面传进来CK参数,将第13位上的数移到第5位上去。其长度为32位
r取值:主页面传进来的参数值

爬虫完整实现

下面用Python实现完整的数据抓取过程。
不妨查询哈尔滨到上海5月15号的机票信息。思路:我们首先构造主页面URL,http://flights.ctrip.com/booking/hrb-sha-day-1.html?ddate1=2016-05-15,然后获取到响应的参数值并构造出rk、CK、r这三个参数值,然后访问那个包含json格式数据的网页,并获取数据。下面是Python的代码示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
#coding:utf-8

import urllib2
from lxml import etree
import json
import random
import sys
reload(sys)
sys.setdefaultencoding('utf8')

def get_json2(date,rk,CK,r):
'''根据构造出的url获取到航班数据'''
url='http://flights.ctrip.com/domesticsearch/search/SearchFirstRouteFlights?DCity1=HRB&ACity1=SHA&SearchType=S&DDate1=%s&IsNearAirportRecommond=0&rk=%s&CK=%s&r=%s'%(date,rk,CK,r)
headers={'Host':"flights.ctrip.com",'User-Agent':"Mozilla/5.0 (Windows NT 10.0; WOW64; rv:45.0) Gecko/20100101 Firefox/45.0",'Referer':"http://flights.ctrip.com/booking/hrb-sha-day-1.html?ddate1=2016-05-18"}
headers['Referer']="http://flights.ctrip.com/booking/hrb-sha-day-1.html?ddate1=%s"%date
req=urllib2.Request(url,headers=headers)
res=urllib2.urlopen(req)
content=res.read()
dict_content=json.loads(content,encoding="gb2312")
print len(dict_content['fis'])

def get_parameter(date):
'''获取重要的参数
date:日期,格式示例:2016-05-13
'''

url='http://flights.ctrip.com/booking/hrb-sha-day-1.html?ddate1=%s'%date
res=urllib2.urlopen(url).read()
tree=etree.HTML(res)
pp=tree.xpath('''//body/script[1]/text()''')[0].split()
CK_original=pp[3][-34:-2]
CK=CK_original[0:5]+CK_original[13]+CK_original[5:13]+CK_original[14:]

rk=pp[-1][18:24]
num=random.random()*10
num_str="%.15f"%num
rk=num_str+rk
r=pp[-1][27:len(pp[-1])-3]

return rk,CK,r

if __name__=='__main__':
date='2016-05-15'
rk,CK,r=get_parameter(date)
get_json2(date,rk,CK,r)

执行结果

1
41

在浏览器中搜索2016年5月15日的航班数确实是41条,如下图所示
浏览器中的搜索结果

总结

至此本次携程网机票信息抓取就告一段落了,上面提供了完整可运行的代码,可以一边参照本博客一边运行查看效果。当然如果想要支持任意两个地点的查询要先知道所有地点的英文缩写,可以把它存储在字典中;另外由于航班信息json数据比较大,用单线程读取效率比较低下,此时可以考虑使用多线程……还有很多可以完善的地方,这些内容就不在本文中展开了。
注意事项

  • 携程网站对于爬虫爬取的频率有限制,频率过高服务器会返回429错误,此时未登录用户将无法正确获取数据。因此建议登录账号后利用cookie进行数据的抓取,虽然登录后过于频繁也会导致429错误(我用Python开20个线程抓取不到10分钟就会出现此错误),但是只要等待3分钟后就可以继续爬取,而且爬取的数据不会出错(数据的正确性可以根据返回的json数据中的Error项来判断,Error代码为104说明数据出错)。
  • 即便采用账号登录的形式,不到几个小时cookie就会失效,因而需要不断地更新cookie值。

用Python抓取携程网机票信息 过程纪实(上篇)

前言

现在有一个需求,想查询一下给定出发地和目的地的机票数目,然后得到所需要的航班信息。不知道哪个网站比较好,于是用bing查了一下,搜索结果中第一个是携程在bing打的广告。bing搜索截图
秉承着对bing搜索一贯的信任(^__^),我点开了携程机票查询的链接。
ctrip机票查询
在上图的左侧查询版块选择出发城市和目的城市后点击搜索按钮,会跳转到另一个页面,如下图所示
携程网机票信息
这个页面的显示结果正是我们所需要的,上面有航班的数目和相应的信息,那么如何获取呢?

页面分析

直接读取html文档吗?

显然不行,这个页面的显示用到了Ajax的异步调用,直接查询html文档是获取不到数据的。话说回来要是这么容易就获取到了还犯得着写个博客记录一下吗:-D

解析JavaScript代码?

没错,JavaScript代码是迟早要进行解析的,不过不是现在(事实上要留到下篇博客)。现在我们要做的是对后台处理过程有个大体的认识,例如数据的格式,信息访问,而且标题说了用Python,那么还要考虑到怎样用Python处理得到的数据,以上这些是本博客接下来要做的内容,至于其他内容将在下篇博客中讲到。
我用的PC机,firefox浏览器,直接F12打开开发工具,切换到网络选项卡,然后重新载入页面,接下来会看到如下图所示的结果
F12截图
上面的图不用多介绍了,下面左侧显示的是网页加载过程中从服务器获取到的文件,右边是相应的内容信息。可以看到图中选中的文件是浏览器显示的主页面,然而这个主页面除了显示标题栏、菜单栏、页脚之外什么也没有,显然咱们要的信息不在这(想查看每个页面显示效果,在上图中先选中文件,然后在右侧选择“预览”选项,就可以看到页面的预览效果,上图右侧就是主页面的预览效果)。知道上面的技巧以后,就可以一边选择文件,一边预览页面,这样很快就可以定位到所需的网页文件。下图就是包含航班信息的网页文件
包含航班信息的js文件
在右侧的预览中可以看到航班数据,不过格式不够直观,将其切换到“响应”选项卡,如下图,返回的数据是json格式。
响应选项卡查看
在json数据中有一个”fis”对应0~38共39个对象,对应网页中显示的39个航班信息,如下图所示

有些城市直接不存在直达的航班,而是需要中转换乘,这种航班信息显示在“tf”中,如下图所示

每个object里面包含该航班的具体信息,下图是打开第一个object看到的内容

里面包含了页面展示所涉及到的全部数据信息,下面是其中的一部分


尤其需要留意的是json文件最下面的Error项,对于正常的json Eoor项是为null的,如果查询的城市之间无直飞航班,则Error 中会包含Code项,值为102;如果查询的两城市之间并不通航,则Error 中同样包含Code项,值为103;最糟糕的是Code值为104,它表明json数据是错的。如下图

编写爬虫

上面已经找到了包含数据的js代码,假如我们想要获取航班的数量信息(类似于上文的39)那么我们在Python中直接访问该url获取资源岂不美哉!然并卵,直接用是不行的。下面的示例代码完成对js对应url的访问,并对response页面进行了显示。

1
2
3
4
5
6
7
8
9
10
11
import urllib2

def get_that():

url='http://flights.ctrip.com/domesticsearch/search/SearchFirstRouteFlights?DCity1=HRB&ACity1=SHA&SearchType=S&DDate1=2016-05-13&IsNearAirportRecommond=0&rk=5.189667156909168071745&CK=89D3A4A3A5F8A7F7E48ACDD1F451127A&r=0.1440474125154478474718'

response=urllib2.urlopen(url).read()
print response

if __name__=='__main__':
get_that()

运行结果

1
{"lps":{},"fis":[],"islpc":true,"tf":null,"sf":null,"rflag":{"rn":false,"rt":false,"rht":false,"rtp":false,"fquery":true},"lp":0,"lcfp":0,"lr":0,"rpl":null,"icfnf":false,"al":[],"iaw":false,"atc":0,"abc":0,"hmat":false,"hmab":false,"pc":0,"latp":0,"latdt":"0001-01-01 00:00:00","gpl":null,"rlp":null,"rrc":0,"rtgt":null,"nnrr":0,"airfreq":null,"apb":{},"als":{},"fcts":[],"ibc":{},"TraceLog":null,"Error":{"Code":104,"Message":"","Data":""}}

没有得到我们想要的数据。error信息中错误代码为104,下篇博客会谈到这个104是怎么来的。从结果看携程的服务器对request的消息头进行了验证,贸然访问不行,那就需要伪装一下了。下面代码演示了用设置了请求头的request访问刚才的网址,然后将json格式转换成Python中的dict类型,并且将其中”fis”关键字对应的值的数目打印出来。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
import urllib2
import json

def get_json():
url='http://flights.ctrip.com/domesticsearch/search/SearchFirstRouteFlights?DCity1=HRB&ACity1=SHA&SearchType=S&DDate1=2016-05-13&IsNearAirportRecommond=0&rk=5.189667156909168071745&CK=89D3A4A3A5F8A7F7E48ACDD1F451127A&r=0.1440474125154478474718'
headers={'Host':"flights.ctrip.com",'User-Agent':"Mozilla/5.0 (Windows NT 10.0; WOW64; rv:45.0) Gecko/20100101 Firefox/45.0",'Referer':"http://flights.ctrip.com/booking/hrb-sha-day-1.html?ddate1=2016-05-13"}
req=urllib2.Request(url,headers=headers)
res=urllib2.urlopen(req)
content=res.read()
dict_content=json.loads(content,encoding="gb2312")
print len(dict_content['fis'])

if __name__=='__main__':
get_json()

上面代码中用到了urllib2模块和json模块,前者用于网络资源的访问,后者用于解析json格式。由于携程网网页的字符编码格式为gb-2312,所以掉用json的loads方法时需要指定字符集为gb-2312。下面是得到的结果

1
39

终于得到了我们想要的结果。这里就不对航班中的其他信息进行提取了,实际上提取的方式是一样的,通过将json格式转换为dict,访问其中的某个键值就变得很轻松了。

小结

至此,本文就告一段落了,本文主要谈到了如何快速定位到所需的js文件,以及构造headers,最后将json格式转换为dict格式方便对数据的操作。但问题到这里还没有结束,我们想要实现的是给定出发地、到达地和出发时间,得到航班数量,然而现在包含数据的js文件是手动设置的,作为一个爬虫,显然这里需要修改。观察url的格式,里面除了我们提供的出发城市(DCity)、目的城市(ACity)、单程(SearchType=S)、日期(DDate)和IsNearAirportRecommond之外,还有三个很重要的参数(rk、CK、r),想要构造出这三个参数,就需要看js代码了,下篇博客会详细介绍js代码中这三个参数的“前世今生”,一起探索吧

Python函数

简介

Python中的函数作为Python中的一个类对象,功能强大,灵活度高。本文从函数基本属性入手,谈一谈Python中的函数

Python函数的基本属性

Python中函数的属性可以使用dir函数进行查看,例如对于下面定义的cubic函数

1
2
3
4
5
6
7
8
def cubic(x):
"""return cubic of given number"""
return x**3

>>> cubic
<function cubic at 0x0000000002E23F98>
>>> dir(cubic)
['__call__', '__class__', '__closure__', '__code__', '__defaults__', '__delattr__', '__dict__', '__doc__', '__format__', '__get__', '__getattribute__', '__globals__', '__hash__', '__init__', '__module__', '__name__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', 'func_closure', 'func_code', 'func_defaults', 'func_dict', 'func_doc', 'func_globals', 'func_name']

上面列出了cubic函数所有的属性,下面谈几个重要的属性

__doc__ :返回制定函数的文档字符串

对于上面的cubic函数,查看它的doc属性如下:

1
2
>>> cubic.__doc__
'return cubic of x'

__module__ :返回函数所在模块的名字

1
2
>>> cubic.__module__
'__main__'

__name__ :返回函数的名字

1
2
>>> cubic.__name__
'cubic'

func_globals:返回一个包含函数全局变量的字典引用

1
2
>>> cubic.func_globals
{'__builtins__': <module '__builtin__' (built-in)>, '__name__': '__main__', 'cubic': <function cubic at 0x0000000002E23EB8>, '__doc__': None, '__package__': None}

func_defaults:返回一个包含默认参数值的元组

1
2
>>> cubic.func_defaults
>>>

上面没有显示任何信息,因为cubic函数不包含默认参数,后面再详细讨论该属性

func_closure: 返回一个胞体元组,胞体中包含了对函数自由变量的绑定,这属于闭包的范畴

1
2
>>> cubic.func_closure
>>>

可以看到,上面的例子过于简单,也没有涉及到闭包,后面详细探讨

函数迭代

函数可以作为参数传递给其他函数,以其他函数作为参数的函数成为高阶函数,在Python中有一些自带的函数就具有这样的特点。如map函数,map函数接受一个函数和一个可迭代对象作为它的参数,将函数应用于迭代对象中的每一项,并将作用后的迭代对象作为列表返回。例如还以前面举的cubic函数为例,看一下map函数的作用结果

1
2
>>> map(cubic,range(12))
[0, 1, 8, 27, 64, 125, 216, 343, 512, 729, 1000, 1331]

函数嵌套定义

可以在函数的内部定义函数,也可以将函数赋值给变量,下面的例子

1
2
3
4
5
6
7
8
9
def outer():
outer_var="in outer function"
def inner():
return outer_var
return inner
>>> function=outer()
>>> function
<function inner at 0x0000000002E23B38>
>>>

上面的例子中,外层函数返回内部函数并将其赋值给变量,现在function所引用的是内部函数的一个实例对象。可以像调用普通函数一样调用它,例如下面:

1
2
3
>>> function()
'in outer function '
>>>

可以正确调用inner函数

函数的定义

函数定义的执行会绑定当前本地名称空间中的函数名到一个函数对象,该对象是一个对函数中可执行代码的包装器。该对象包含了一个对全局名称空间(有别于当前名称空间,后者是该函数调用的全局名称空间)的引用,函数只有在调用时才会真正执行

函数的参数

Python中的函数支持固定参数和可变参数,后者可以是列表、字典或者其他迭代对象。

默认参数

使用默认参数时,用户可以省去一些重复输入,同时代码本身健壮性可以显著增强。下面是一个函数默认参数的函数的例子

1
2
3
4
5
6
def repeat(str,times=3):
print str*times
>>> repeat("haha")
hahahahahaha
>>> repeat("haha",5)
hahahahahahahahahaha

可以看到,当没有给times传入值时,就会使用默认的参数值;而当指定times值之后,就会使用指定值。

注意:当默认参数为可变参数时要格外小心,由于函数定义只执行一次,因此相同的可变结构会用于后续所有的函数调用中。例如

1
2
3
4
5
6
7
8
9
def mutable_show(args,default_args=[]):
default_args.append(args)
print "default_args:{}".format(default_args)

>>> mutable_show("once")
default_args:['once']
>>> mutable_show("twice")
default_args:['once', 'twice']
>>>

上面的代码中两次输入的args被先后加到了default_args中,所以使用可变就够作为默认参数时要小心出错。

关键字参数

采用”arg=value”的形式调用函数称之为关键词参数,注意这里指的是调用的时候采用”arg=value”的形式而非”value”这样的形式。
例如对于上面的repeat函数中,可以采用下面的集中方法来调用该函数

1
2
3
4
5
6
>>> repeat(str="hehe")
hehehehehehe
>>> repeat(times=5,str="heihei")
heiheiheiheiheiheiheiheiheihei
>>> repeat(str="heihei",times=5)
heiheiheiheiheiheiheiheiheihei

上面代码中第一个参数使用了关键字参数的方式,第二个参数采用默认参数值,函数正确执行。第二个和第三个参数顺序颠倒但是都可以正确执行,说明关键字参数的先后顺序不影响函数执行。但要注意关键字参数不能放在非关键字参数的前面,例如下面的方式就会出错

1
2
3
>>> repeat(str="heihei",5)
File "<stdin>", line 1
SyntaxError: non-keyword arg after keyword arg

上面的第二个参数是非关键字参数,它必须放在关键字参数的前面。但是如果改成下面这样也是不对的。

1
2
3
4
>>> repeat(5,str="heiheihei")
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: repeat() got multiple values for keyword argument 'str'

因为按照函数参数匹配的方式,第一个参数5被复制给形参str(专业的说法是:这里的5是位置参数,会被赋值给相应位置的形参),而后面再次给str赋值,给同一个参数多次赋值是不可以的。

任意的参数列表

Python中函数可以接受以元组形式传递的任意数量的参数,下面是一个相应的例子

1
2
3
4
5
def mutable_show(separator,*args):
print separator.join(args)
>>> mutable_show("",'haha','hehe','heihei')
hahaheheheihei
>>>

上面的’haha’,’hehe’,’heihei’被捆绑为一个元组,可以通过args访问该元组。

解包函数参数

函数调用的参数可以是元组、列表或者字典,这是需要使用*或者**将这些参数解包到函数内部。首先看一个基本的例子:

1
2
3
4
5
6
7
8
def print_args(a,b,c):
print a
print b
print c
>>> print_args(1,2,3)
1
2
3

如果参数本来就在一个list中,可以将list作为参数传递进去,像下面这样:

1
2
3
4
5
>>> a=range(1,4)
>>> print_args(*a)
1
2
3

类似的,对于字典形式的参数可以使用**的方式传递给函数,像下面的例子

1
2
3
4
5
6
def print_dict(var1,var2,var3="hehe"):
print var2,var3,var1
>>> d={'var1':"wenqiang","var2":"My name ","var3":"is "}
>>> print_dict(**d)
My name is wenqiang
>>>

*和**应用场景:参数个数不定时

有的时候不知道调用的时候参数的个数,这时可以使用*和**作为参数。
对于下面的形式

1
print_args(arg,*args,**kwargs)

后面的args和kwargs是可选的,但要注意函数定义时*args必须位于**kwargs的前面
下面是一个使用的例子

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
def print_args(arg,*args,**kwargs):
print arg
for item in args:
print args
for item in kwargs:
print item,kwargs[item]
>>> args=range(1,6)
>>> kwargs={'name':"program",'language':"Python",'content':"function"}
>>> print_args("test",*args,**kwargs)
test
(1, 2, 3, 4, 5)
(1, 2, 3, 4, 5)
(1, 2, 3, 4, 5)
(1, 2, 3, 4, 5)
(1, 2, 3, 4, 5)
content function
name program
language Python

匿名函数

可以使用lambda创建匿名函数,lambda表达式返回函数对象,该函数可以想普通函数一样被调用,见下面的例子

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
>>>cubic=lambda x: x**3
>>> for i in range(10):
... cubic(i)
...
0
1
8
27
64
125
216
343
512
729
>>>

函数的嵌套和闭包

在函数内部定义函数形成了函数的嵌套,像前面的例子

1
2
3
4
5
def outer():
outer_var="in outer function"
def inner():
return outer_var
return inner

每次调用外部函数时,都会创建一个内部函数的实例并返回到外部(原本inner函数作用域只在outer函数内部,通过返回内部函数inner可以在其他地方调用该函数),因为每次执行调用代码时inner函数都执行函数定义,但不会执行其函数体,只有当调用inner函数时函数体才会执行。
inner函数可以访问outer函数的变量,这是Python允许的操作,像之前举的例子,inner函数调用后会返回outer函数中定义的变量。对于嵌套函数,当内部函数引用外部函数的变量时,我们认为嵌套函数相对于引用变量是封闭的。对于这种情形,我们可以使用函数属性__closure__来访问该变量,如下所示:

1
2
3
4
5
6
7
8
9
>>> a=outer()
>>> a
<function inner at 0x0000000002E23EB8>
>>> va=a.__closure__
>>> va
(<cell at 0x0000000002E3E948: str object at 0x0000000002E4F030>,)
>>> va[0].cell_contents
'in outer function '
>>>

上面的例子中,使用__closure__属性得到的是一个包含全部闭包变量的元组,使用cell_contents方法可以查看变量的值

注意:Python 3之前的版本中指向不可变类型的变量无法在闭包中反弹。下面的例子:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
def counter():
count = 0
def c():
count += 1
return count
return c

>>> a=counter()
>>> a()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 4, in c
UnboundLocalError: local variable 'count' referenced before assignment
>>>

一种解决办法是用可变类型代替上面的变量,例如:

1
2
3
4
5
6
7
8
9
10
11
12
def counter():
count = [0]
def c():
count[0]+= 1
return count[0]
return c

>>> a=counter()
>>> a()
1
>>> a()
2

在Python 3中引入了nonlocal关键字解决了上面的问题,在Python 3中可以如下定义:

1
2
3
4
5
6
7
def counter():
count = 0
def c():
nonlocal count
count += 1
return count
return c

内建函数 apply() filter() map() reduce()

这些函数实现了函数式编程语言中的一些功能结合lambda表示式可以用很精简的代码完成很丰富的功能。这里只简要的提一下,后面会有专门的博文讲述这几个函数。

apply()函数

函数完整的定义如下:

1
apply(func[,nkw][,kw])

其中第一个参数是一个函数,第二个可选参数为非关键字参数,第三个可选参数为关键字参数。apply的返回值是func执行后的返回值。说的直白一些就是相当于func([nkw][,kw])因此使用这个函数未必会简化代码量,所以在1.6之后的版本中已经不推荐使用,《Python核心编程》中说这个函数会逐步淘汰掉。
下面举个例子对比一下用和不用这个函数的效果

1
2
3
4
5
6
7
def repeat(str,times):
print str*times

>>> repeat("hehe",times=6)
hehehehehehehehehehehehe
>>> apply(repeat,("hehe",),{"times":6})
hehehehehehehehehehehehe

上面用两种方式对repeat函数进行了相同目的的调用,第一种是常规的函数调用形式,传入的第一个参数是位置参数,第二个是关键字参数,调用格式简洁明了;第二种方式采用apply函数的形式,第一个参数是函数名,第二个参数是位置参数,这里需要以元组的形式传入,第三个参数是关键字参数,传入的关键字参数要以字典的形式传进来。可以看到利用apply反而会使问题变得更加复杂和繁琐。

filter函数

filter函数的定义形式如下

1
filter(func,seq)

func是一个布尔函数,即返回值为bool值(True或者False);seq是一个序列。filter函数会将seq中的每个元素作为参数传进func函数中,并且将func返回值为True的元素加进最终要返回的序列中,最终返回由所有满足func返回值为True的元素组成的序列。
下面举一个例子

1
2
3
4
5
def func(num):
return num%2==0

>>> filter(func,range(10))
[0, 2, 4, 6, 8]

上面定义的函数当num为偶数时返回True,否则返回false。通过filter调用,最终返回使得func值为True的所有元素,即序列中所有的偶数。其实在Python中引入list comprehension后利用list comprehension的特性来实现这种功能同样十分轻松,甚至后者更为便捷。假如想用list comprehension来实现这样的功能,只需要像下面这样

1
2
>>> [i for i in range(10) if i%2==0]
[0, 2, 4, 6, 8]

所以自从引入了列表推导后,函数式编程的函数的作用就变小了。

map函数

map函数的定义如下

1
map(func,seq1[,seq2...])

如果seq只有一个,则map函数的功能是把seq中的每个元素逐一代入到func中,并将作用后的结果以列表的形式返回。当seq不止一个时,即参数为seq1,seq2,……,此时map的操作是将seq1和seq2,……中对应位置的元素提取出来供func调用,并将调用后的结果加入到返回值列表。例如有两个序列,那么首先各取出第一个元素,seq1[0]和seq2[0],并将这两个值作为参数注入到函数func中,得到一个结果,放到结果列表中,然后再取seq1[1]和seq2[1],这样一直进行到两个序列元素都迭代过为止。如果两个序列长度不同,则较短的序列会用None值补全。下面举一个例子

1
2
3
4
5
def func(x,y):
return y**x

>>> map(func,range(10),range(15,25))
[1, 16, 289, 5832, 130321, 3200000, 85766121, 2494357888L, 78310985281L, 2641807540224L]

如果func为None(注意map里的func必须明确指定,可以明确指定为None),那么map此时的作用和zip很像,都是将后面的序列按位置匹配到元组中,不过zip会以序列中长度最短的为准,一旦有序列到末位,迭代就结束了。看下面的代码演示

1
2
3
4
5
6
>>> map(None,range(10),range(15,25))
[(0, 15), (1, 16), (2, 17), (3, 18), (4, 19), (5, 20), (6, 21), (7, 22), (8, 23), (9, 24)]
>>> map(None,range(10),range(15,26))
[(0, 15), (1, 16), (2, 17), (3, 18), (4, 19), (5, 20), (6, 21), (7, 22), (8, 23), (9, 24), (None, 25)]
>>> zip(range(10),range(15,26))
[(0, 15), (1, 16), (2, 17), (3, 18), (4, 19), (5, 20), (6, 21), (7, 22), (8, 23), (9, 24)]

可以看到如果后面的序列长度相同且func为None,则map函数作用和zip完全相同。

reduce函数

reduce函数定义如下

1
reduce(func,seq[,init])

func一定要是个二元函数(即接收两个参数),seq为输入序列,这里面的init是可选的。如果没有提供init参数,reduce的作用过程是,首先将seq中的前两个元素代入到函数func中,将函数的返回值和seq中的第三个元素作为参数如果到func中,再将执行后函数的返回结果和seq中的第四个元素作为参数传入到函数func中……依此类推,直到将序列迭代完。如果提供了init参数,reduce作用的区别仅在于初始时将seq中的第一个元素和init作为参数传入到func中,而不是seq的前两个元素,后面的操作完全相同。下面举个例子

1
2
3
4
def multi(x,y):
return x*y
>>> reduce(multi,range(1,7))
720

上面的例子中没有指定初始化参数,因此函数作用过程是先把序列中的前两个元素(1和2)作为参数传入到函数multi中,返回值2和序列的下一个元素3作为参数再传入multi中,得到6……依此类推得到720。

《高级数据库系统》笔记—— 第九章 并发控制

回到上一章

并发控制

保证并发执行的事务能保持一致性的整个过程

串行调度和可串行化调度

调度

  • 调度是一个或多个事务的重要操作按时间排序的一个序列
  • 如READ, WRITE序列

串行调度

  • 如果一个调度的动作组成首先是一个事务的所有动作,然后是另一个事务的所有功作,依此类推、而没有动作的混合,则该调度为串行调 度
  • 更精确地讲,已知调度S中的任意两个事务T和T’,若T的某个动作在T’的某个动作前,则T的所有动作在T’的所有动作前,那么调度S是 串行的

串行调度举例

可串行化调度

  • 如果不管数据库初始状态如何,一个调度对数据库状态的影响都和某个串行调度相同,则该调度是可串行化的

下图是一个可串行化的调度
串行调度变化前 串行调度变化后

事务和调度的一种记法

  • 只考虑事务的读写操作
  • 用ri(X)、wi(X)表示事务Ti读和写数据库元素X
    用r.和w表示事务和对数据库元素的修改
  • 事务集合T的调度S是组成它的事务动作的一个交错的序列,

《高级数据库系统》笔记—— 第八章 日志与故障恢复

回到上一章

事务的引入

  • 计算环境的脆弱性—故障恢复问题
    • 银行转帐(故障恢复)
  • 计算环境的分布性—并发控制问题
    • 订飞机票(并发执行)

事务示例

银行转帐:事务T从A帐户过户50¥到B帐户

1
2
3
4
5
6
T:read(A);
A := A – 50;
write(A);
read(B);
B := B + 50;
write(B);

其中

1
2
read(X):从数据库传送数据项X到事务的工作区中
write(X):从事务的工作区中将数据项X写回数据库

事务中数据访问过程

数据访问过程

可恢复操作的问题与模型

故障模式:

  • 错误数据输入:引入约束机制
    • 但有些错误是无法检测的,例如输错某一位。
  • 介质故障
    • 磁盘局部故障:可通过奇偶校验检测
    • 磁盘重大故障:利用RAID
  • 灾难性故障
    • RAID失效,因系统中所有磁盘均被破坏
    • 可用备份或冗余分布式拷贝恢复
  • 系统故障:是导致事务状态丢失的问题
    • 掉电或软件错误
    • 无法确定事务的哪些部分(包括对数据库的修改)已经进行

事务:

  • 事务是数据库操作的执行单位。每一个查询或数据库更新语句就是—个事务
  • 在嵌入式SQL系统中,一旦对数据库进行的操作执行,事务就开始,而事务的结束使用显式的commit或rollback结束
  • SQL中事务的定义
    • 事务以Begin transaction开始,以Commit work或 Rollback work结束
    • Commit work表示提交,事务正常结束
    • Rollback work表示事务非正常结束,撤消事务已做的操作,回滚到事务开始时的状态

事务的ACID特性

A:表示事务的原子性(Atomicity),即事务完全执行或完全不执行

  • 事务中包含的所有操作要么全做,要么全不做原子性由恢复机制实现

C:表示一致性(Consistency),所有数据库都有一致性约束,或关于数据之间联系的预期状态

  • 事务的隔离执行必须保证数据库的一致性。事务开始前,数据库处于一致性的状态;事务结束后,数据库必须仍处于一致性状态。
  • 数据库的一致性状态由用户来负责,由并发控制机制实现。如银行转帐,转帐前后两个帐户金额之和应保持不变

I:表示隔离(Isolation),即表面看起来,每个事务都是在没有其它事务同时执行的情况下执行的

  • 系统必须保证事务不受其它并发执行事务的影响。对任何一对事务T1,T2,在T1看来,T2要么在T1开始之前已经结束,要么在T1完成之后再开始执行
  • 隔离性通过并发控制机制实现

D:表示持久性(Durability),即一旦事务完成了, 事务对数据库的影响就不会丢失

  • 一个事务一旦提交之后,它对数据库的影响必须是永久的
  • 系统发生故障不能改变事务的持久性。持久性通过恢复机制实现

事务

事务与数据库交互过程中使用的三种地址空间

  • 保存数据库元素的磁盘块空间
  • 缓冲区管理器管理的地址空间
  • 事务的局部地址空间

三种空间的计划过程如下图所示
三种地址空间
上图中

1
2
READ(X, t)和WRITE(t, X)由事务发出
INPUT(X)和OUTPUT(X)由缓冲区管理器发出

事务的原语操作

用一种记法来描述使数据在地址空间之间移动的操作:

  • 1.INPUT(X):将包含数据库元素X的磁盘块拷贝到主存缓冲区
  • 2.READ(X, t):将数据库元素X拷贝到事务的局部变量t
  • 3.WRITE(X, t):将局部变量t的值拷贝到主存缓冲区中的数据库元素X
    1. OUTPUT(X):将包含X的缓冲区拷贝回磁盘

事务状态

下图说明了事务的几种状态以及这些状态间的转换
几种状态的转换

undo 日志

  • 日志
    • 日志是日志记录的一个序列,用于记载有关某个事务已做的事的某些情况
  • 日志块最初在主存中创建,一旦合适,日志块就被永久地写到磁盘上
  • 日志记录的格式
    • ,表示事务T已经开始
    • ,表示事务T成功完成
    • ,事务T未成功,被中止
    • ,表示事务T改变了数据库元素X,X原来的值为v(X的旧值)
  • 更新记录
  • undo日志规则
  • 使用undo日志的恢复

    • 如果不能完全确定事务的影响已经完成并且已经存储到磁盘上,那么事务对数据库所做的所有更新都将被撤销,数据库被恢复,就好像这 - 些事务从来未曾执行过。
  • 更新记录

    • 含义是,事务T改变了数据库元素X,X原来的值是v
    • 注意: undo日志不记录数据库元素的新值,而只记录旧值。如果在使用undo日志的系统中需要进行恢复时,恢复管理器要做的唯一事情是 通过恢复旧值消除事务可能在磁盘上造成的影响
  • undo日志的规则
    对于任一事务T,按照如下顺序向磁盘输出
    T的日志信息:
    • 首先,写更新日志记录
    • 其次,改变数据库,执行OUTPUT(X)
    • 最后,写日志
      但是顺序是对各个数据库元素单独适用,而不是对事务的更新记录集合整个适用
      →立即修改的技术
      允许数据库修改在事务仍处于活跃状态时就输出到数据库中,此时称其为未提交修改

例如对于下面的事务
事务举例
其对应的日志顺序为
事务日志

使用undo日志进行恢复

  • 从尾部开始扫描日志
  • 在扫描过程中,记住所有有记录的事务T
  • 在由尾部向后扫描的过程中,若看到
    有记录, 则
    • 若T的COMMIT记录已经被扫描到,则什么也不做;
    • 否则,T是一个未完成的事务或被中止的事务。必须将数据库中X的值改为v。然后,将写入磁盘

例如对于下面的事务
undo日志

  • 若执行到第2~11步中的任意一步发生故障,
    • 利用undo日志,恢复旧值
  • 若执行完第12步后发生故障,则表示T已经完全执行完,不必做任何处理动作

检查点:周期性地对日志作检查点

  • 静止检查点:
    • 停止接受新的事务
    • 等到所有当前活跃事务提交或中止,并在日志中写入了COMMIT或ABORT记录
    • 将日志刷新到磁盘
    • 写入日志记录,并再次刷新日志
  • 非静止检查点
    • 在进行检查点时不必关闭系统,允许新事务进入

redo日志

Undo日志的一个问题

将事务改变的所有数据写到磁盘前不能提交该事务

redo日志

更新记录的格式,其中,v为X的新值

redo日志的规则

  • 写磁盘的顺序为:
    • 更新记录
    • COMMIT日志
    • OUTPUT(X)
  • 使用redo日志的恢复

恢复管理器的工作:

  • 确定已提交的事务。
  • 从首部开始扫描日志。对遇到的每一记录:
    • 如果T是未提交的事务,则什么也不做。
    • 如果T是提交的事务,则为数据库元素X写入值v。
  • 对每个未完成的事务T,在日志中写入一个记录并刷新日志。

下面是一个redo日志的例子
redo日志例子

redo日志的检查点

  • 不管检查点是静止的还是非静止的,在检查点的开始和结束之间我们必须采取的一个关键动作是将已被提交事务修改但还未写到磁盘的所有数据库元素写到磁盘
  • 另一方面,我们不需要等待活跃事务提交或中止就能完成检查点,因为它们无论如何都不允许在那个时候将它们的页写到磁盘

redo日志举例

检查点恢复规则

  • 找到最后一个日志
  • 对于在相应检查点插入时活跃的事务和插入检查点之后开始的事务,记录所有需要Redo的已提交事务
  • 从需redo事务中最早开始的事务向后扫描,并Redo所有需要提交的事务
  • 对未提交的事务插入

含有checkpoint的redo示例

undo日志vs.redo日志

Undo日志与Redo日志的主要区别
当数据库元素被修改时日志中保存旧值还是新值

  • Undo日志要求数据在事务结束后立即写到磁盘,可能增加需要进行的磁盘I/O数
  • Redo日志要求我们在事务提交和日志记录刷新以前将所有修改过的块保留在缓冲区中,可能增加事务需要的平均缓冲区数

undo/redo日志

undo/redo日志结合了两种日志的优点

代价:在日志中维护更多信息 ,事务T更新了数据库元素X的值;其更新前的值为v,更新后的值为w

undo/redo日志规则

  • 在事务T所更新磁盘上的数据库元素X之前,相应日志记录必须写入磁盘
  • 注意:此处没有任何对commit日志记录的要求,Undo/Redo日志仅需要满足Undo 和Redo日志共同的限制

undo/redo日志恢复过程

  • 从后往前扫描日志,构造undo-list和redo-list
    • 对每个形如的记录,将Ti 加入redo-list
    • 对每个形如的记录,如果Ti不属于redo-list,则将Ti加入undo-list
  • 由后至前扫描日志,对undo-list中的每个事务 Ti的每一个日志记录执行undo操作
    • 在具体实现中本步骤可以和第一步一起进行
  • 由前至后重新扫描日志,并且对redo-list中每个事务Ti的每一个日志记录执行redo操作
    • 对每个未完成的事务在日志Ti末尾加入, Flush log 并将数据库置为正常状态

undo/redo日志的检查点

  • 写入日志记录,其中,T1, …, Tk是所有的活跃事务, 并刷新日志
  • 将所有脏缓冲区写到磁盘,脏缓冲区即包含一个或多个修改过的数据库元素的缓冲区
    • 注意:该过程并不将检查点开始和结束之间修改的数据写入磁盘
  • 写入日志记录并刷新日志

防备介质故障

  • 当主存数据丢失时,日志可以保证磁盘上的数据不会丢失。
  • 然而,当一个或多个磁盘丢失时,如果下列条件成立,可以通过日志重建数据库:
    • 日志所在的磁盘不同于存放数据的磁盘
    • 日志在检查点以后不会被丢弃,并且
    • 日志是redo或undo/redo类型,因而新值被存储在日志当中
  • 然而,实际中,日志的增长远比数据库快,所以,永远保存日志是不现实的

防备介质故障的措施

备份:当介质故障发生时,数据库可以恢复到备份那一时刻的状态

  • 要前进到一个更近的状态,可以使用日志
  • 具体方式
    • 完全转储
    • 增量转储

日志恢复

下一章 并发控制

《高级数据库系统》笔记—— 第六章 查询执行

回到上一章

查询编译过程

  • A 查询分析:构造分析树表达查询及其结构
  • B 查询重写:将分析树转化为逻辑查询计划
    • 逻辑查询计划通常是查询的代数表达式
    • 逻辑查询计划将会被转化为一个预期所需时间较小的等价的计划
  • C 生成物理查询计划:根据B 步骤生成的逻辑查询计划的每一个操作符选择实现算法,并选择操作符的执行顺序物理计划还包括许多细节 ,如被查询的关系是如何访问的,及关系是否需要排序等

B,C部分被称为查询优化器

下一章 查询编译器

,