-
Notifications
You must be signed in to change notification settings - Fork 2
Expand file tree
/
Copy pathatom.xml
More file actions
1823 lines (1603 loc) · 304 KB
/
atom.xml
File metadata and controls
1823 lines (1603 loc) · 304 KB
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
<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
<title><![CDATA[ShinChan's Blog]]></title>
<subtitle><![CDATA[Vi Veri Veniversum Vivus Vici]]></subtitle>
<link href="/atom.xml" rel="self"/>
<link href="http://chenqx.github.com/"/>
<updated>2015-04-05T10:12:51.891Z</updated>
<id>http://chenqx.github.com/</id>
<author>
<name><![CDATA[ShinChan]]></name>
<email><![CDATA[chenqiuxing@gmail.com]]></email>
</author>
<generator uri="http://zespia.tw/hexo/">Hexo</generator>
<entry>
<title><![CDATA[Linux shell 执行多个命令的几种方法]]></title>
<link href="http://chenqx.github.com/2015/03/30/Methods-of-Linux-Shell-for-Several-Commands/"/>
<id>http://chenqx.github.com/2015/03/30/Methods-of-Linux-Shell-for-Several-Commands/</id>
<published>2015-03-30T01:13:05.000Z</published>
<updated>2015-04-03T03:31:12.000Z</updated>
<content type="html"><![CDATA[<h3 id="‘_;_’分隔符"><code>‘ ; ’</code>分隔符</h3>
<p> 每个命令之间用 <code>;</code> 隔开,各命令的执行给果,不会影响其它命令的执行。换句话说,各个命令都会执行,但不保证每个命令都执行成功。</p>
<h3 id="‘_&&_’分隔符"><code>‘ && ’</code>分隔符</h3>
<p> 每个命令之间用 <code>&&</code> 隔开,若前面的命令执行成功,才会去执行后面的命令。这样可以保证所有的命令执行完毕后,执行过程都是成功的。</p>
<h3 id="‘_||_’分隔符"><code>‘ || ’</code>分隔符</h3>
<p> 每个命令之间用 <code>||</code> 隔开,<code>||</code>是或的意思,只有前面的命令执行失败后才去执行下一条命令,直到执行成功一条命令为止。</p>
]]></content>
<summary type="html">
<![CDATA[<h3 id="‘_;_’分隔符"><code>‘ ; ’</code>分隔符</h3>
<p> 每个命令之间用 <code>;</code> 隔开,各命令的执行给果,不会影响其它命令的执行。换句话说,各个命令都会执行,但不保证每个命令都执行成功。</p>
<h3 id="‘_]]>
</summary>
<category term="Linux" scheme="http://chenqx.github.com/tags/Linux/"/>
<category term="Linux" scheme="http://chenqx.github.com/categories/Linux/"/>
</entry>
<entry>
<title><![CDATA[分治算法]]></title>
<link href="http://chenqx.github.com/2015/03/16/Introduction-to-Divide-and-Conquer-Algorithm/"/>
<id>http://chenqx.github.com/2015/03/16/Introduction-to-Divide-and-Conquer-Algorithm/</id>
<published>2015-03-16T06:42:32.000Z</published>
<updated>2015-03-16T06:51:44.000Z</updated>
<content type="html"><![CDATA[<h2 id="基本概念">基本概念</h2>
<p> 在计算机科学中,分治法是一种很重要的算法。字面上的解释是“分而治之”(Divide and Conquer),就是把一个复杂的问题分成两个或更多的相同或相似的子问题,再把子问题分成更小的子问题……直到最后子问题可以简单的直接求解,原问题的解即子问题的解的合并。这个技巧是很多高效算法的基础,如排序算法(快速排序,归并排序),傅立叶变换(快速傅立叶变换)……<br> 任何一个可以用计算机求解的问题所需的计算时间都与其规模有关。问题的规模越小,越容易直接求解,解题所需的计算时间也越少。例如,对于n个元素的排序问题,当n=1时,不需任何计算。n=2时,只要作一次比较即可排好序。n=3时只要作3次比较即可,…。而当n较大时,问题就不那么容易处理了。要想直接解决一个规模较大的问题,有时是相当困难的。</p>
<h2 id="基本思想及策略">基本思想及策略</h2>
<p> 分治法的设计思想是:将一个难以直接解决的大问题,分割成一些规模较小的相同问题,以便各个击破,分而治之。<br> 分治策略是:对于一个规模为n的问题,若该问题可以容易地解决(比如说规模n较小)则直接解决,否则将其分解为k个规模较小的子问题,这些子问题互相独立且与原问题形式相同,递归地解这些子问题,然后将各子问题的解合并得到原问题的解。这种算法设计策略叫做分治法。<br> 如果原问题可分割成k个子问题,1< k≤n,且这些子问题都可解并可利用这些子问题的解求出原问题的解,那么这种分治法就是可行的。由分治法产生的子问题往往是原问题的较小模式,这就为使用递归技术提供了方便。在这种情况下,反复应用分治手段,可以使子问题与原问题类型一致而其规模却不断缩小,最终使子问题缩小到很容易直接求出其解。这自然导致递归过程的产生。分治与递归像一对孪生兄弟,经常同时应用在算法设计之中,并由此产生许多高效算法。</p>
<h2 id="分治法适用的情况">分治法适用的情况</h2>
<p> 分治法所能解决的问题一般具有以下几个特征:</p>
<ul>
<li><p>该问题的规模缩小到一定的程度就可以容易地解决。绝大多数问题都可以满足的,因为问题的计算复杂性一般是随着问题规模的增加而增加</p>
</li>
<li><p>该问题可以分解为若干个规模较小的相同问题,即该问题具有最优子结构性质。这条特征是应用分治法的前提它也是大多数问题可以满足的,此特征反映了递归思想的应用。</p>
</li>
<li>利用该问题分解出的子问题的解可以合并为该问题的解。这条特征是关键,能否利用分治法完全取决于问题是否具有第三条特征,如果具备了第一条和第二条特征,而不具备第三条特征,则可以考虑用贪心法或动态规划法。</li>
<li>该问题所分解出的各个子问题是相互独立的,即子问题之间不包含公共的子子问题。这条特征涉及到分治法的效率,如果各子问题是不独立的则分治法要做许多不必要的工作,重复地解公共的子问题,此时虽然可用分治法,但一般用动态规划法较好。</li>
</ul>
<h2 id="基本步骤">基本步骤</h2>
<p> 分治法在每一层递归上都有三个步骤:<br> <code>step1 分解</code>:将原问题分解为若干个规模较小,相互独立,与原问题形式相同的子问题;<br> <code>step2 解决</code>:若子问题规模较小而容易被解决则直接解,否则递归地解各个子问题;<br> <code>step3 合并</code>:将各个子问题的解合并为原问题的解。</p>
<p> 它的一般的算法设计模式如下:</p>
<pre><code>Divide-and-Conquer(P)
<span class="number">1.</span> <span class="keyword">if</span> |P|≤n0
<span class="number">2.</span> then <span class="keyword">return</span>(ADHOC(P))
<span class="number">3.</span> 将P分解为较小的子问题 P1 ,P2 ,<span class="keyword">...</span>,Pk
<span class="number">4.</span> <span class="keyword">for</span> i←<span class="number">1</span> to k
<span class="number">5.</span> do yi ← Divide-and-Conquer(Pi) △ 递归解决Pi
<span class="number">6.</span> <span class="literal">T</span> ← MERGE(y1,y2,<span class="keyword">...</span>,yk) △ 合并子问题
<span class="number">7.</span> <span class="keyword">return</span>(<span class="literal">T</span>)
</code></pre><p> 其中|P|表示问题P的规模;n0为一阈值,表示当问题P的规模不超过n0时,问题已容易直接解出,不必再继续分解。ADHOC(P)是该分治法中的基本子算法,用于直接解小规模的问题P。因此,当P的规模不超过n0时直接用算法ADHOC(P)求解。算法MERGE(y1,y2,…,yk)是该分治法中的合并子算法,用于将P的子问题P1 ,P2 ,…,Pk的相应的解y1,y2,…,yk合并为P的解。</p>
<h2 id="复杂性分析">复杂性分析</h2>
<p> 一个分治法将规模为n的问题分成k个规模为n/m的子问题去解。设分解阀值n0=1,且adhoc解规模为1的问题耗费1个单位时间。再设将原问题分解为k个子问题以及用merge将k个子问题的解合并为原问题的解需用f(n)个单位时间。用T(n)表示该分治法解规模为|P|=n的问题所需的计算时间,则有:<br> <br>$T\left ( n \right )= kT\left ( n/m \right )+f\left ( n \right )$</p>
<p> 通过迭代法求得方程的解:<br> 递归方程及其解只给出n等于m的方幂时T(n)的值,但是如果认为T(n)足够平滑,那么由n等于m的方幂时T(n)的值可以估计T(n)的增长速度。通常假定T(n)是单调上升的,从而当 mi≤n< mi+1 时,T(mi)≤T(n)< T(mi+1)。</p>
<h2 id="示例:_归并排序">示例: 归并排序</h2>
<p> 归并排序(Merge sort)是建立在归并操作上的一种有效的排序算法。该算法是采用分治法(Divide and Conquer)的一个非常典型的应用。将已有序的子序列合并,得到完全有序的序列;即先使每个子序列有序,再使子序列段间有序。以二路归并为例:<br><img src="http://newtonblogimg.qiniudn.com/mergesort.png" alt="二路归并排序示例"><br> 代码示例:</p>
<figure class="highlight c++"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div><div class="line">20</div><div class="line">21</div><div class="line">22</div><div class="line">23</div><div class="line">24</div><div class="line">25</div><div class="line">26</div><div class="line">27</div><div class="line">28</div><div class="line">29</div><div class="line">30</div><div class="line">31</div><div class="line">32</div><div class="line">33</div><div class="line">34</div><div class="line">35</div><div class="line">36</div><div class="line">37</div><div class="line">38</div><div class="line">39</div><div class="line">40</div><div class="line">41</div><div class="line">42</div><div class="line">43</div><div class="line">44</div><div class="line">45</div><div class="line">46</div><div class="line">47</div><div class="line">48</div><div class="line">49</div><div class="line">50</div><div class="line">51</div><div class="line">52</div><div class="line">53</div></pre></td><td class="code"><pre><div class="line"><span class="preprocessor">#<span class="keyword">include</span> <iostream></span></div><div class="line"><span class="keyword">using</span> <span class="keyword">namespace</span> <span class="built_in">std</span>;</div><div class="line"></div><div class="line"><span class="comment">//将有二个有序数列a[first...mid]和a[mid...last]合并。</span></div><div class="line"><span class="keyword">void</span> mergearray(<span class="keyword">int</span> a[], <span class="keyword">int</span> first, <span class="keyword">int</span> mid, <span class="keyword">int</span> last, <span class="keyword">int</span> temp[]){</div><div class="line"> <span class="keyword">int</span> i = first, j = mid + <span class="number">1</span>;</div><div class="line"> <span class="keyword">int</span> m = mid, n = last;</div><div class="line"> <span class="keyword">int</span> k = <span class="number">0</span>;</div><div class="line"> </div><div class="line"> <span class="keyword">while</span> (i <= m && j <= n){</div><div class="line"> <span class="keyword">if</span> (a[i] <= a[j])</div><div class="line"> temp[k++] = a[i++];</div><div class="line"> <span class="keyword">else</span></div><div class="line"> temp[k++] = a[j++];</div><div class="line"> }</div><div class="line"> <span class="keyword">while</span> (i <= m)</div><div class="line"> temp[k++] = a[i++];</div><div class="line"> <span class="keyword">while</span> (j <= n)</div><div class="line"> temp[k++] = a[j++];</div><div class="line"></div><div class="line"> <span class="keyword">for</span> (i = <span class="number">0</span>; i < k; i++)</div><div class="line"> a[first + i] = temp[i];</div><div class="line">}</div><div class="line"></div><div class="line"><span class="keyword">void</span> mergesort(<span class="keyword">int</span> a[], <span class="keyword">int</span> first, <span class="keyword">int</span> last, <span class="keyword">int</span> temp[]){</div><div class="line"> <span class="keyword">if</span> (first < last){</div><div class="line"> <span class="keyword">int</span> mid = (first + last) / <span class="number">2</span>;</div><div class="line"> mergesort(a, first, mid, temp); <span class="comment">//左边有序</span></div><div class="line"> mergesort(a, mid + <span class="number">1</span>, last, temp); <span class="comment">//右边有序</span></div><div class="line"> mergearray(a, first, mid, last, temp); <span class="comment">//再将二个有序数列合并</span></div><div class="line"> }</div><div class="line">}</div><div class="line"></div><div class="line"><span class="keyword">bool</span> MergeSort(<span class="keyword">int</span> a[], <span class="keyword">int</span> n){</div><div class="line"> <span class="keyword">int</span> *p = <span class="keyword">new</span> <span class="keyword">int</span>[n];</div><div class="line"> <span class="keyword">if</span> (p == NULL)</div><div class="line"> <span class="keyword">return</span> <span class="keyword">false</span>;</div><div class="line"> mergesort(a, <span class="number">0</span>, n - <span class="number">1</span>, p);</div><div class="line"> <span class="keyword">delete</span>[] p;</div><div class="line"> <span class="keyword">return</span> <span class="keyword">true</span>;</div><div class="line">}</div><div class="line"></div><div class="line"><span class="keyword">int</span> main(){</div><div class="line"> <span class="keyword">int</span> arr[] = {<span class="number">1</span>, <span class="number">5</span>, <span class="number">2</span>, <span class="number">4</span>, <span class="number">6</span>, <span class="number">3</span>, <span class="number">2</span>, <span class="number">6</span>};</div><div class="line"> </div><div class="line"> MergeSort(arr, <span class="number">8</span>);</div><div class="line"> </div><div class="line"> <span class="keyword">for</span> (<span class="keyword">int</span> i = <span class="number">0</span>; i < <span class="number">8</span>; ++i){</div><div class="line"> <span class="built_in">cout</span><<arr[i]<<<span class="string">" "</span>;</div><div class="line"> }</div><div class="line"> </div><div class="line"> <span class="built_in">cout</span><<endl;</div><div class="line">}</div></pre></td></tr></table></figure>
<h2 id="可使用分治法求解的一些经典问题">可使用分治法求解的一些经典问题</h2>
<ul>
<li>二分搜索</li>
<li>大整数乘法</li>
<li>Strassen矩阵乘法</li>
<li>棋盘覆盖</li>
<li>归排序</li>
<li>快速排序</li>
<li>线性时间选择</li>
<li>最接近点对问题</li>
<li>循环赛日程表</li>
<li>汉诺塔</li>
</ul>
<h2 id="分治法设计程序时的思维过程">分治法设计程序时的思维过程</h2>
<p> 实际上就是类似于数学归纳法,找到解决本问题的求解方程公式,然后根据方程公式设计递归程序。<br> 1、一定是先找到最小问题规模时的求解方法;<br> 2、然后考虑随着问题规模增大时的求解方法;<br> 3、找到求解的递归函数式后(各种规模或因子),设计递归程序即可。
</p>
<p>auther:<a href="http://www.cnblogs.com/steven_oyj/archive/2010/05/22/1741370.html" target="_blank" rel="external"> 红脸书生</a></p>
]]></content>
<summary type="html">
<![CDATA[<h2 id="基本概念">基本概念</h2>
<p> 在计算机科学中,分治法是一种很重要的算法。字面上的解释是“分而治之”(Divide and Conquer),就是把一个复杂的问题分成两个或更多的相同或相似的子问题,再把子问题分成更小的子问题……直到最后子问题可以简单的直]]>
</summary>
<category term="Algorithm" scheme="http://chenqx.github.com/tags/Algorithm/"/>
<category term="Algorithm" scheme="http://chenqx.github.com/categories/Algorithm/"/>
</entry>
<entry>
<title><![CDATA[VS2010配置和连接MySQL详解]]></title>
<link href="http://chenqx.github.com/2015/02/06/Config-and-Connect-MySQL-in-Visual-Studio/"/>
<id>http://chenqx.github.com/2015/02/06/Config-and-Connect-MySQL-in-Visual-Studio/</id>
<published>2015-02-06T11:08:41.000Z</published>
<updated>2015-02-06T12:03:51.000Z</updated>
<content type="html"><![CDATA[<p> 本文介绍 VS2010(Microsoft Visual Studio 10.0) 下利用 MySQL 官方 connector API 的配置和连接 MySQL。</p>
<ul>
<li><a href="http://dev.mysql.com/downloads/connector/cpp/" target="_blank" rel="external">Download MySQL Connector/C++</a></li>
</ul>
<p> 根据自己的系统下载相应的版本。解压或安装后文件夹名字太长,这里将“mysql-connector-c++-noinstall-1.0.5-win32”改为“mysql”。</p>
<blockquote>
<p>VS2008 以上的版本都适用</p>
</blockquote>
<h2 id="环境配置">环境配置</h2>
<p> 下面是在 VS2010 版本下的配置过程。</p>
<ul>
<li>1. 菜单 Project ->property ->c/c++>general ->additional include directories 添加下面两项。<br>D:\Microsoft Visual Studio 10.0\library\mysql\include\cppconn;<br>D:\Microsoft Visual Studio 10.0\library\mysql\include;<br><img src="http://newtonblogimg.qiniudn.com/step1.png" alt=""></li>
<li>2. 菜单 Project ->property ->linker ->general ->additional include directories 添加下面三项。<br>D:\MySQL\MySQL Server 5.6\lib;<br>D:\MySQL\MySQL Server 5.6\bin;<br>D:\Microsoft Visual Studio 10.0\library\mysql\lib;<br><img src="http://newtonblogimg.qiniudn.com/step2.png" alt=""></li>
<li><p>3. 菜单 Project ->property ->linker ->input ->additional include directories 添加下面三项。<br>mysqlcppconn.lib;<br>mysqlcppconn-static.lib;<br>libmysql.lib;<br><img src="http://newtonblogimg.qiniudn.com/step3.png" alt=""></p>
</li>
<li><p>4. 将mysql\lib下的mysqlcppconn.dll文件和 \$MySQL\bin\libmysql.dll 复制到Windows\system32 文件夹底下。<br> 这样就配置好了。</p>
</li>
</ul>
<h2 id="创建MySQL数据库">创建MySQL数据库</h2>
<p> 这里简单建立一个连接测试数据库 <code>contest</code>。</p>
<figure class="highlight sql"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div></pre></td><td class="code"><pre><div class="line">mysql>create database contest;</div><div class="line">mysql>use contest</div><div class="line">mysql>create table test(</div><div class="line"> > id int(4) not null primary key auto_increment,</div><div class="line"> > name char(32) not null,;</div></pre></td></tr></table></figure>
<h2 id="本地连接和操作MySQL">本地连接和操作MySQL</h2>
<p> 头文件定义(系统默认生成):</p>
<figure class="highlight c++"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div></pre></td><td class="code"><pre><div class="line"><span class="comment">//Head file Definition</span></div><div class="line"><span class="preprocessor">#<span class="keyword">pragma</span> once</span></div><div class="line"><span class="keyword">class</span> mysqlWriter</div><div class="line">{</div><div class="line"><span class="keyword">public</span>:</div><div class="line"> mysqlWriter(<span class="keyword">void</span>);</div><div class="line"> ~mysqlWriter(<span class="keyword">void</span>);</div><div class="line">};</div></pre></td></tr></table></figure>
<p> 函数定义:</p>
<figure class="highlight C++"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div><div class="line">20</div><div class="line">21</div><div class="line">22</div><div class="line">23</div><div class="line">24</div><div class="line">25</div><div class="line">26</div><div class="line">27</div><div class="line">28</div><div class="line">29</div><div class="line">30</div><div class="line">31</div><div class="line">32</div><div class="line">33</div><div class="line">34</div><div class="line">35</div><div class="line">36</div><div class="line">37</div><div class="line">38</div><div class="line">39</div><div class="line">40</div><div class="line">41</div><div class="line">42</div><div class="line">43</div><div class="line">44</div><div class="line">45</div><div class="line">46</div><div class="line">47</div><div class="line">48</div><div class="line">49</div><div class="line">50</div><div class="line">51</div><div class="line">52</div><div class="line">53</div><div class="line">54</div><div class="line">55</div></pre></td><td class="code"><pre><div class="line"><span class="comment">// cpp2mysql.cpp : Defines the entry point for the console application.</span></div><div class="line"><span class="comment">/*</span></div><div class="line">cpp2mysql.cpp, Created on Feb, 2015</div><div class="line">#version: 1.0</div><div class="line">#author: By chenqx @http://chenqx.github.com</div><div class="line">*/</div><div class="line"></div><div class="line"><span class="preprocessor">#<span class="keyword">include</span> "StdAfx.h"</span></div><div class="line"><span class="preprocessor">#<span class="keyword">include</span> "mysqlWriter.h"</span></div><div class="line"><span class="preprocessor">#<span class="keyword">include</span> <iostream></span></div><div class="line"><span class="preprocessor">#<span class="keyword">include</span><string></span></div><div class="line"><span class="preprocessor">#<span class="keyword">include</span> <mysql_connection.h></span></div><div class="line"><span class="preprocessor">#<span class="keyword">include</span> <mysql_driver.h></span></div><div class="line"><span class="preprocessor">#<span class="keyword">include</span> <statement.h></span></div><div class="line"><span class="preprocessor">#<span class="keyword">include</span> <prepared_statement.h></span></div><div class="line"></div><div class="line"><span class="keyword">using</span> <span class="keyword">namespace</span> sql;</div><div class="line"><span class="keyword">using</span> <span class="keyword">namespace</span> <span class="built_in">std</span>;</div><div class="line"></div><div class="line">mysqlWriter::mysqlWriter(<span class="keyword">void</span>){</div><div class="line"> mysql::MySQL_Driver *driver;</div><div class="line"> Connection *con;</div><div class="line"> Statement *state;</div><div class="line"> ResultSet *result;</div><div class="line"> PreparedStatement *prep_stmt;</div><div class="line"></div><div class="line"> driver = sql::mysql::get_mysql_driver_instance();</div><div class="line"> con = driver->connect(<span class="string">"tcp://127.0.0.1:3306"</span>, <span class="string">"root"</span>,<span class="string">"passwd"</span>); <span class="comment">//Connect localhost</span></div><div class="line"> state = con->createStatement();</div><div class="line"> <span class="comment">//Set the database being used.</span></div><div class="line"> con->setSchema(<span class="string">"contest"</span>);</div><div class="line"></div><div class="line"> prep_stmt = con->prepareStatement(<span class="string">"INSERT INTO test(name) VALUES (?)"</span>);</div><div class="line"> </div><div class="line"> <span class="comment">//Insert values.</span></div><div class="line"> prep_stmt->setString(<span class="number">1</span>, <span class="string">"testvalue"</span>);</div><div class="line"> prep_stmt->execute();</div><div class="line"> </div><div class="line"> <span class="comment">//SQL query</span></div><div class="line"> result = state->executeQuery(<span class="string">"select * from test"</span>);</div><div class="line"> <span class="keyword">while</span>(result->next()){</div><div class="line"> <span class="keyword">int</span> id = result->getInt(<span class="string">"id"</span>);</div><div class="line"> <span class="built_in">string</span> count = result->getString(<span class="string">"name"</span>);</div><div class="line"> <span class="built_in">cout</span><<id<<<span class="string">":"</span><<count<<endl;</div><div class="line"> }</div><div class="line"> </div><div class="line"> <span class="comment">// Release.</span></div><div class="line"> <span class="keyword">delete</span> prep_stmt;</div><div class="line"> <span class="keyword">delete</span> state;</div><div class="line"> <span class="keyword">delete</span> con;</div><div class="line">}</div><div class="line"></div><div class="line">mysqlWriter::~mysqlWriter(<span class="keyword">void</span>){</div><div class="line"> <span class="comment">//pass</span></div><div class="line">}</div></pre></td></tr></table></figure>
<h2 id="远程连接MySQL">远程连接MySQL</h2>
<p> 有时候需要操作非本地其它 PC 上的 MySQL 数据库,在连接前需要对访问的计算机进行配置,添加访问权限。这里提供两种方法:</p>
<h3 id="方法一">方法一</h3>
<ul>
<li>1. 进入MySQL 安装路径的 bin 目录:</li>
</ul>
<figure class="highlight c++"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">cd $\MySQL\bin\>MySQL -h localhost -u root</div></pre></td></tr></table></figure>
<p> 这样应该可以进入MySQL服务器,代码如下:</p>
<figure class="highlight sql"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div></pre></td><td class="code"><pre><div class="line">mysql>update user set host = '%' where user = 'root'; </div><div class="line">mysql>select host, user from user;</div></pre></td></tr></table></figure>
<ul>
<li>2. 授予访问权限</li>
</ul>
<figure class="highlight sql"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">mysql>GRANT ALL PRIVILEGES ON *.* TO 'root'@'%' IDENTIFIED BY 'mypassword' WITH GRANT OPTION</div></pre></td></tr></table></figure>
<ul>
<li>3. 修改生效</li>
</ul>
<figure class="highlight sql"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">mysql>FLUSH PRIVILEGES</div></pre></td></tr></table></figure>
<ul>
<li>4. 退出重启MySQL服务器 </li>
</ul>
<figure class="highlight sql"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">mysql>EXIT</div></pre></td></tr></table></figure>
<p> 这样就可以在其它任何的主机上以root身份登录啦!</p>
<h3 id="方法二">方法二</h3>
<ul>
<li>1. 在控制台执行 mysql -u root -p mysql,系统提示输入数据库root用户的密码,输入完成后即进入mysql控制台,这个命令的第一个mysql是执行命令,第二个mysql是系统数据名称,不一样的。 </li>
<li>2. 在mysql控制台执行:</li>
</ul>
<figure class="highlight sql"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line"><span class="operator"><span class="keyword">GRANT</span> <span class="keyword">ALL</span> <span class="keyword">PRIVILEGES</span> <span class="keyword">ON</span> *.* <span class="keyword">TO</span> <span class="string">'root'</span>@<span class="string">'%'</span> <span class="keyword">IDENTIFIED</span> <span class="keyword">BY</span> <span class="string">'yourPassword'</span> <span class="keyword">WITH</span> <span class="keyword">GRANT</span> <span class="keyword">OPTION</span>;</span></div></pre></td></tr></table></figure>
<ul>
<li><p>3. 在mysql控制台执行命令中的 ‘root’@’%’ 可以这样理解: root是用户名,%是主机名或IP地址,这里的%代表任意主机或IP地址,你也可替换成任意其它用户名或指定唯一的IP地址;’yourPassword’是给授权用户指定的登录数据库的密码;另外需要说明一点的是我这里的都是授权所有权限,可以指定部分权限,GRANT具体操作详情见:<a href="http://dev.mysql.com/doc/refman/5.1/en/grant.html。" target="_blank" rel="external">http://dev.mysql.com/doc/refman/5.1/en/grant.html。</a></p>
</li>
<li><p>4. 不放心的话可以 在mysql 控制台执行下面命令检查一下用户表里的内容。</p>
</li>
</ul>
<figure class="highlight sql"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line"><span class="operator"><span class="keyword">select</span> host, <span class="keyword">user</span> <span class="keyword">from</span> <span class="keyword">user</span>;</span></div></pre></td></tr></table></figure>
<p> 设置好后通过 TCP 远程计算机的IP 即可。</p>
<figure class="highlight c++"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">con = driver->connect(<span class="string">"tcp://xxx.xxx.xxx.xxx:3306"</span>, <span class="string">"user"</span>,<span class="string">"passwd"</span>); <span class="comment">//Connect remote TCP + IP</span></div></pre></td></tr></table></figure>
<p> 数据库操作如上节所述。</p>
<h2 id="Further_reading">Further reading</h2>
<ul>
<li><a href="http://dev.mysql.com/doc/connector-cpp/en/index.html" target="_blank" rel="external">MySQL Connector/C++ Developer Guide</a></li>
</ul>
]]></content>
<summary type="html">
<![CDATA[<p> 本文介绍 VS2010(Microsoft Visual Studio 10.0) 下利用 MySQL 官方 connector API 的配置和连接 MySQL。</p>
<ul>
<li><a href="http://dev.mysql.com/downloads]]>
</summary>
<category term="C/C++" scheme="http://chenqx.github.com/tags/C-C/"/>
<category term="MySQL" scheme="http://chenqx.github.com/tags/MySQL/"/>
<category term="Develop" scheme="http://chenqx.github.com/categories/Develop/"/>
</entry>
<entry>
<title><![CDATA[常用数据存储格式介绍]]></title>
<link href="http://chenqx.github.com/2015/01/31/Introduction-to-Common-Data-Storage-Format/"/>
<id>http://chenqx.github.com/2015/01/31/Introduction-to-Common-Data-Storage-Format/</id>
<published>2015-01-31T10:32:25.000Z</published>
<updated>2015-02-01T08:02:41.000Z</updated>
<content type="html"><![CDATA[<p> 本文介绍一些常用的数据存储格式,包括TXT, Excel, CSV, XML, JSON 和数据库 (典型的如关系数据库 MySQL, NoSQL 数据库 MongDB 等 )。</p>
<h2 id="Text/Excel_文件">Text/Excel 文件</h2>
<p> Text 文本文档文件,扩展名 <code>.txt</code>,要注意其编码方式。<br> Excel 电子表格格式,扩展名 <code>.xls</code> 或 <code>.xlsx</code>。<br> 日常的文本、数据存储和处理文件。</p>
<h2 id="CSV_格式">CSV 格式</h2>
<p> <a href="http://baike.baidu.com/link?url=dhwYFIs5NGA1J4waLi0TL9Bc22hlAXOOXf4Xyw2cL6nb2wXd_3qyq2zwQFIFD7wGMppWUMq_-l31jvHw2BoB1dZ5qPcRn6C66BHRwVtT5vq" target="_blank" rel="external">CSV(Comma-Separated Values)逗号分隔值文件格式</a>,有时也称为字符分隔值,因为分隔字符也可以不是逗号。其文件以纯文本形式存储表格数据(数字和文本)。纯文本意味着该文件是一个字符序列,不含必须像二进制数字那样被解读的数据。CSV文件由任意数目的记录组成,记录间以某种换行符分隔;每条记录由字段组成,字段间的分隔符是其它字符或字符串,最常见的是逗号或制表符。通常,所有记录都有完全相同的字段序列。</p>
<p><strong>Example - Movies.csv</strong></p>
<pre><code><span class="variable">The</span> <span class="variable">Hobbit</span>:<span class="variable">The</span> <span class="variable">Battle</span> <span class="keyword">of</span> <span class="variable">Five</span> <span class="variable">Armies</span>,<span class="number">2015</span>,<span class="variable">America</span>
<span class="variable">Transformers</span>: <span class="variable">Age</span> <span class="keyword">of</span> <span class="variable">Extinction</span>,<span class="number">2014</span>,<span class="variable">America</span>
<span class="variable">Lucy</span>,<span class="number">2014</span>, <span class="variable">America</span>
<span class="variable">Intouchables</span>,<span class="number">2011</span>,<span class="variable">France</span>
</code></pre><p> <br> 4条记录,每条记录为电影名,上映时间,国家,用“,”分隔。</p>
<h2 id="XML_格式">XML 格式</h2>
<blockquote>
<p> “当 XML(扩展标记语言)于 1998 年 2 月被引入软件工业界时,它给整个行业带来了一场风暴。有史以来第一次,这个世界拥有了一种用来结构化文档和数据的通用且适应性强的格式,它不仅仅可以用于 WEB,而且可以被用于任何地方。”<br> ——《Designing With Web Standards Second Edition》, Jeffrey Zeldman</p>
</blockquote>
<p> <a href="http://baike.baidu.com/link?url=mH5ljhstNglG0VVH7qeusk7qobQQf9588CyskVr7htybk2Kf65r_wBnj56xh989XPZ_5aO80FF6Ig7Qnsmxc5necJJFm8T2-cqEm-Eu3A-ufg6M86iiRpBpStTmq85NA" target="_blank" rel="external">XML(eXtensible Markup Language)可扩展标记语言</a>,是一种标记语言, 扩展名 <code>.csv</code>。标记指计算机所能理解的信息符号,通过此种标记,计算机之间可以处理包含各种信息的文章等。如何定义这些标记,既可以选择国际通用的标记语言,比如HTML,也可以使用像XML这样由相关人士自由决定的标记语言,这就是语言的可扩展性。XML是从标准通用标记语言(SGML)中简化修改出来的。它主要用到的有可扩展标记语言、可扩展样式语言(XSL)、XBRL和<a href="http://baike.baidu.com/view/307399.htm" target="_blank" rel="external">XPath</a>等。但 XML 需要存储标签,需要额外的内存。<br> <em>查看 <a href="http://www.w3school.com.cn/x.asp" target="_blank" rel="external">XML 教程</a></em>。</p>
<p><strong>Example - Books.xml</strong></p>
<pre><code><span class="tag"><<span class="title">bookstore</span>></span>
<span class="tag"><<span class="title">book</span> <span class="attribute">category</span>=<span class="value">"COOKING"</span>></span>
<span class="tag"><<span class="title">title</span> <span class="attribute">lang</span>=<span class="value">"en"</span>></span>Everyday Italian<span class="tag"></<span class="title">title</span>></span>
<span class="tag"><<span class="title">author</span>></span>Giada De Laurentiis<span class="tag"></<span class="title">author</span>></span>
<span class="tag"><<span class="title">year</span>></span>2005<span class="tag"></<span class="title">year</span>></span>
<span class="tag"><<span class="title">price</span>></span>30.00<span class="tag"></<span class="title">price</span>></span>
<span class="tag"></<span class="title">book</span>></span>
<span class="tag"><<span class="title">book</span> <span class="attribute">category</span>=<span class="value">"CHILDREN"</span>></span>
<span class="tag"><<span class="title">title</span> <span class="attribute">lang</span>=<span class="value">"en"</span>></span>Harry Potter<span class="tag"></<span class="title">title</span>></span>
<span class="tag"><<span class="title">author</span>></span>J K. Rowling<span class="tag"></<span class="title">author</span>></span>
<span class="tag"><<span class="title">year</span>></span>2005<span class="tag"></<span class="title">year</span>></span>
<span class="tag"><<span class="title">price</span>></span>29.99<span class="tag"></<span class="title">price</span>></span>
<span class="tag"></<span class="title">book</span>></span>
<span class="tag"><<span class="title">book</span> <span class="attribute">category</span>=<span class="value">"WEB"</span>></span>
<span class="tag"><<span class="title">title</span> <span class="attribute">lang</span>=<span class="value">"en"</span>></span>Learning XML<span class="tag"></<span class="title">title</span>></span>
<span class="tag"><<span class="title">author</span>></span>Erik T. Ray<span class="tag"></<span class="title">author</span>></span>
<span class="tag"><<span class="title">year</span>></span>2003<span class="tag"></<span class="title">year</span>></span>
<span class="tag"><<span class="title">price</span>></span>39.95<span class="tag"></<span class="title">price</span>></span>
<span class="tag"></<span class="title">book</span>></span>
<span class="tag"></<span class="title">bookstore</span>></span>
</code></pre><p> <br> 例子中的根元素是 <code><bookstore></code>。文档中的所有 <code><book></code> 元素都被包含在 <code><bookstore></code> 中。<code><book></code> 元素有 4 个子元素:<code><title></code>、<code><author></code>、<code><year></code>、<code><price></code>。</p>
<h2 id="JSON_格式">JSON 格式</h2>
<p> <a href="http://baike.baidu.com/link?url=pLBYQifS2bEX1u-pcDWV5SvIVLa6vFtLRZn_ExdBGF3WyfEqFw0pesXvxKzgZPqqJNnILyEZ7NXgpDZjZSE8F_" target="_blank" rel="external">JSON(JavaScript Object Notation)</a> 是一种轻量级的数据交换格式,扩展名 <code>.json</code>。它基于JavaScript(Standard ECMA-262 3rd Edition - December 1999)的一个子集。 JSON采用完全独立于语言的文本格式,但是也使用了类似于C语言家族的习惯(包括C, C++, C#, Java, JavaScript, Perl, Python等)。这些特性使JSON成为理想的数据交换语言。易于人阅读和编写,同时也易于机器解析和生成(网络传输速度快)。<br> JSON 是存储和交换文本信息的语法,类似 XML。JSON 比 XML 更小、更快,更易解析。<br> <em>查看 <a href="http://www.w3school.com.cn/json/" target="_blank" rel="external">JSON 教程</a></em>。</p>
<p><strong>Example - employees.json</strong></p>
<pre><code>{
"<span class="attribute">employees</span>": <span class="value">[
{ "<span class="attribute">firstName</span>":<span class="value"><span class="string">"Bill"</span> </span>, "<span class="attribute">lastName</span>":<span class="value"><span class="string">"Gates"</span> </span>},
{ "<span class="attribute">firstName</span>":<span class="value"><span class="string">"George"</span> </span>, "<span class="attribute">lastName</span>":<span class="value"><span class="string">"Bush"</span> </span>},
{ "<span class="attribute">firstName</span>":<span class="value"><span class="string">"Thomas"</span> </span>, "<span class="attribute">lastName</span>":<span class="value"><span class="string">"Carter"</span> </span>}
]
</span>}
</code></pre><p> 这个 employee 对象是包含 3 个员工记录(对象)的数组。</p>
<h2 id="MySQL">MySQL</h2>
<p> <a href="http://www.mysql.com/" target="_blank" rel="external">MySQL</a>是最流行的关系型数据库管理系统,在WEB应用方面MySQL是最好的RDBMS(Relational Database Management System:关系数据库管理系统)应用软件之一。<br> <img src="http://newtonblogimg.qiniudn.com/mysql.jpg" alt=""><br> MySQL是一个关系型数据库管理系统,由瑞典MySQL AB公司开发,目前属于Oracle公司。MySQL是一种关联数据库管理系统,关联数据库将数据保存在不同的表中,而不是将所有数据放在一个大仓库内,这样就增加了速度并提高了灵活性。MySQL 主要有一下特点:</p>
<ul>
<li>MySQL是开源的,所以你不需要支付额外的费用。</li>
<li>Mysql支持大型的数据库。可以处理拥有上千万条记录的大型数据库。</li>
<li>MySQL使用标准的SQL数据语言形式。</li>
<li>MySQL可以允许于多个系统上,并且支持多种语言。这些编程语言包括C、C++、Python、Java、Perl、PHP、Eiffel、Ruby和Tcl等。</li>
<li>MySQL支持大型数据库,支持5000万条记录的数据仓库,32位系统表文件最大可支持4GB,64位系统支持最大的表文件为8TB。</li>
<li>MySQL是可以定制的,采用了GPL协议,你可以修改源码来开发自己的Mysql系统。</li>
</ul>
<p> <em>查看<a href="http://www.w3cschool.cc/mysql/mysql-tutorial.html" target="_blank" rel="external">MySQL 教程</a></em>。
</p>
<h2 id="MongDB">MongDB</h2>
<p> <a href="http://www.mongodb.org/" target="_blank" rel="external">MongDB</a>是一个高性能,易部署,开源,无模式的文档型非关系数据库,是当前NoSql数据库中比较热门的一种。它在许多场景下可用于替代传统的关系型数据库或键/值存储方式。Mongo使用C++开发。<br><img src="http://newtonblogimg.qiniudn.com/Mongdb.jpg" alt=""></p>
<pre><code>-<span class="ruby"> 什么是<span class="constant">NoSql</span>?
</span> NoSql,全称是 Not Only Sql,指的是非关系型的数据库。下一代数据库主要解决几个要点:非关系型的、分布式的、开源的、水平可扩展的。原始的目的是为了大规模web应用,这场运动开始于2009年初,通常特性应用如:模式自由、支持简易复制、简单的API、最终的一致性(非ACID)、大容量数据等。NoSQL被我们用得最多的当数key-value存储,当然还有其他的文档型的、列存储、图型数据库、xml数据库等。
</code></pre><p> MongDB 主要有一下特点:</p>
<ul>
<li>面向集合存储,易存储对象类型的数据。</li>
<li>模式自由。</li>
<li>支持动态查询,支持完全索引,包含内部对象。</li>
<li>支持复制和故障恢复。</li>
<li>使用高效的二进制数据存储,包括大型对象(如视频等)。</li>
<li>支持Python,PHP,Ruby,Java,C,C#,Javascript,Perl及C++语言的驱动程序,社区中也提供了对Erlang及.NET等平台的驱动程序。</li>
<li>等等。<br> <em>查看 <a href="http://docs.mongodb.org/manual/" target="_blank" rel="external">MongDB 官方教程</a></em>。</li>
</ul>
<h2 id="Further_reading">Further reading</h2>
]]></content>
<summary type="html">
<![CDATA[<p> 本文介绍一些常用的数据存储格式,包括TXT, Excel, CSV, XML, JSON 和数据库 (典型的如关系数据库 MySQL, NoSQL 数据库 MongDB 等 )。</p>
<h2 id="Text/Excel_文件">Text/Excel 文件</h2>]]>
</summary>
<category term="Tools" scheme="http://chenqx.github.com/tags/Tools/"/>
<category term="Develop" scheme="http://chenqx.github.com/categories/Develop/"/>
</entry>
<entry>
<title><![CDATA[白话详解何为量化投资]]></title>
<link href="http://chenqx.github.com/2015/01/22/Intro-to-Quantitative-Investment/"/>
<id>http://chenqx.github.com/2015/01/22/Intro-to-Quantitative-Investment/</id>
<published>2015-01-22T00:10:05.000Z</published>
<updated>2015-04-05T10:12:04.000Z</updated>
<content type="html"><![CDATA[<blockquote>
<p>量化投资( Quantitative Investment ),简单地说,就是利用数学、统计学、信息技术的量化投资方法来管理投资组合。数量化投资的组合构建注重的是对宏观数据、市场行为、企业财务数据、交易数据进行分析,利用数据挖掘技术、统计技术、计算方法等处理数据,以得到最优的投资组合和投资机会。</p>
</blockquote>
<h2 id="量化投资,故事才刚刚开始">量化投资,故事才刚刚开始</h2>
<p> 量化投资就是借助现代统计学、数学的方法,从海量历史大数据中寻找能够带来股票上涨的多种“大概率”策略和规律,并在此基础上,综合归纳成因子和模型程序,最终纪律严明地按照这些数量化模型组合来进行独立投资,力求取得稳定的、可持续的、高于平均的超额回报。<br> <img src="http://newtonblogimg.qiniudn.com/intro.png" alt=""><br> 海外量化投资已经非常成熟,而中国采用量化技术的进行投资才起步不久,相对来说量化对冲基金捕捉套利机会用的多一些,而主动管理的纯股票型基金还是少数。此外中国市场无效性和波动性更大,可挖掘的规律更多,故机会与前景看好,可以说,量化投资正步入黄金时代。</p>
<h2 id="量化投资的特征">量化投资的特征</h2>
<p><img src="http://newtonblogimg.qiniudn.com/feature.png" alt=""></p>
<p> 量化投资的运作和FOF(基金中的基金)有点像类似,基金经理构建出一篮子模型组操作公募基金。每个模型根据自己的构建原理自主选股,好像是一个独立的子基金。在运作过程中,基金经理根据实际情况和业绩因地制宜的对因子或模型进行调整,使之不断迭代,持续有效。一般来说,真正的量化投资,基金经理是模型的构建者和资金的给与者(仓位控制),至于模型选出什么股票,基金经理不是无权干预,而是无法干预。<br> <img src="http://newtonblogimg.qiniudn.com/figwar.png" alt=""><br> 这么一来,量化投资保证了模型的独立自主和自我学习的有效性,最大限度的降低了人性弱点可能带来的错误干预。于是从结果和宏观层面来看,量化投资和普通的主动管理基金就形成了巨大的差别,如图:<br> <img src="http://newtonblogimg.qiniudn.com/cmp.png" alt=""><br> 左边第一列有点夸张,不是说量化投资基金经理很闲,这里主要说的是工作模式。主动投资管理的基金经理要不停的挖掘、调研、选股票,靠的是人;而量化投资基金经理更多的是进行数据分析、构建新的模型、研究外方股东有啥最新最先进的模型进行本土化尝试,股票交给模型来挖,靠的是电脑。<br> 此外,主动投资管理基金经理都希望挖掘到牛股,那感觉就像杨过对小龙女,不说天长地久吧,想至少赚个好几倍的心还是有的。量化投资则不同,电脑自动买卖,换手率高,股票基本不长期持有,一旦达到目的触发相应规则立刻卖出。那感觉像楚留香,说的直白一点,人家就是来谈恋爱的,不是来结婚的。<br> 所以一切结果最后体现在持仓上,就是一般量化投资产品没有“十大重仓股”的概念,比如某些量化投资产品持仓300多只股票每个股票占比都小于2%,非常分散,也就保证了量化投资产品可以覆盖多个行业的多只股票,分散投资、分散风险,也就能圈住各个热点板块的轮动。</p>
<h2 id="量化基金的收益来源:αα……α+β">量化基金的收益来源:αα……α+β</h2>
<p> 1、αα……α:量化投资获取超额收益的逻辑是:不求在每只股票上都赚很多钱,但求在很多股票上每只都赚一点钱。一句话,积小胜为大胜,积全市场很多股票的小α为整个基金的大α。原理在于,量化投资的优势不是对单一上市公司的深度挖掘,而是对全市场股票进行的大样本、大数据、大强度的广度挖掘。这一点,“人脑”做不到,只能用“电脑”。<br><img src="http://newtonblogimg.qiniudn.com/sh.png" alt=""><br> 2、β(市场风险):这点不用细说,去年以来市场整体向上,自然给量化产品带来很高的系统性收益。</p>
<h2 id="业绩的持续性和模型的有效性">业绩的持续性和模型的有效性</h2>
<p> 持续性的业绩非常重要,一般来讲,某一个基金前一年表现的很好后一年就会很差,只有少数“神一般”的基金经理才能做到改变逻辑、改对逻辑、最终还能获利。量化投资的运作原理决定了对于市场热点而言,它不会赚翻,但是绝不会错过。从业绩上来看,量化投资连续多年把握住了机会,未来如何?可以期待并加以验证!<br><img src="http://newtonblogimg.qiniudn.com/m.png" alt=""><br> 同时,量化投资的有效性在未来依然会持续很长时间,原因有三:</p>
<ol>
<li>历史数据的样本空间会越来越大,而我们对大数据的分析能力也会越来越强,可挖掘的信息就会越来越多;</li>
<li>投资人的研究能力再厉害人再多,也无法覆盖全市场所有的股票,这就为量化投资提供了施展的空间;</li>
<li>A股的波动性和无效性,决定了量化投资挖到金矿的概率依然是非常大!<h2 id="快来,让我们一起看上帝">快来,让我们一起看上帝</h2>
量化投资的起源是在海外,如果大家对量化投资感兴趣,想知道原来除了巴菲特之外,这世上还有另外一种股神的话,可以了解一下公认的全球量化之王、华尔街的异类、世界顶级数学家詹姆斯•西蒙斯老师那让人瞠目结舌的人生:<br><img src="http://newtonblogimg.qiniudn.com/pn.png" alt=""><br> 23岁戴博士帽;26岁为美国政府破译密码;30岁任数学系主任;37岁获几何学最高奖;44岁杀入华尔街成立传奇量化对冲基金;1988年至2010年退休年均回报率高达35%,不仅远远跑赢大市,较索罗斯和巴菲特的成绩高上十余个百分点;花甲之年跻身福布斯富豪榜的72名并承诺捐出大部分财产。</li>
</ol>
<p> <strong>后续:市场若好,便是晴天;那市场转熊呢…</strong><br> <br> 说了这么多好听的,不好听的也必须要说:单纯的量化投资方式,产品表现好和中小盘的轻舞飞扬不无关系,那么万一中小盘行情结束了呢?万一经济和市场没大家想的那么美好呢?风险无处不在,风险永远是一场说来就来的意外。<br> 因此,对于量化这种“锋利”的投资方式,在瞬息万变的市场环境中,对冲将是控制风险的最好选择!</p>
]]></content>
<summary type="html">
<![CDATA[<blockquote>
<p>量化投资( Quantitative Investment ),简单地说,就是利用数学、统计学、信息技术的量化投资方法来管理投资组合。数量化投资的组合构建注重的是对宏观数据、市场行为、企业财务数据、交易数据进行分析,利用数据挖掘技术、统计技术、计算]]>
</summary>
<category term="Quant" scheme="http://chenqx.github.com/tags/Quant/"/>
<category term="Quant" scheme="http://chenqx.github.com/categories/Quant/"/>
</entry>
<entry>
<title><![CDATA[Hadoop/Spark]]></title>
<link href="http://chenqx.github.com/2015/01/12/Hadoop-Spark/"/>
<id>http://chenqx.github.com/2015/01/12/Hadoop-Spark/</id>
<published>2015-01-12T01:20:21.000Z</published>
<updated>2015-01-31T09:58:45.000Z</updated>
<content type="html"><![CDATA[<p>Updating</p>
]]></content>
<summary type="html">
<![CDATA[<p>Updating</p>
]]>
</summary>
<category term="Hadoop" scheme="http://chenqx.github.com/tags/Hadoop/"/>
<category term="Spark" scheme="http://chenqx.github.com/tags/Spark/"/>
<category term="Hadoop/Spark" scheme="http://chenqx.github.com/categories/Hadoop-Spark/"/>
</entry>
<entry>
<title><![CDATA[正则表达式30分钟入门教程]]></title>
<link href="http://chenqx.github.com/2015/01/09/Regular-Expressions-Tutorial-In-Thirty-Minutes/"/>
<id>http://chenqx.github.com/2015/01/09/Regular-Expressions-Tutorial-In-Thirty-Minutes/</id>
<published>2015-01-09T07:24:05.000Z</published>
<updated>2015-01-12T08:58:05.000Z</updated>
<content type="html"><![CDATA[<h2 id="本文目标">本文目标</h2>
<p> 30分钟内让你明白正则表达式是什么,并对它有一些基本的了解,让你可以在自己的程序或网页里使用它。</p>
<h2 id="如何使用本教程">如何使用本教程</h2>
<p> 别被下面那些复杂的表达式吓倒,只要跟着我一步一步来,你会发现正则表达式其实并没有想像中的那么困难。当然,如果你看完了这篇教程之后,发现自己明白了很多,却又几乎什么都记不得,那也是很正常的——我认为,没接触过正则表达式的人在看完这篇教程后,能把提到过的语法记住 80% 以上的可能性为零。这里只是让你明白基本的原理,以后你还需要多练习,多使用,才能熟练掌握正则表达式。</p>
<pre><code> 最重要的是——请给我30分钟,如果你没有使用正则表达式的经验,请不要试图在30秒内入门——除非你是超人 <span class="pseudo">:)</span>
</code></pre><p> 除了作为入门教程之外,本文还试图成为可以在日常工作中使用的正则表达式语法参考手册。就作者本人的经历来说,这个目标还是完成得不错的——你看,我自己也没能把所有的东西记下来,不是吗?</p>
<h2 id="正则表达式到底是什么东西?">正则表达式到底是什么东西?</h2>
<p> 在编写处理字符串的程序或网页时,经常会有查找符合某些复杂规则的字符串的需要。正则表达式就是用于描述这些规则的工具。换句话说,<strong>正则表达式</strong>就是记录文本规则的代码。</p>
<pre><code> 字符是计算机软件处理文字时最基本的单位,可能是字母,数字,标点符号,空格,换行符,汉字等等。字符串是0个或更多个字符的序列。文本也就是文字,字符串。说某个字符串匹配某个正则表达式,通常是指这个字符串里有一部分(或几部分分别)能满足表达式给出的条件。
</code></pre><p> 很可能你使用过 Windows/Dos 下用于文件查找的<strong>通配符 (wildcard)</strong>,也就是<code>*</code>和<code>?</code>。如果你想查找某个目录下的所有的Word文档的话,你会搜索<code>*.doc</code>。在这里,<code>*</code>会被解释成任意的字符串。和通配符类似,正则表达式也是用来进行文本匹配的工具,只不过比起通配符,它能更精确地描述你的需求——当然,代价就是更复杂——比如你可以编写一个正则表达式,用来查找所有以0开头,后面跟着2-3个数字,然后是一个连字号“-”,最后是7或8位数字的字符串(像010-12345678或0376-7654321)。</p>
<h2 id="入门">入门</h2>
<p> 学习正则表达式的最好方法是从例子开始,理解例子之后再自己对例子进行修改,实验。下面给出了不少简单的例子,并对它们作了详细的说明。<br> 假设你在一篇英文小说里查找<em>hi</em>,你可以使用正则表达式<em>hi</em>。<br> 这几乎是最简单的正则表达式了,它可以精确匹配这样的字符串:由两个字符组成,前一个字符是<em>h</em>,后一个是<em>i</em>。通常,处理正则表达式的工具会提供一个忽略大小写的选项,如果选中了这个选项,它可以匹配<em>hi, HI, Hi, hI</em>这四种情况中的任意一种。<br> 不幸的是,很多单词里包含<em>hi</em>这两个连续的字符,比如 <em>him, history, high</em> 等等。用 <em>hi</em> 来查找的话,这里边的 <em>hi</em> 也会被找出来。如果要精确地查找 <em>hi</em> 这个单词的话,我们应该使用<code>\bhi\b</code>。<br> \b是正则表达式规定的一个特殊代码(好吧,某些人叫它<strong>元字符,metacharacter)</strong>,代表着单词的开头或结尾,也就是单词的分界处。虽然通常英文的单词是由空格,标点符号或者换行来分隔的,但是<code>\b</code>并不匹配这些单词分隔字符中的任何一个,它<strong>只匹配一个位置</strong>。</p>
<pre><code> 如果需要更精确的说法,<span class="command">\b</span>匹配这样的位置:它的前一个字符和后一个字符不全是(一个是,一个不是或不存在)<span class="command">\w</span>。
</code></pre><p> 假如你要找的是 <em>hi</em> 后面不远处跟着一个 <em>Lucy</em>,你应该用 <code>\bhi\b.*\bLucy\b</code>。<br> 这里,<code>.</code> 是另一个元字符,匹配除了换行符以外的任意字符。<code>*</code> 同样是元字符,不过它代表的不是字符,也不是位置,而是数量——它指定 <code>*</code> 前边的内容可以连续重复使用任意次以使整个表达式得到匹配。因此,<code>.*</code> 连在一起就意味着任意数量的不包含换行的字符。现在 <code>\bhi\b.*\bLucy\b</code> 的意思就很明显了:先是一个单词<em>hi</em>,然后是任意个任意字符(但不能是换行),最后是<em>Lucy</em>这个单词。<br> 如果同时使用其它元字符,我们就能构造出功能更强大的正则表达式。比如下面这个例子:<br> <em>0\d\d-\d\d\d\d\d\d\d\d</em> 匹配这样的字符串:以0开头,然后是两个数字,然后是一个连字号“-”,最后是8个数字(也就是中国的电话号码。当然,这个例子只能匹配区号为3位的情形)。<br>这里的 <code>\d</code> 是个新的元字符,匹配一位数字(0,或1,或2,或……)。<code>-</code>不是元字符,只匹配它本身——连字符(或者减号,或者中横线,或者随你怎么称呼它)。<br>为了避免那么多烦人的重复,我们也可以这样写这个表达式:<code>0\d{2}-\d{8}</code>。这里<code>\d</code>后面的 <code>{2}({8})</code> 的意思是前面<code>\d</code> 必须连续重复匹配2次(8次)。</p>
<h2 id="元字符">元字符</h2>
<p> 现在你已经知道几个很有用的元字符了,如 <code>\b</code>, <code>.</code>, <code>*</code>,还有<code>\d.</code>正则表达式里还有更多的元字符,比如<code>\s</code>匹配任意的空白符,包括空格,制表符(Tab),换行符,中文全角空格等。<code>\w</code>匹配字母或数字或下划线或汉字等。<br> 下面来看看更多的例子:<br> <code>\ba\w*\b</code>匹配以字母 <em>a</em> 开头的单词——先是某个单词开始处 (\b),然后是字母 <em>a</em>,然后是任意数量的字母或数字 (\w*),最后是单词结束处 (\b)。</p>
<pre><code> 好吧,现在我们说说正则表达式里的单词是什么意思吧:就是不少于一个的连续的\<span class="tag">w</span>。不错,这与学习英文时要背的成千上万个同名的东西的确关系不大 <span class="pseudo">:)</span>
</code></pre><p> <code>\d+</code>匹配1个或更多连续的数字。这里的<code>+</code>是和<code>*</code>类似的元字符,不同的是<code>*</code>匹配重复任意次(可能是0次),而<code>+</code>则匹配重复1次或更多次。<br><code>\b\w{6}\b</code> 匹配刚好6个字符的单词(<strong>表1.常用的元字符</strong>)。</p>
<table>
<thead>
<tr>
<th style="text-align:center"><strong>代码/语法</strong></th>
<th style="text-align:left"><strong>说明</strong> </th>
</tr>
</thead>
<tbody>
<tr>
<td style="text-align:center">.</td>
<td style="text-align:left">匹配除换行符以外的任意字符</td>
</tr>
<tr>
<td style="text-align:center">\w</td>
<td style="text-align:left">匹配字母或数字或下划线或汉字</td>
</tr>
<tr>
<td style="text-align:center">\s</td>
<td style="text-align:left">匹配任意的空白符</td>
</tr>
<tr>
<td style="text-align:center">\d</td>
<td style="text-align:left">匹配数字</td>
</tr>
<tr>
<td style="text-align:center">\b</td>
<td style="text-align:left">匹配单词的开始或结束</td>
</tr>
<tr>
<td style="text-align:center">^</td>
<td style="text-align:left">匹配字符串的开始</td>
</tr>
<tr>
<td style="text-align:center">$</td>
<td style="text-align:left">匹配字符串的结束</td>
</tr>
</tbody>
</table>
<p> 元字符 <code>^</code>(和数字6在同一个键位上的符号)和<code>$</code>都匹配一个位置,这和 <code>\b</code> 有点类似。^匹配你要用来查找的字符串的开头,<code>$</code> 匹配结尾。这两个代码在验证输入的内容时非常有用,比如一个网站如果要求你填写的QQ号必须为5位到12位数字时,可以使用:<code>^\d{5,12}$</code>。<br> 这里的<code>{5,12}</code>和前面介绍过的<code>{2}</code>是类似的,只不过<code>{2}</code>匹配只能不多不少重复2次,<code>{5,12}</code>则是重复的次数不能少于5次,不能多于12次,否则都不匹配。<br> 因为使用了 <code>^</code> 和 <code>$</code> ,所以输入的整个字符串都要用来和<code>\d{5,12}</code>来匹配,也就是说整个输入必须是5到12个数字,因此如果输入的QQ号能匹配这个正则表达式的话,那就符合要求了。<br> 和忽略大小写的选项类似,有些正则表达式处理工具还有一个处理多行的选项。如果选中了这个选项,<code>^</code>和<code>$</code>的意义就变成了匹配行的开始处和结束处。
</p>
<h2 id="字符转义">字符转义</h2>
<p> 如果你想查找元字符本身的话,比如你查找<code>.</code>,或者<code>*</code>,就出现了问题:你没办法指定它们,因为它们会被解释成别的意思。这时你就得使用<code>\</code>来取消这些字符的特殊意义。因此,你应该使用<code>\.</code>和<code>\*</code>。当然,要查找<code>\</code>本身,你也得用<code>\\.</code><br>例如:<code>deerchao\.net</code>匹配 <em>deerchao.net</em>,<code>C:\\Windows</code>匹配 <em>C:\Windows</em>。</p>
<h2 id="重复">重复</h2>
<p> 你已经看过了前面的<code>*</code>,<code>+</code>,<code>{2}</code>,<code>{5,12}</code>这几个匹配重复的方式了。下面是正则表达式中所有的限定符(指定数量的代码,例如<code>*</code>,<code>{5,12}</code>等),<strong>表2.常用的限定符</strong>:</p>
<table>
<thead>
<tr>
<th style="text-align:center"><strong>代码/语法</strong></th>
<th style="text-align:left"><strong>说明</strong> </th>
</tr>
</thead>
<tbody>
<tr>
<td style="text-align:center">*</td>
<td style="text-align:left">重复零次或更多次</td>
</tr>
<tr>
<td style="text-align:center">+</td>
<td style="text-align:left">重复一次或更多次</td>
</tr>
<tr>
<td style="text-align:center">?</td>
<td style="text-align:left">重复零次或一次</td>
</tr>
<tr>
<td style="text-align:center">{n}</td>
<td style="text-align:left">重复n次</td>
</tr>
<tr>
<td style="text-align:center">{n,}</td>
<td style="text-align:left">重复n次或更多次</td>
</tr>
<tr>
<td style="text-align:center">{n,m}</td>
<td style="text-align:left">重复n到m次</td>
</tr>
</tbody>
</table>
<p> 下面是一些使用重复的例子:<br><code>Windows\d+</code>匹配<em>Windows</em>后面跟1个或更多数字<br><code>^\w+</code>匹配一行的第一个单词(或整个字符串的第一个单词,具体匹配哪个意思得看选项设置)。</p>
<h2 id="字符类">字符类</h2>
<p> 要想查找数字,字母或数字,空白是很简单的,因为已经有了对应这些字符集合的元字符,但是如果你想匹配没有预定义元字符的字符集合(比如元音字母a,e,i,o,u),应该怎么办?<br> 很简单,你只需要在方括号里列出它们就行了,像 <code>[aeiou]</code> 就匹配任何一个英文元音字母,<code>[.?!]</code> 匹配标点符号(.或?或!)。<br> 我们也可以轻松地指定一个<strong>字符范围</strong>,像<code>[0-9]</code>代表的含意与<code>\d</code>就是完全一致的:一位数字;同理<code>[a-z0-9A-Z_]</code>也完全等同于<code>\w</code>(如果只考虑英文的话)。<br> 下面是一个更复杂的表达式:<code>\(?0\d{2}[) -]?\d{8}</code>。<br> 这个表达式可以匹配几种格式的电话号码,像(010)88886666,或 022-22334455,或 02912345678等。我们对它进行一些分析吧:首先是一个转义字符<code>\(</code>,它能出现0次或1次(?),然后是一个0,后面跟着2个数字(\d{2}),然后是)或-或空格中的一个,它出现1次或不出现(?),最后是8个数字(\d{8})。</p>
<h2 id="分枝条件">分枝条件</h2>
<p> 不幸的是,刚才那个表达式也能匹配 010)12345678 或 (022-87654321 这样的“不正确”的格式。要解决这个问题,我们需要用到<strong>分枝条件</strong>。正则表达式里的分枝条件指的是有几种规则,如果满足其中任意一种规则都应该当成匹配,具体方法是用|把不同的规则分隔开。听不明白?没关系,看例子:<br> <code>0\d{2}-\d{8}|0\d{3}-\d{7}</code> 这个表达式能匹配两种以连字号分隔的电话号码:一种是三位区号,8位本地号(如010-12345678),一种是4位区号,7位本地号(0376-2233445)。<br> <code>\(?0\d{2}\)?[- ]?\d{8}|0\d{2}[-]?\d{8}</code> 这个表达式匹配3位区号的电话号码,其中区号可以用小括号括起来,也可以不用,区号与本地号间可以用连字号或空格间隔,也可以没有间隔。你可以试试用分枝条件把这个表达式扩展成也支持4位区号的。<br> <code>\d{5}-\d{4}|\d{5}</code> 这个表达式用于匹配美国的邮政编码。美国邮编的规则是5位数字,或者用连字号间隔的9位数字。之所以要给出这个例子是因为它能说明一个问题:<strong>使用分枝条件时,要注意各个条件的顺序</strong>。如果你把它改成 <code>\d{5}|\d{5}-\d{4}</code> 的话,那么就只会匹配5位的邮编(以及9位邮编的前5位)。原因是匹配分枝条件时,将会从左到右地测试每个条件,如果满足了某个分枝的话,就不会去再管其它的条件了。</p>
<h2 id="分组">分组</h2>
<p> 我们已经提到了怎么重复单个字符(直接在字符后面加上限定符就行了);但如果想要重复多个字符又该怎么办?你可以用<strong>小括号来指定子表达式(也叫做分组)</strong>,然后你就可以指定这个子表达式的重复次数了,你也可以对子表达式进行其它一些操作(后面会有介绍)。<br> <code>(\d{1,3}\.){3}\d{1,3}</code> 是一个简单的IP地址匹配表达式。要理解这个表达式,请按下列顺序分析它:<code>\d{1,3}</code> 匹配1到3位的数字,<code>(\d{1,3}\.){3}</code>匹配三位数字加上一个英文句号(这个整体也就是这个分组)重复3次,最后再加上一个一到三位的数字 <code>(\d{1,3})</code>。</p>
<pre><code> <span class="literal">IP</span>地址中每个数字都不能大于<span class="number">255</span>. 经常有人问我, <span class="number">01.02</span><span class="string">.03</span><span class="string">.04</span> 这样前面带有<span class="number">0</span>的数字, 是不是正确的<span class="literal">IP</span>地址呢? 答案是: 是的, <span class="literal">IP</span> 地址里的数字可以包含有前导 <span class="number">0</span> (leading zeroes).
</code></pre><p> 不幸的是,它也将匹配 256.300.888.999 这种不可能存在的IP地址。如果能使用算术比较的话,或许能简单地解决这个问题,但是正则表达式中并不提供关于数学的任何功能,所以只能使用冗长的分组,选择,字符类来描述一个正确的IP地址:<code>((2[0-4]\d|25[0-5]|[01]?\d\d?)\.){3}(2[0-4]\d|25[0-5]|[01]?\d\d?)</code>。<br> 理解这个表达式的关键是理解 <code>2[0-4]\d|25[0-5]|[01]?\d\d?</code>,这里我就不细说了,你自己应该能分析得出来它的意义。</p>
<h2 id="反义">反义</h2>
<p> 有时需要查找不属于某个能简单定义的字符类的字符。比如想查找除了数字以外,其它任意字符都行的情况,这时需要用到反义(<strong>表3.常用的反义代码</strong>):</p>
<table>
<thead>
<tr>
<th style="text-align:center"><strong>代码/语法</strong></th>
<th style="text-align:left"><strong>说明</strong> </th>
</tr>
</thead>
<tbody>
<tr>
<td style="text-align:center">\W</td>
<td style="text-align:left">匹配任意不是字母,数字,下划线,汉字的字符</td>
</tr>
<tr>
<td style="text-align:center">\S</td>
<td style="text-align:left">匹配任意不是空白符的字符</td>
</tr>
<tr>
<td style="text-align:center">\D</td>
<td style="text-align:left">匹配任意非数字的字符</td>
</tr>
<tr>
<td style="text-align:center">\B</td>
<td style="text-align:left">匹配不是单词开头或结束的位置</td>
</tr>
<tr>
<td style="text-align:center">[^x]</td>
<td style="text-align:left">匹配除了x以外的任意字符</td>
</tr>
<tr>
<td style="text-align:center">[^aeiou]</td>
<td style="text-align:left">匹配除了aeiou这几个字母以外的任意字符</td>
</tr>
</tbody>
</table>
<p> 例子:<code>\S+</code>匹配不包含空白符的字符串。<br> <code><a[^>]+></code>匹配用尖括号括起来的以a开头的字符串。</p>
<h2 id="后向引用">后向引用</h2>
<p> 使用小括号指定一个子表达式后,<strong>匹配这个子表达式的文本</strong>(也就是此分组捕获的内容)可以在表达式或其它程序中作进一步的处理。默认情况下,每个分组会自动拥有一个组号,规则是:从左向右,以分组的左括号为标志,第一个出现的分组的组号为1,第二个为2,以此类推。</p>
<pre><code> 呃……其实,组号分配还不像我刚说得那么简单:
-<span class="ruby"> 分组<span class="number">0</span>对应整个正则表达式
</span>-<span class="ruby"> 实际上组号分配过程是要从左向右扫描两遍的:第一遍只给未命名组分配,第二遍只给命名组分配--因此所有命名组的组号都大于未命名的组号
</span>-<span class="ruby"> 你可以使用(?:exp)这样的语法来剥夺一个分组对组号分配的参与权.</span>
</code></pre><p> <strong>后向引用</strong>用于重复搜索前面某个分组匹配的文本。例如,<code>\1</code>代表分组1匹配的文本。难以理解?请看示例:<br> <code>\b(\w+)\b\s+\1\b</code> 可以用来匹配重复的单词,像<em>go go</em>, 或者 <em>kitty kitty</em>。这个表达式首先是一个单词,也就是单词开始处和结束处之间的多于一个的字母或数字 <code>(\b(\w+)\b)</code>,这个单词会被捕获到编号为1的分组中,然后是1个或几个空白符 <code>(\s+)</code>,最后是分组1中捕获的内容(也就是前面匹配的那个单词) <code>(\1)</code>。<br> 你也可以自己指定子表达式的<strong>组名</strong>。要指定一个子表达式的组名,请使用这样的语法:<code>(?<Word>\w+)</code>(或者把尖括号换成’也行:<code>(?'Word'\w+))</code>,这样就把 <code>\w+</code> 的组名指定为 <em>Word</em> 了。要反向引用这个分组<strong>捕获</strong>的内容,你可以使用 <code>\k<Word></code> ,所以上一个例子也可以写成这样:<code>\b(?<Word>\w+)\b\s+\k<Word>\b</code>。<br> 使用小括号的时候,还有很多特定用途的语法。下面列出了最常用的一些(<strong>表4.常用分组语法</strong>):</p>
<table>
<thead>
<tr>
<th style="text-align:center"><strong>分类</strong></th>
<th style="text-align:center"><strong>代码/语法</strong></th>
<th style="text-align:left"><strong>说明</strong></th>
</tr>
</thead>
<tbody>
<tr>
<td style="text-align:center">捕获</td>
<td style="text-align:center">(exp)</td>
<td style="text-align:left">匹配exp,并捕获文本到自动命名的组里</td>
</tr>
<tr>
<td style="text-align:center"></td>
<td style="text-align:center">(?<name>exp)</name></td>
<td style="text-align:left">匹配exp,并捕获文本到名称为name的组里,也可以写成(?’name’exp)</td>
</tr>
<tr>
<td style="text-align:center"></td>
<td style="text-align:center">(?:exp)</td>
<td style="text-align:left">匹配exp,不捕获匹配的文本,也不给此分组分配组号</td>
</tr>
<tr>
<td style="text-align:center">零宽断言</td>
<td style="text-align:center">(?=exp)</td>
<td style="text-align:left">匹配exp前面的位置</td>
</tr>
<tr>
<td style="text-align:center"></td>
<td style="text-align:center">(?<=exp)</td>
<td style="text-align:left">匹配exp后面的位置</td>
</tr>
<tr>
<td style="text-align:center"></td>
<td style="text-align:center">(?!exp)</td>
<td style="text-align:left">匹配后面跟的不是exp的位置</td>
</tr>
<tr>
<td style="text-align:center"></td>
<td style="text-align:center">(?<!exp)</td>
<td style="text-align:left">匹配前面不是exp的位置</td>
</tr>
<tr>
<td style="text-align:center">注释</td>
<td style="text-align:center">(?#comment)</td>
<td style="text-align:left">这种类型的分组不对正则表达式的处理产生任何影响,用于提供注释让人阅读</td>
</tr>
</tbody>
</table>
<p> 我们已经讨论了前两种语法。第三个<code>(?:exp)</code>不会改变正则表达式的处理方式,只是这样的组匹配的内容不会像前两种那样被捕获到某个组里面,也不会拥有组号。“我为什么会想要这样做?”——好问题,你觉得为什么呢?</p>
<h2 id="零宽断言">零宽断言</h2>
<p> 接下来的四个用于查找在某些内容(但并不包括这些内容)之前或之后的东西,也就是说它们像<code>\b</code>,<code>^</code>,<code>$</code>那样用于指定一个位置,这个位置应该满足一定的条件(即断言),因此它们也被称为<strong>零宽断言</strong>。最好还是拿例子来说明吧:</p>
<pre><code><span class="code"> 断言用来声明一个应该为真的事实。正则表达式中只有当断言为真时才会继续进行匹配。</span>
<span class="smartquote">`(?=exp)`也叫**零宽度正预测先行断言**,它断言自身出现的位置的后面能匹配表达式exp。比如 `\b\w+(?=ing\b)`,匹配以ing结尾的单词的前面部分(除了ing以外的部分),如查找*I'</span>m singing while you're dancing.* 时,它会匹配<span class="strong">*sing*</span>和<span class="strong">*danc*</span>。
</code></pre><p> <code>(?<=exp)</code>也叫<strong>零宽度正回顾后发断言</strong>,它断言自身出现的位置的前面能匹配表达式exp。比如 <code>(?<=\bre)\w+\b</code> 会匹配以re开头的单词的后半部分(除了re以外的部分),例如在查找 <em>reading a book</em> 时,它匹配 <em>ading</em> 。<br> 假如你想要给一个很长的数字中每三位间加一个逗号(当然是从右边加起了),你可以这样查找需要在前面和里面添加逗号的部分:<code>((?<=\d)\d{3})+\b</code>,用它对 1234567890 进行查找时结果是 234567890。<br> 下面这个例子同时使用了这两种断言:<code>(?<=\s)\d+(?=\s)</code> 匹配以空白符间隔的数字(再次强调,不包括这些空白符)。</p>
<h2 id="负向零宽断言">负向零宽断言</h2>
<p> 前面我们提到过怎么查找<strong>不是某个字符或不在某个字符类里的字符的方法(反义)</strong>。但是如果我们<strong>只是想要确保某个字符没有出现,但并不想去匹配它</strong>时怎么办?例如,如果我们想查找这样的单词—它里面出现了字母q,但是q后面跟的不是字母u,我们可以尝试这样:<br> <code>\b\w*q[^u]\w*\b</code>匹配包含后面不是字母u的字母q的单词。但是如果多做测试(或者你思维足够敏锐,直接就观察出来了),你会发现,如果q出现在单词的结尾的话,像<em>Iraq,Benq</em>,这个表达式就会出错。这是因为<code>[^u]</code>总要匹配一个字符,所以如果q是单词的最后一个字符的话,后面的<code>[^u]</code>将会匹配q后面的单词分隔符(可能是空格,或者是句号或其它的什么),后面的\w<code>*\b</code>将会匹配下一个单词,于是 <code>b\w*q[^u]\w*\b</code> 就能匹配整个 <em>Iraq fighting</em> 。<strong>负向零宽断言</strong>能解决这样的问题,因为它只匹配一个位置,并不消费任何字符。现在,我们可以这样来解决这个问题:<code>\b\w*q(?!u)\w*\b</code>。<br><strong>零宽度负预测先行断言</strong><code>(?!exp)</code>,断言此位置的后面不能匹配表达式exp。例如:<code>\d{3}(?!\d)</code>匹配三位数字,而且这三位数字的后面不能是数字;<code>\b((?!abc)\w)+\b</code>匹配不包含连续字符串abc的单词。<br> 同理,我们可以用<code>(?<!exp)</code>,<strong>零宽度负回顾后发断言</strong>来断言此位置的前面不能匹配表达式<code>exp:(?<![a-z])\d{7}</code>匹配前面不是小写字母的七位数字。</p>
<pre><code> 请详细分析表达式 `(?<span class="variable"><=<(\w+)></span>).<span class="keyword">*</span>(?=<span class="variable"><\/\1></span>)`,这个表达式最能表现零宽断言的真正用途。
</code></pre><p> 一个更复杂的例子:<code>(?<=<(\w+)>).*(?=<\/\1>) 匹配不包含属性的简单 HTML 标签内里的内容。</code>(?<=<(\w+)>)<code>指定了这样的**前缀**:被尖括号括起来的单词(比如可能是</code><b><code>),然后是</code>.<em>`(任意的字符串),最后是一个<em>*后缀</em></em><code>(?=<\/\1>)</code>。注意后缀里的<code>\/</code>,它用到了前面提过的字符转义;<code>\1</code>则是一个反向引用,引用的正是捕获的第一组,前面的<code>(\w+)</code>匹配的内容,这样如果前缀实际上是<code><b></code>的话,后缀就是<code></b></code>了。整个表达式匹配的是<code><b></code>和<code></b></code>之间的内容(再次提醒,不包括前缀和后缀本身)。</b></p>
<h2 id="注释">注释</h2>
<p> 小括号的另一种用途是通过语法 <code>(?#comment)</code> 来包含注释。例如:<code>2[0-4]\d(?#200-249)|25[0-5](?#250-255)|[01]?\d\d?(?#0-199)</code>。<br> 要包含注释的话,最好是启用“忽略模式里的空白符”选项,这样在编写表达式时能任意的添加空格,Tab,换行,而实际使用时这些都将被忽略。启用这个选项后,在#后面到这一行结束的所有文本都将被当成注释忽略掉。例如,我们可以前面的一个表达式写成这样:</p>
<pre><code> (?<span class="variable"><= # 断言要匹配的文本的前缀
<(\w+)></span> <span class="comment"># 查找尖括号括起来的字母或数字(即HTML/XML标签)</span>
) <span class="comment"># 前缀结束</span>
.<span class="keyword">*</span> <span class="comment"># 匹配任意文本</span>
(?= <span class="comment"># 断言要匹配的文本的后缀</span>
<span class="variable"><\/\1></span> <span class="comment"># 查找尖括号括起来的内容:前面是一个"/",后面是先前捕获的标签</span>
) <span class="comment"># 后缀结束</span>
</code></pre><h2 id="贪婪与懒惰">贪婪与懒惰</h2>
<p> 当正则表达式中包含能接受重复的限定符时,通常的行为是(在使整个表达式能得到匹配的前提下)<strong>匹配尽可能多的字符</strong>。以这个表达式为例:<code>a.*b</code>,它将会匹配最长的以a开始,以b结束的字符串。如果用它来搜索<em>aabab</em>的话,它会匹配整个字符串<em>aabab</em>。这被称为<strong>贪婪匹配</strong>。<br> 有时,我们更需要<strong>懒惰匹配</strong>,也就是匹配尽可能少的字符。前面给出的限定符都可以被转化为懒惰匹配模式,只要在它后面加上一个问号<code>?</code>。这样<code>.*?</code>就意味着匹配任意数量的重复,但是在能使整个匹配成功的前提下使用最少的重复。现在看看懒惰版的例子吧:<br> <code>a.*?b</code>匹配最短的,以 a 开始,以 b 结束的字符串。如果把它应用于<em>aabab</em>的话,它会匹配<em>aab</em>(第一到第三个字符)和<em>ab</em>(第四到第五个字符)。(<strong>表5.懒惰限定符</strong>)</p>
<table>
<thead>
<tr>
<th style="text-align:center"><strong>代码/语法</strong></th>
<th style="text-align:left"><strong>说明</strong> </th>
</tr>
</thead>
<tbody>
<tr>
<td style="text-align:center">*?</td>
<td style="text-align:left">重复任意次,但尽可能少重复</td>
</tr>
<tr>
<td style="text-align:center">+?</td>
<td style="text-align:left">重复1次或更多次,但尽可能少重复</td>
</tr>
<tr>
<td style="text-align:center">??</td>
<td style="text-align:left">重复0次或1次,但尽可能少重复</td>
</tr>
<tr>
<td style="text-align:center">{n,m}?</td>
<td style="text-align:left">重复n到m次,但尽可能少重复</td>
</tr>
<tr>
<td style="text-align:center">{n,}?</td>
<td style="text-align:left">重复n次以上,但尽可能少重复</td>
</tr>
</tbody>
</table>
<h2 id="处理选项">处理选项</h2>
<p> 上面介绍了几个选项如忽略大小写,处理多行等,这些选项能用来改变处理正则表达式的方式。下面是.Net中常用的正则表达式选项(<strong>表6.常用的处理选项</strong>):</p>
<table>
<thead>
<tr>
<th style="text-align:center"><strong>名称</strong></th>
<th style="text-align:left"><strong>说明</strong> </th>
</tr>
</thead>
<tbody>
<tr>
<td style="text-align:center">IgnoreCase(忽略大小写)</td>
<td style="text-align:left">匹配时不区分大小写。</td>
</tr>
<tr>
<td style="text-align:center">Multiline(多行模式)</td>
<td style="text-align:left">更改^和$的含义,使它们分别在任意一行的行首和行尾匹配,而不仅仅在整个字符串的开头和结尾匹配。(在此模式下,$的精确含意是:匹配\n之前的位置以及字符串结束前的位置.)</td>
</tr>
<tr>
<td style="text-align:center">Singleline(单行模式)</td>
<td style="text-align:left">更改.的含义,使它与每一个字符匹配(包括换行符\n)。</td>
</tr>
<tr>
<td style="text-align:center">IgnorePatternWhitespace(忽略空白)</td>
<td style="text-align:left">忽略表达式中的非转义空白并启用由#标记的注释。</td>
</tr>
<tr>
<td style="text-align:center">ExplicitCapture(显式捕获)</td>
<td style="text-align:left">仅捕获已被显式命名的组。</td>
</tr>
</tbody>
</table>
<p> 一个经常被问到的问题是:是不是只能同时使用多行模式和单行模式中的一种?答案是:不是。这两个选项之间没有任何关系,除了它们的名字比较相似(以至于让人感到疑惑)以外。</p>
<h2 id="平衡组/递归匹配">平衡组/递归匹配</h2>
<p> 有时我们需要匹配像 ( 100 * ( 50 + 15 ) ) 这样的可嵌套的层次性结构,这时简单地使用 <code>\(.+\)</code> 则只会匹配到最左边的左括号和最右边的右括号之间的内容(这里我们讨论的是贪婪模式,懒惰模式也有下面的问题)。假如原来的字符串里的左括号和右括号出现的次数不相等,比如 ( 5 / ( 3 + 2 ) ) ),那我们的匹配结果里两者的个数也不会相等。有没有办法在这样的字符串里匹配到最长的,配对的括号之间的内容呢?<br> 为了避免(和<code>\(</code>把你的大脑彻底搞糊涂,我们还是用尖括号代替圆括号吧。现在我们的问题变成了如何把<code>xx <aa <bbb> <bbb> aa> yy</code>这样的字符串里,最长的配对的尖括号内的内容捕获出来?<br> 这里需要用到以下的语法构造:
</p>
<ul>
<li><code>(?'group')</code> 把捕获的内容命名为group,并压入<strong>堆栈(Stack)</strong></li>
<li><code>(?'-group')</code>从堆栈上弹出最后压入堆栈的名为group的捕获内容,如果堆栈本来为空,则本分组的匹配失败</li>
<li><code>(?(group)yes|no)</code> 如果堆栈上存在以名为group的捕获内容的话,继续匹配yes部分的表达式,否则继续匹配no部分</li>
<li><p><code>(?!)</code> 零宽负向先行断言,由于没有后缀表达式,试图匹配总是失败</p>
<pre><code> 如果你不是一个程序员(或者你自称程序员但是不知道堆栈是什么东西),你就这样理解上面的三种语法吧:第一个就是在黑板上写一个<span class="string">"group"</span>,第二个就是从黑板上擦掉一个<span class="string">"group"</span>,第三个就是看黑板上写的还有没有<span class="string">"group"</span>,如果有就继续匹配<span class="literal">yes</span>部分,否则就匹配<span class="literal">no</span>部分。
</code></pre></li>
</ul>
<p> 我们需要做的是每碰到了左括号,就在压入一个”Open”,每碰到一个右括号,就弹出一个,到了最后就看看堆栈是否为空--如果不为空那就证明左括号比右括号多,那匹配就应该失败。正则表达式引擎会进行回溯(放弃最前面或最后面的一些字符),尽量使整个表达式得到匹配。</p>
<pre><code><span class="variable">< #最外层的左括号
[^<></span>]<span class="keyword">*</span> <span class="comment">#最外层的左括号后面的不是括号的内容</span>
(
(
(?'Open'<span class="variable"><) #碰到了左括号,在黑板上写一个"Open"
[^<></span>]<span class="keyword">*</span> <span class="comment">#匹配左括号后面的不是括号的内容</span>
)+
(
(?'-Open'>) <span class="comment">#碰到了右括号,擦掉一个"Open"</span>
[^<span class="variable"><></span>]<span class="keyword">*</span> <span class="comment">#匹配右括号后面不是括号的内容</span>
)+
)<span class="keyword">*</span>
(?(Open)(?!)) <span class="comment">#在遇到最外层的右括号前面,判断黑板上还有没有没擦掉的"Open";如果还有,则匹配失败</span>
> <span class="comment">#最外层的右括号</span>
</code></pre><p> 平衡组的一个最常见的应用就是匹配HTML,下面这个例子可以匹配嵌套的< div >标签。</p>
<figure class="highlight html"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line"><span class="tag"><<span class="title">div[^</span>></span>]*>[^<span class="tag"><></span>]*(((?'Open'<span class="tag"><<span class="title">div[^</span>></span>]*>)[^<span class="tag"><></span>]*)+((?'-Open'<span class="tag"></<span class="title">div</span>></span>)[^<span class="tag"><></span>]*)+)*(?(Open)(?!))<span class="tag"></<span class="title">div</span>></span></div></pre></td></tr></table></figure>
<h2 id="参考文献">参考文献</h2>
<ul>
<li><a href="http://item.jd.com/11070361.html?sid=deerchao&t=1" target="_blank" rel="external">精通正则表达式(第3版)</a></li>
<li><a href="http://msdn.microsoft.com/zh-cn/library/az24scfc.aspx" target="_blank" rel="external">微软的正则表达式教程</a></li>
<li><a href="http://msdn.microsoft.com/zh-cn/library/system.text.regularexpressions.regex.aspx" target="_blank" rel="external">System.Text.RegularExpressions.Regex类(MSDN)</a></li>
<li><a href="http://www.regular-expressions.info/pressions.regex.aspx" target="_blank" rel="external">专业的正则表达式教学网站(英文)</a></li>
</ul>
<p>作者:<a href="http://deerchao.net/" target="_blank" rel="external">deerchao</a> — 转自<a href="http://deerchao.net/tutorials/regex/regex.htm#mission" target="_blank" rel="external">原文</a></p>
]]></content>
<summary type="html">
<![CDATA[<h2 id="本文目标">本文目标</h2>
<p> 30分钟内让你明白正则表达式是什么,并对它有一些基本的了解,让你可以在自己的程序或网页里使用它。</p>
<h2 id="如何使用本教程">如何使用本教程</h2>
<p> 别被下面那些复杂的表达式吓倒,只要跟着我一步一]]>
</summary>
<category term="Tools" scheme="http://chenqx.github.com/tags/Tools/"/>
<category term="NLP" scheme="http://chenqx.github.com/tags/NLP/"/>
<category term="Tools" scheme="http://chenqx.github.com/categories/Tools/"/>
</entry>
<entry>
<title><![CDATA[Scrapy爬虫抓取动态网站]]></title>
<link href="http://chenqx.github.com/2014/12/23/Spider-Advanced-for-Dynamic-Website-Crawling/"/>
<id>http://chenqx.github.com/2014/12/23/Spider-Advanced-for-Dynamic-Website-Crawling/</id>
<published>2014-12-23T01:13:05.000Z</published>
<updated>2015-01-31T09:48:56.000Z</updated>
<content type="html"><![CDATA[<p> 前面一文<a href="http://chenqx.github.io/2014/11/09/Scrapy-Tutorial-for-BBSSpider/" target="_blank" rel="external">Scrapy爬虫抓取网站数据</a>已经介绍了如何实现一个爬虫,文中介绍静态bbs网页的抓取。但是,互联网大部分的web页面都是动态的,经常逛的网站例如京东、淘宝等,商品列表都是js,并有Ajax渲染,这样就获取不到网页内容(获取到后台数据后再组合成html展示出来的)。单纯获取页面而没有执行到js的话是无法看到商品数据列表信息的。<br> 那么,我们可以怎么获取这些数据呢?本文以典型的<strong>比价网站</strong>为例,如:<a href="http://gouwu.sogou.com/" target="_blank" rel="external"><strong>搜狗购物</strong></a>,<a href="http://www.etao.com/" target="_blank" rel="external"><strong>一淘网</strong></a>,抓取给定商品的价格及其来源网站,如下图。详见<a href="https://github.com/chenqx/spiderDemo/tree/master/gouwu.sogou.com" target="_blank" rel="external">完整的爬虫代码</a>。<br> <img src="http://newtonblogimg.qiniudn.com/searching.png" alt="Search list"><br> <img src="http://newtonblogimg.qiniudn.com/items.png" alt="抓取内容"></p>
<h2 id="Preliminaries">Preliminaries</h2>
<p> 抓取前先了解一些概念和工具。</p>
<h3 id="什么是动态网页">什么是动态网页</h3>
<p> <a href="http://baike.baidu.com/link?url=ZZmfwSxRg3-ZicJDgja2o6tOmEV-ionvlI6uOTUqEOsdZV4qHVjZybUOl-W_xGBSZJ_6sP4mKfBYfuHiNTiSS_" target="_blank" rel="external">动态网页</a>是指跟静态网页相对的一种网页编程技术。静态网页,随着html代码的生成,页面的内容和显示效果就基本上不会发生变化了——除非你修改页面代码。而动态网页则不然,页面代码虽然没有变,但是显示的内容却是可以随着时间、环境或者数据库操作的结果而发生改变的。与静态网页相对应的,能与后台数据库进行交互,数据传递。也就是说,网页 URL的后缀不是.htm、.html、.shtml、.xml等静态网页的常见形动态网页制作格式,而是以.aspx、.asp、.jsp、.php、.perl、.cgi等形式为后缀,并且在动态网页网址中有一个标志性的符号——“?”。可以通过以下方式简单验证某网页是否为动态网页。</p>
<pre><code> 在页面上右键查看源代码,和右键审查元素所看到的html代码是不一样的,如果后者中能看到商品数据信息,而前者没有的话,就说明这个页面是动态生成的。
</code></pre><h3 id="Selenium">Selenium</h3>
<p> <a href="http://www.seleniumhq.org/" target="_blank" rel="external">Selenium</a>是Thoughtworks公司的一个集成测试的强大工具。Selenium 是 ThoughtWorks 专门为 Web 应用程序编写的一个验收测试工具。与其他测试工具相比,使用 Selenium 的最大好处是: Selenium 测试直接在浏览器中运行,就像真实用户所做的一样。在浏览器加载js后,便可以通过xpath来解析网页了。可以先用 pip install 或 easy_install 安装 Selenium package。</p>
<figure class="highlight python"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">pip install -U selenium</div></pre></td></tr></table></figure>
<h2 id="编写_Spider">编写 Spider</h2>
<p> 这里就不详细说明 <code>item</code>、<code>pipeline</code>、<code>setting</code>文件的编写了。如果对这些模块不熟的话可以先看看 <a href="http://chenqx.github.io/2014/11/09/Scrapy-Tutorial-for-BBSSpider/" target="_blank" rel="external">Our first spider</a>。</p>
<h3 id="获得检索商品页面">获得检索商品页面</h3>
<p> 搜索某一款产品,如 Iphone6,我们就可以得到该产品检索结果的起始页面的 <code>start_urls</code>。但通常情况下,我们可能要得到很多商品相应的信息,那该怎么处理呢?容易想到的是让浏览器模拟我们手动输入,自动响应检索事件,从而得到目标页面的 <code>start_urls</code>。另一种方法是,我们将目标产品存到一个配置文件中,直接将<code>http://gouwu.sogou.com/shop?query=</code>+ <code>ItemList</code> 作为 <code>start_urls</code>。这里采用后一种方法,简单粗暴有效。</p>
<figure class="highlight Python"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div></pre></td><td class="code"><pre><div class="line"><span class="comment">#import lstData</span></div><div class="line">start_urls = [ (<span class="string">'http://gouwu.sogou.com/shop?query='</span> + searchWord ) <span class="keyword">for</span> searchWord <span class="keyword">in</span> lstData().lst]</div></pre></td></tr></table></figure>
<h3 id="解析网页">解析网页</h3>
<p> 首先启用 selenium,这里用本地浏览器 Firefox:</p>
<figure class="highlight python"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div></pre></td><td class="code"><pre><div class="line"><span class="function"><span class="keyword">def</span> <span class="title">__init__</span><span class="params">(self)</span>:</span></div><div class="line"> CrawlSpider.__init__(self)</div><div class="line"> <span class="comment"># use any browser you wish</span></div><div class="line"> self.browser = webdriver.Firefox() </div><div class="line"></div><div class="line"><span class="function"><span class="keyword">def</span> <span class="title">__del__</span><span class="params">(self)</span>:</span></div><div class="line"> self.browser.close()</div></pre></td></tr></table></figure>
<p> 得到所有产品的 <code>start_urls</code> 后,我们便可以通过 <code>Xpath</code> 提取想要的数据了。这里抓取的内容有标题、价格和来源网站。</p>
<figure class="highlight python"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div></pre></td><td class="code"><pre><div class="line">_x_query = {</div><div class="line"> <span class="string">'title'</span>: <span class="string">'//p[@class="title"]/a/@title'</span>,</div><div class="line"> <span class="string">'price'</span> : <span class="string">'//span[@class="shopprice font17"]/text()'</span>,</div><div class="line"> <span class="string">'name'</span>: <span class="string">'//span[@class="floatR hui61 mt1"]/text()'</span>,<span class="comment">##source</span></div><div class="line"> }</div></pre></td></tr></table></figure>
<p> 然后提取页面(下一页),定义提取和过滤 <code>url</code>:</p>
<figure class="highlight python"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div></pre></td><td class="code"><pre><div class="line">link_extractor = {</div><div class="line"> <span class="string">'page_down'</span>: SgmlLinkExtractor(allow = <span class="string">'/shop\?query=.+'</span>,),<span class="comment">#restrict_xpaths = '//a[@class = "pagination-next"]'</span></div><div class="line"> <span class="string">'page'</span>: SgmlLinkExtractor(allow = <span class="string">'/detail/\d+\.html.+'</span>),</div><div class="line"> }</div></pre></td></tr></table></figure>
<p> 这样我们的 Spider 就差不多定义好了。完整 Spider 程序如下:</p>
<figure class="highlight python"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div><div class="line">20</div><div class="line">21</div><div class="line">22</div><div class="line">23</div><div class="line">24</div><div class="line">25</div><div class="line">26</div><div class="line">27</div><div class="line">28</div><div class="line">29</div><div class="line">30</div><div class="line">31</div><div class="line">32</div><div class="line">33</div><div class="line">34</div><div class="line">35</div><div class="line">36</div><div class="line">37</div><div class="line">38</div><div class="line">39</div><div class="line">40</div><div class="line">41</div><div class="line">42</div><div class="line">43</div><div class="line">44</div><div class="line">45</div><div class="line">46</div><div class="line">47</div><div class="line">48</div><div class="line">49</div><div class="line">50</div><div class="line">51</div><div class="line">52</div><div class="line">53</div><div class="line">54</div><div class="line">55</div><div class="line">56</div><div class="line">57</div></pre></td><td class="code"><pre><div class="line"><span class="comment">#-*- coding: utf-8 -*-</span></div><div class="line"><span class="string">'''</span></div><div class="line">gouwu.sogou.com Spider, Created on Dec, 2014</div><div class="line">#version: 1.0</div><div class="line">#author: chenqx @http://chenqx.github.com</div><div class="line">See more: http://doc.scrapy.org/en/latest/index.html</div><div class="line">'''</div><div class="line"><span class="keyword">import</span> time</div><div class="line"><span class="keyword">from</span> scrapy.selector <span class="keyword">import</span> Selector</div><div class="line"><span class="keyword">from</span> scrapy.http <span class="keyword">import</span> Request</div><div class="line"><span class="keyword">from</span> scrapy.contrib.spiders <span class="keyword">import</span> CrawlSpider</div><div class="line"><span class="keyword">from</span> scrapy.contrib.loader <span class="keyword">import</span> ItemLoader</div><div class="line"><span class="keyword">from</span> scrapy.contrib.linkextractors.sgml <span class="keyword">import</span> SgmlLinkExtractor</div><div class="line"><span class="keyword">from</span> etao.items <span class="keyword">import</span> EtaoItem</div><div class="line"><span class="keyword">from</span> etao.lstData <span class="keyword">import</span> lstData</div><div class="line"><span class="keyword">from</span> selenium <span class="keyword">import</span> webdriver</div><div class="line"></div><div class="line"><span class="class"><span class="keyword">class</span> <span class="title">etaoSpider</span><span class="params">(CrawlSpider)</span>:</span></div><div class="line"> <span class="comment"># name of spiders</span></div><div class="line"> name = <span class="string">'Spider'</span></div><div class="line"> allow_domain = [<span class="string">'gouwu.sogou.com'</span>]</div><div class="line"> start_urls = [ (<span class="string">'http://gouwu.sogou.com/shop?query='</span> + searchWord ) <span class="keyword">for</span> searchWord <span class="keyword">in</span> lstData().lst]</div><div class="line"> link_extractor = {</div><div class="line"> <span class="string">'page'</span>: SgmlLinkExtractor(allow = <span class="string">'/detail/\d+\.html.+'</span>),</div><div class="line"> <span class="string">'page_down'</span>: SgmlLinkExtractor(allow = <span class="string">'/shop\?query=.+'</span>,),<span class="comment">#restrict_xpaths = '//a[@class = "pagination-next"]'</span></div><div class="line"> }</div><div class="line"> _x_query = {</div><div class="line"> <span class="string">'title'</span>: <span class="string">'//p[@class="title"]/a/@title'</span>,</div><div class="line"> <span class="string">'name'</span>: <span class="string">'//span[@class="floatR hui61 mt1"]/text()'</span>,<span class="comment">#//li[2]/a/div[@class="ruyitao-market-name ruyitao-market-name-hightlight"]/text()</span></div><div class="line"> <span class="string">'price'</span> : <span class="string">'//span[@class="shopprice font17"]/text()'</span>, <span class="comment"># 'price' : '//span[@class = "price"]/text()',</span></div><div class="line"> }</div><div class="line"></div><div class="line"> <span class="function"><span class="keyword">def</span> <span class="title">__init__</span><span class="params">(self)</span>:</span></div><div class="line"> CrawlSpider.__init__(self)</div><div class="line"> <span class="comment"># use any browser you wish</span></div><div class="line"> self.browser = webdriver.Firefox() </div><div class="line"></div><div class="line"> <span class="function"><span class="keyword">def</span> <span class="title">__del__</span><span class="params">(self)</span>:</span></div><div class="line"> self.browser.close()</div><div class="line"></div><div class="line"> <span class="function"><span class="keyword">def</span> <span class="title">parse</span><span class="params">(self, response)</span>:</span></div><div class="line"> <span class="comment">#crawl all display page</span></div><div class="line"> <span class="keyword">for</span> link <span class="keyword">in</span> self.link_extractor[<span class="string">'page_down'</span>].extract_links(response):</div><div class="line"> <span class="keyword">yield</span> Request(url = link.url, callback=self.parse)</div><div class="line"></div><div class="line"> <span class="comment">#start browser</span></div><div class="line"> self.browser.get(response.url)</div><div class="line"> <span class="comment">#loading time interval</span></div><div class="line"> time.sleep(<span class="number">5</span>)</div><div class="line"> <span class="comment"># get the data and write it to scrapy items</span></div><div class="line"> etaoItem_loader = ItemLoader(item=EtaoItem(), response = response)</div><div class="line"> url = str(response.url)</div><div class="line"> etaoItem_loader.add_value(<span class="string">'url'</span>, url)</div><div class="line"> etaoItem_loader.add_xpath(<span class="string">'title'</span>, self._x_query[<span class="string">'title'</span>])</div><div class="line"> etaoItem_loader.add_xpath(<span class="string">'name'</span>, self._x_query[<span class="string">'name'</span>])</div><div class="line"> etaoItem_loader.add_xpath(<span class="string">'price'</span>, self._x_query[<span class="string">'price'</span>])</div><div class="line"> <span class="keyword">yield</span> etaoItem_loader.load_item()</div></pre></td></tr></table></figure>
<h2 id="结论">结论</h2>
<p> 本文介绍了利用 selenium 实现动态网站数据抓取的一种方法。但需要注意的是 selenium 需要运行本地浏览器,比较耗时,不太适合大规模网页抓取。因此可以尝试其它的 Javascript 加载工具,如 webkit、spynner,也可以调用无界面依赖的浏览器引擎 Casperjs、Phantomjs等。
</p>
]]></content>
<summary type="html">
<![CDATA[<p> 前面一文<a href="http://chenqx.github.io/2014/11/09/Scrapy-Tutorial-for-BBSSpider/" target="_blank" rel="external">Scrapy爬虫抓取网站数据</a>已经介绍了如]]>
</summary>
<category term="Python" scheme="http://chenqx.github.com/tags/Python/"/>
<category term="Scrapy" scheme="http://chenqx.github.com/tags/Scrapy/"/>
<category term="Develop" scheme="http://chenqx.github.com/categories/Develop/"/>
</entry>
<entry>
<title><![CDATA[8 Easy Steps to Becoming a Data Scientist]]></title>
<link href="http://chenqx.github.com/2014/12/08/8-Easy-Steps-to-Becoming-a-Data-Scientist/"/>
<id>http://chenqx.github.com/2014/12/08/8-Easy-Steps-to-Becoming-a-Data-Scientist/</id>
<published>2014-12-08T11:48:46.000Z</published>
<updated>2014-12-08T10:29:48.000Z</updated>
<content type="html"><![CDATA[<p><img src="http://blog.datacamp.com/wp-content/uploads/2014/08/How-to-become-a-data-scientist.jpg" alt="8 Easy Steps to Becoming a Data Scientist"></p>
<!--[1]: /img/blogImage/How-to-become-a-data-scientist.jpg-->
]]></content>
<summary type="html">
<![CDATA[<p><img src="http://blog.datacamp.com/wp-content/uploads/2014/08/How-to-become-a-data-scientist.jpg" alt="8 Easy Steps to Becoming a Data Sc]]>
</summary>
<category term="Data Mining" scheme="http://chenqx.github.com/tags/Data-Mining/"/>
<category term="Data Mining" scheme="http://chenqx.github.com/categories/Data-Mining/"/>
</entry>
<entry>
<title><![CDATA[A Few Useful Things to Know about Machine Learning]]></title>
<link href="http://chenqx.github.com/2014/12/03/A-Few-Useful-Things-to-Know-about-Machine-Learning/"/>
<id>http://chenqx.github.com/2014/12/03/A-Few-Useful-Things-to-Know-about-Machine-Learning/</id>
<published>2014-12-03T08:48:46.000Z</published>
<updated>2014-12-08T11:14:32.000Z</updated>
<content type="html"><![CDATA[<p> 下图是<a href="https://breezedeus.github.io/2012/10/30/breezedeus-things-about-ml.html" target="_blank" rel="external">BreezeDeus</a>对Pedro Domingos 发表在 Communications of the ACM 2012年第10期的的论文<a href="http://homes.cs.washington.edu/~pedrod/papers/cacm12.pdf" target="_blank" rel="external">《A few useful things to know about machine learning》</a>的总结,大图可以在<a href="http://pan.baidu.com/s/1hqBX1h6" target="_blank" rel="external">这里下载</a>,也可以阅读<a href="http://www.valleytalk.org/wp-content/uploads/2012/11/%E6%9C%BA%E5%99%A8%E5%AD%A6%E4%B9%A0%E9%82%A3%E4%BA%9B%E4%BA%8B.pdf" target="_blank" rel="external">译文</a>。一篇非常不错的介绍 Machine Learning 的文章。<br> <br><img src="http://newtonblogimg.qiniudn.com/A%20few%20useful%20things%20to%20know%20about%20machine%20learning.jpg" alt="A Few Useful Things to Know about Machine Learning"></p>
]]></content>
<summary type="html">
<![CDATA[<p> 下图是<a href="https://breezedeus.github.io/2012/10/30/breezedeus-things-about-ml.html" target="_blank" rel="external">BreezeDeus</a>对Pedr]]>
</summary>
<category term="Machine Learning" scheme="http://chenqx.github.com/tags/Machine-Learning/"/>
<category term="Machine Learning" scheme="http://chenqx.github.com/categories/Machine-Learning/"/>
</entry>
<entry>
<title><![CDATA[Python 2.7.x 与 Python 3.x 的主要差异]]></title>
<link href="http://chenqx.github.com/2014/11/10/Key-differences-between-Python-2-7-x-and-Python-3-x/"/>
<id>http://chenqx.github.com/2014/11/10/Key-differences-between-Python-2-7-x-and-Python-3-x/</id>
<published>2014-11-10T12:04:25.000Z</published>
<updated>2015-01-31T09:55:46.000Z</updated>
<content type="html"><![CDATA[<p> 因这学期负责Python课程的助教,刚开始上机试验的几节课,有很多同学用 Python3.4 的编译器编译 Python 2.7 的程序而导致不通过。Python 2.7.x 和 Python 3.x 版本并非完全兼容。<br> 许多 Python 初学者想知道他们应该从 Python 的哪个版本开始学习。对于这个问题我的答案是 “你学习你喜欢的教程的版本,然后检查他们之间的不同。” 但如果你并未了解过两个版本之间的差异,个人推荐使用 Python 2.7.x 版本,毕竟大部分教材等资料还是用Python 2.7.x来写的。<br> 但是如果你开始一个新项目,并且有选择权?我想说的是目前没有对错,只要你计划使用的库 Python 2.7.x 和 Python 3.x 双方都支持的话。尽管如此,当在编写它们中的任何一个的代码,或者是你计划移植你的项目的时候,是非常值得看看这两个主要流行的 Python 版本之间的差别的,以便避免常见的陷阱。<br> 本文翻译自:<a href="http://nbviewer.ipython.org/github/rasbt/python_reference/blob/master/tutorials/key_differences_between_python_2_and_3.ipynb?create=1" target="_blank" rel="external">《Key differences between Python 2.7.x and Python 3.x》</a></p>
<h2 id="__future__模块"><strong><code>__future__</code>模块</strong></h2>
<p> Python 3.x 介绍的 一些Python 2 不兼容的关键字和特性可以通过在 Python 2 的内置 <code>__future__</code> 模块导入。如果你计划让你的代码支持 Python 3.x,建议你使用 <code>__future__</code> 模块导入。例如,如果我想要 在Python 2 中表现 Python 3.x 中的整除,我们可以通过如下导入</p>
<figure class="highlight Python"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line"><span class="keyword">from</span> __future__ <span class="keyword">import</span> division</div></pre></td></tr></table></figure>
<p> 更多的 <code>__future__</code> 模块可被导入的特性被列在下表中:</p>
<table>
<thead>
<tr>
<th><strong>feature</strong></th>
<th style="text-align:right"><strong>optional in</strong></th>
<th style="text-align:center"><strong>mandatory in</strong></th>
<th><strong>effect</strong></th>
</tr>
</thead>
<tbody>
<tr>
<td>nested_scopes</td>
<td style="text-align:right">2.1.0b1</td>
<td style="text-align:center">2.2</td>
<td><a href="http://legacy.python.org/dev/peps/pep-0227/" target="_blank" rel="external">PEP 227</a>: Statically Nested Scopes</td>
</tr>
<tr>
<td>generators</td>
<td style="text-align:right">2.2.0a1</td>
<td style="text-align:center">2.3</td>
<td><a href="http://legacy.python.org/dev/peps/pep-0255/" target="_blank" rel="external">PEP 255</a>: Simple Generators</td>
</tr>
<tr>
<td>division</td>
<td style="text-align:right">2.2.0a2</td>
<td style="text-align:center">3.0</td>
<td><a href="http://legacy.python.org/dev/peps/pep-0238/" target="_blank" rel="external">PEP 238</a>: Changing the Division Operator</td>
</tr>
<tr>
<td>absolute_import</td>
<td style="text-align:right">2.5.0a1</td>
<td style="text-align:center">3.0</td>
<td><a href="http://legacy.python.org/dev/peps/pep-0328/" target="_blank" rel="external">PEP 328</a>: Imports: Multi-Line and Absolute/Relative</td>
</tr>
<tr>
<td>with_statement</td>
<td style="text-align:right">2.5.0a1</td>
<td style="text-align:center">2.6</td>
<td><a href="http://www.python.org/dev/peps/pep-0343" target="_blank" rel="external">PEP 343</a>: The “with” Statement</td>
</tr>
<tr>
<td>print_function</td>
<td style="text-align:right">2.5.0a2</td>
<td style="text-align:center">3.0</td>
<td><a href="http://legacy.python.org/dev/peps/pep-3105/" target="_blank" rel="external">PEP 3105</a>: Make print a function</td>
</tr>
<tr>
<td>unicode_literals</td>
<td style="text-align:right">2.5.0a2</td>
<td style="text-align:center">3.0</td>
<td><a href="http://legacy.python.org/dev/peps/pep-3112/" target="_blank" rel="external">PEP 3112</a>: Bytes literals in Python 3000</td>
</tr>
</tbody>
</table>
<p>(Source: <a href="https://docs.python.org/2/library/future.html" target="_blank" rel="external">https://docs.python.org/2/library/future.html</a>)</p>
<figure class="highlight Python"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line"><span class="keyword">from</span> platform <span class="keyword">import</span> python_version</div></pre></td></tr></table></figure>
<h2 id="print函数"><strong><code>print</code>函数</strong></h2>
<p> 很琐碎,而 <code>print</code> 语法的变化可能是最广为人知的了,但是仍值得一提的是: Python 2 的 print 声明已经被 <code>print()</code> 函数取代了,这意味着我们必须包装我们想打印在小括号中的对象。<br>Python 2 不具有额外的小括号问题。但对比一下,如果我们按照 Python 2 的方式不使用小括号调用 <code>print</code> 函数,Python 3 将抛出一个语法异常(<code>SyntaxError</code>)。</p>
<p><strong><em>Python 2</em></strong></p>
<figure class="highlight Python"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div></pre></td><td class="code"><pre><div class="line"><span class="keyword">print</span> <span class="string">'Python'</span>, python_version()</div><div class="line"><span class="keyword">print</span> <span class="string">'Hello, World!'</span></div><div class="line">print(<span class="string">'Hello, World!'</span>)</div><div class="line"><span class="keyword">print</span> <span class="string">"text"</span>, ; <span class="keyword">print</span> <span class="string">'print more text on the same line'</span></div></pre></td></tr></table></figure>
<p><em>run result:</em><br>Python 2.7.6<br>Hello, World!<br>Hello, World!<br>text print more text on the same line</p>
<p><strong><em>Python 3</em></strong></p>
<figure class="highlight Python"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div></pre></td><td class="code"><pre><div class="line">print(<span class="string">'Python'</span>, python_version())</div><div class="line">print(<span class="string">'Hello, World!'</span>)</div><div class="line">print(<span class="string">"some text,"</span>, end=<span class="string">""</span>) </div><div class="line">print(<span class="string">' print more text on the same line'</span>)</div></pre></td></tr></table></figure>
<p><em>run result:</em><br>Python 3.4.1<br>Hello, World!<br>some text, print more text on the same line</p>
<figure class="highlight Python"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line"><span class="keyword">print</span> <span class="string">'Hello, World!'</span></div></pre></td></tr></table></figure>
<p><em>run result:</em><br> File “<ipython-input-3-139a7c5835bd>“, line 1<br> print ‘Hello, World!’<br> ^<br>SyntaxError: invalid syntax</ipython-input-3-139a7c5835bd></p>
<p><strong>Note:</strong><br> 以上通过 Python 2 使用 <code>Printing "Hello, World"</code> 是非常正常的,尽管如此,如果你有多个对象在小括号中,我们将创建一个元组,因为 <code>print</code> 在 Python 2 中是一个声明,而不是一个函数调用。</p>
<figure class="highlight Python"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div></pre></td><td class="code"><pre><div class="line"><span class="keyword">print</span> <span class="string">'Python'</span>, python_version()</div><div class="line">print(<span class="string">'a'</span>, <span class="string">'b'</span>)</div><div class="line"><span class="keyword">print</span> <span class="string">'a'</span>, <span class="string">'b'</span></div></pre></td></tr></table></figure>
<p><em>run result:</em><br>Python 2.7.7<br>(‘a’, ‘b’)<br>a b</p>
<h2 id="整除"><strong>整除</strong></h2>
<p> 如果你正在移植代码,这个变化是特别危险的。或者你在 Python 2 上执行 Python 3 的代码。因为这个整除的变化表现在它会被忽视(即它不会抛出语法异常)。<br> 因此,我还是倾向于使用一个 <code>float(3)/2</code> 或 <code>3/2.0</code> 代替在我的 Python 3 脚本保存在 Python 2 中的 <code>3/2</code> 的一些麻烦(并且反而过来也一样,我建议在你的 Python 2 脚本中使用 <code>from __future__ import division</code>)<br> <br><strong><em>Python 2</em></strong></p>
<figure class="highlight Python"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div></pre></td><td class="code"><pre><div class="line"><span class="keyword">print</span> <span class="string">'Python'</span>, python_version()</div><div class="line"><span class="keyword">print</span> <span class="string">'3 / 2 ='</span>, <span class="number">3</span> / <span class="number">2</span></div><div class="line"><span class="keyword">print</span> <span class="string">'3 // 2 ='</span>, <span class="number">3</span> // <span class="number">2</span></div><div class="line"><span class="keyword">print</span> <span class="string">'3 / 2.0 ='</span>, <span class="number">3</span> / <span class="number">2.0</span></div><div class="line"><span class="keyword">print</span> <span class="string">'3 // 2.0 ='</span>, <span class="number">3</span> // <span class="number">2.0</span></div></pre></td></tr></table></figure>
<p><em>run result:</em><br>Python 2.7.6<br>3 / 2 = 1<br>3 // 2 = 1<br>3 / 2.0 = 1.5<br>3 // 2.0 = 1.0</p>
<p><strong><em>Python 3</em></strong></p>
<figure class="highlight Python"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div></pre></td><td class="code"><pre><div class="line">print(<span class="string">'Python'</span>, python_version())</div><div class="line">print(<span class="string">'3 / 2 ='</span>, <span class="number">3</span> / <span class="number">2</span>)</div><div class="line">print(<span class="string">'3 // 2 ='</span>, <span class="number">3</span> // <span class="number">2</span>)</div><div class="line">print(<span class="string">'3 / 2.0 ='</span>, <span class="number">3</span> / <span class="number">2.0</span>)</div><div class="line">print(<span class="string">'3 // 2.0 ='</span>, <span class="number">3</span> // <span class="number">2.0</span>)</div></pre></td></tr></table></figure>
<p><em>run result:</em><br>Python 3.4.1<br>3 / 2 = 1.5<br>3 // 2 = 1<br>3 / 2.0 = 1.5<br>3 // 2.0 = 1.0</p>
<h2 id="Unicode"><strong><code>Unicode</code></strong></h2>
<p> Python 2 有 ASCII str() 类型,<code>unicode()</code> 是单独的,不是 <code>byte</code> 类型。<br> 现在, 在 Python 3,我们最终有了 <code>Unicode (utf-8)</code> 字符串,以及一个字节类:<code>byte</code> 和 <code>bytearrays</code>。</p>
<p><strong><em>Python 2</em></strong></p>
<figure class="highlight Python"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line"><span class="keyword">print</span> <span class="string">'Python'</span>, python_version()</div></pre></td></tr></table></figure>
<p><em>run result:</em><br>Python 2.7.6</p>
<figure class="highlight Python"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line"><span class="keyword">print</span> type(unicode(<span class="string">'this is like a python3 str type'</span>))</div></pre></td></tr></table></figure>
<p><em>run result:</em><br>< type ‘unicode’ ></p>
<figure class="highlight Python"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line"><span class="keyword">print</span> type(<span class="string">b'byte type does not exist'</span>)</div></pre></td></tr></table></figure>
<p><em>run result:</em><br>< type ‘str’ ></p>
<figure class="highlight Python"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line"><span class="keyword">print</span> <span class="string">'they are really'</span> + <span class="string">b' the same'</span></div></pre></td></tr></table></figure>
<p><em>run result:</em><br>they are really the same</p>
<figure class="highlight Python"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line"><span class="keyword">print</span> type(bytearray(<span class="string">b'bytearray oddly does exist though'</span>))</div></pre></td></tr></table></figure>
<p><em>run result:</em><br>< type ‘bytearray’ ></p>
<p><strong><em>Python 3</em></strong></p>
<figure class="highlight Python"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div></pre></td><td class="code"><pre><div class="line">print(<span class="string">'Python'</span>, python_version())</div><div class="line">print(<span class="string">'strings are now utf-8 \u03BCnico\u0394é!'</span>)</div></pre></td></tr></table></figure>
<p><em>run result:</em><br>Python 3.4.1<br>strings are now utf-8 μnicoΔé!</p>
<figure class="highlight Python"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div></pre></td><td class="code"><pre><div class="line">print(<span class="string">'Python'</span>, python_version(), end=<span class="string">""</span>)</div><div class="line">print(<span class="string">' has'</span>, type(<span class="string">b' bytes for storing data'</span>))</div></pre></td></tr></table></figure>
<p><em>run result:</em><br>Python 3.4.1 has < class ‘bytes’ ></p>
<figure class="highlight Python"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div></pre></td><td class="code"><pre><div class="line">print(<span class="string">'and Python'</span>, python_version(), end=<span class="string">""</span>)</div><div class="line">print(<span class="string">' also has'</span>, type(bytearray(<span class="string">b'bytearrays'</span>)))</div></pre></td></tr></table></figure>
<p><em>run result:</em><br>and Python 3.4.1 also has < class ‘bytearray’></p>
<figure class="highlight Python"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line"><span class="string">'note that we cannot add a string'</span> + <span class="string">b'bytes for data'</span></div></pre></td></tr></table></figure>
<p><em>run result:</em><br>-—————————————————————————————————————<br>TypeError Traceback (most recent call last)<br>< ipython-input-13-d3e8942ccf81> in < module>()<br>——> 1 ‘note that we cannot add a string’ + b’bytes for data’</p>
<p>TypeError: Can’t convert ‘bytes’ object to str implicitly</p>
<h2 id="xrange模块"><strong><code>xrange</code>模块</strong></h2>
<p> 在 Python 2 中 <code>xrange()</code> 创建迭代对象的用法是非常流行的。比如: <code>for</code> 循环或者是列表/集合/字典推导式。<br> 这个表现十分像生成器(比如。“惰性求值”)。但是这个 <code>xrange-iterable</code> 是无穷的,意味着你可以无限遍历。<br> 由于它的惰性求值,如果你不得仅仅不遍历它一次,<code>xrange()</code> 函数 比 <code>range()</code> 更快(比如 <code>for</code> 循环)。尽管如此,对比迭代一次,不建议你重复迭代多次,因为生成器每次都从头开始。<br> 在 Python 3 中,<code>range()</code> 是像 <code>xrange()</code> 那样实现以至于一个专门的 <code>xrange()</code> 函数都不再存在(在 Python 3 中 <code>xrange()</code> 会抛出命名异常)。</p>
<figure class="highlight Python"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div></pre></td><td class="code"><pre><div class="line"><span class="keyword">import</span> timeit</div><div class="line">n = <span class="number">10000</span></div><div class="line"><span class="function"><span class="keyword">def</span> <span class="title">test_range</span><span class="params">(n)</span>:</span></div><div class="line"> <span class="keyword">return</span> <span class="keyword">for</span> i <span class="keyword">in</span> range(n):</div><div class="line"> <span class="keyword">pass</span></div><div class="line"><span class="function"><span class="keyword">def</span> <span class="title">test_xrange</span><span class="params">(n)</span>:</span></div><div class="line"> <span class="keyword">for</span> i <span class="keyword">in</span> xrange(n):</div><div class="line"> <span class="keyword">pass</span></div></pre></td></tr></table></figure>
<p><strong><em>Python 2</em></strong></p>
<figure class="highlight Python"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div></pre></td><td class="code"><pre><div class="line"><span class="keyword">print</span> <span class="string">'Python'</span>, python_version()</div><div class="line"><span class="keyword">print</span> <span class="string">'\ntiming range()'</span></div><div class="line">%timeit test_range(n)</div><div class="line"><span class="keyword">print</span> <span class="string">'\n\ntiming xrange()'</span></div><div class="line">%timeit test_xrange(n)</div></pre></td></tr></table></figure>
<p><em>run result:</em><br>Python 2.7.6</p>
<p>timing range()<br>1000 loops, best of 3: 433 µs per loop</p>
<p>timing xrange()<br>1000 loops, best of 3: 350 µs per loop</p>
<p><strong><em>Python 3</em></strong></p>
<figure class="highlight Python"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div></pre></td><td class="code"><pre><div class="line">print(<span class="string">'Python'</span>, python_version())</div><div class="line">print(<span class="string">'\ntiming range()'</span>)</div><div class="line">%timeit test_range(n)</div></pre></td></tr></table></figure>
<p><em>run result:</em><br>Python 3.4.1</p>
<p>timing range()<br>1000 loops, best of 3: 520 µs per loop</p>
<figure class="highlight Python"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">print(xrange(<span class="number">10</span>))</div></pre></td></tr></table></figure>
<p><em>run result:</em><br>-—————————————————————————————————————<br>NameError Traceback (most recent call last)</p>
<p><ipython-input-5-5d8f9b79ea70> in <module>()<br>——> 1 print(xrange(10))</module></ipython-input-5-5d8f9b79ea70></p>
<p>NameError: name ‘xrange’ is not defined</p>
<h2 id="Python3中的range对象的__contains__方法"><strong>Python3中的<code>range</code>对象的<code>__contains__</code>方法</strong></h2>
<p> 另外一件值得一提的事情就是在 Python 3 中 <code>range</code> 有一个新的 <code>__contains__</code> 方法(感谢 Yuchen Ying 指出了这个),<code>__contains__</code> 方法可以加速 “查找” 在 Python 3.x 中显著的整数和布尔类型。</p>
<figure class="highlight Python"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div></pre></td><td class="code"><pre><div class="line">x = <span class="number">10000000</span></div><div class="line"><span class="function"><span class="keyword">def</span> <span class="title">val_in_range</span><span class="params">(x, val)</span>:</span></div><div class="line"> <span class="keyword">return</span> val <span class="keyword">in</span> range(x)</div><div class="line"><span class="function"><span class="keyword">def</span> <span class="title">val_in_xrange</span><span class="params">(x, val)</span>:</span></div><div class="line"> <span class="keyword">return</span> val <span class="keyword">in</span> xrange(x)</div><div class="line">print(<span class="string">'Python'</span>, python_version())</div><div class="line"><span class="keyword">assert</span>(val_in_range(x, x/<span class="number">2</span>) == <span class="keyword">True</span>)</div><div class="line"><span class="keyword">assert</span>(val_in_range(x, x//<span class="number">2</span>) == <span class="keyword">True</span>)</div><div class="line">%timeit val_in_range(x, x/<span class="number">2</span>)</div><div class="line">%timeit val_in_range(x, x//<span class="number">2</span>)</div></pre></td></tr></table></figure>
<p><em>run result:</em><br>Python 3.4.1<br>1 loops, best of 3: 742 ms per loop<br>1000000 loops, best of 3: 1.19 µs per loop<br> <br> 基于以上的 timeit 的结果,当它使一个整数类型,而不是浮点类型的时候,你可以看到执行查找的速度是 60000 倍快。尽管如此,因为 Python 2.x 的 <code>range</code> 或者是 <code>xrange</code> 没有一个 <code>__contains__</code> 方法,这个整数类型或者是浮点类型的查询速度不会相差太大。</p>
<figure class="highlight Python"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div></pre></td><td class="code"><pre><div class="line"><span class="keyword">print</span> <span class="string">'Python'</span>, python_version()</div><div class="line"><span class="keyword">assert</span>(val_in_xrange(x, x/<span class="number">2.0</span>) == <span class="keyword">True</span>)</div><div class="line"><span class="keyword">assert</span>(val_in_xrange(x, x/<span class="number">2</span>) == <span class="keyword">True</span>)</div><div class="line"><span class="keyword">assert</span>(val_in_range(x, x/<span class="number">2</span>) == <span class="keyword">True</span>)</div><div class="line"><span class="keyword">assert</span>(val_in_range(x, x//<span class="number">2</span>) == <span class="keyword">True</span>)</div><div class="line">%timeit val_in_xrange(x, x/<span class="number">2.0</span>)</div><div class="line">%timeit val_in_xrange(x, x/<span class="number">2</span>)</div><div class="line">%timeit val_in_range(x, x/<span class="number">2.0</span>)</div><div class="line">%timeit val_in_range(x, x/<span class="number">2</span>)</div></pre></td></tr></table></figure>
<p><em>run result:</em><br>Python 2.7.7<br>1 loops, best of 3: 285 ms per loop<br>1 loops, best of 3: 179 ms per loop<br>1 loops, best of 3: 658 ms per loop<br>1 loops, best of 3: 556 ms per loop<br> <br> 下面说下 <code>__contain__</code>方法并没有加入到 Python 2.x 中的证据:</p>
<figure class="highlight Python"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div></pre></td><td class="code"><pre><div class="line">print(<span class="string">'Python'</span>, python_version())</div><div class="line">range.__contains__</div></pre></td></tr></table></figure>
<p><em>run result:</em><br>Python 3.4.1</p>
<p>< slot wrapper ‘<strong>contains</strong>‘ of ‘range’ objects ></p>
<figure class="highlight Python"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div></pre></td><td class="code"><pre><div class="line"><span class="keyword">print</span> <span class="string">'Python'</span>, python_version()</div><div class="line">range.__contains__</div></pre></td></tr></table></figure>
<p><em>run result:</em><br>Python 2.7.7</p>
<p>-—————————————————————————————————————<br>AttributeError Traceback (most recent call last)<br>< ipython-input-7-05327350dafb> in < module>()<br> 1 print ‘Python’, python<em>version()<br>——> 2 range.`<em>_contains</em></em>`</p>
<p>AttributeError: ‘builtin<em>function<em>or_method’ object has no attribute `’__contains</em></em>‘`</p>
<figure class="highlight Python"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div></pre></td><td class="code"><pre><div class="line"><span class="keyword">print</span> <span class="string">'Python'</span>, python_version()</div><div class="line">xrange.__contains__</div></pre></td></tr></table></figure>
<p><em>run result:</em><br>Python 2.7.7</p>
<p>-—————————————————————————————————————<br>AttributeError Traceback (most recent call last)<br>< ipython-input-8-7d1a71bfee8e> in < module>()<br> 1 print ‘Python’, python<em>version()<br>——> 2 xrange.`<em>_contains</em></em>`</p>
<p>AttributeError: type object ‘xrange’ has no attribute <code>'__contains__'</code></p>
<p> <strong>注意在 Python 2 和 Python 3 中速度的不同</strong><br> 有些人指出了 Python 3 的 <code>range()</code> 和 Python 2 的 <code>xrange()</code> 之间的速度不同。因为他们是用相同的方法实现的,因此期望相同的速度。尽管如此,这事实在于 Python 3 倾向于比 Python 2 运行的慢一点。</p>
<figure class="highlight Python"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div></pre></td><td class="code"><pre><div class="line"><span class="function"><span class="keyword">def</span> <span class="title">test_while</span><span class="params">()</span>:</span></div><div class="line"> i = <span class="number">0</span></div><div class="line"> <span class="keyword">while</span> i < <span class="number">20000</span>:</div><div class="line"> i += <span class="number">1</span></div><div class="line"> <span class="keyword">return</span></div></pre></td></tr></table></figure>
<p><strong><em>Python 3</em></strong></p>
<figure class="highlight Python"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div></pre></td><td class="code"><pre><div class="line">print(<span class="string">'Python'</span>, python_version())</div><div class="line">%timeit test_while()</div></pre></td></tr></table></figure>
<p><em>run result:</em><br>Python 3.4.1<br>100 loops, best of 3: 2.68 ms per loop</p>
<p><strong><em>Python 2</em></strong></p>
<figure class="highlight Python"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div></pre></td><td class="code"><pre><div class="line"><span class="keyword">print</span> <span class="string">'Python'</span>, python_version()</div><div class="line">%timeit test_while()</div></pre></td></tr></table></figure>
<p><em>run result:</em><br>Python 2.7.6<br>1000 loops, best of 3: 1.72 ms per loop</p>
<h2 id="Raising_exceptions"><strong>Raising exceptions</strong></h2>
<p> Python 2 接受新旧两种语法标记,在 Python 3 中如果我不用小括号把异常参数括起来就会阻塞(并且反过来引发一个语法异常)。</p>
<p><strong><em>Python 2</em></strong></p>
<figure class="highlight Python"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line"><span class="keyword">print</span> <span class="string">'Python'</span>, python_version()</div></pre></td></tr></table></figure>
<p><em>run result:</em><br>Python 2.7.6</p>
<figure class="highlight Python"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line"><span class="keyword">raise</span> IOError, <span class="string">"file error"</span></div></pre></td></tr></table></figure>
<p><em>run result:</em> </p>
<p>-—————————————————————————————————————<br>IOError Traceback (most recent call last)<br>< ipython-input-8-25f049caebb0> in < module>()<br>——> 1 raise IOError, “file error”</p>
<p>IOError: file error</p>
<figure class="highlight Python"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line"><span class="keyword">raise</span> IOError(<span class="string">"file error"</span>)</div></pre></td></tr></table></figure>
<p><em>run result:</em><br>-—————————————————————————————————————<br>IOError Traceback (most recent call last)<br>< ipython-input-9-6f1c43f525b2> in < module>()<br>——> 1 raise IOError(“file error”)</p>
<p>IOError: file error</p>
<p><strong><em>Python 3</em></strong></p>
<figure class="highlight Python"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line"><span class="keyword">print</span> <span class="string">'Python'</span>, python_version()</div></pre></td></tr></table></figure>
<p><em>run result:</em><br>Python 3.4.1</p>
<figure class="highlight Python"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line"><span class="keyword">raise</span> IOError, <span class="string">"file error"</span></div></pre></td></tr></table></figure>
<p><em>run result:</em> </p>
<p> File “<ipython-input-10-25f049caebb0>“, line 1<br> raise IOError, “file error”<br> ^<br>SyntaxError: invalid syntax<br> <br> 在 Python 3 中,可以这样抛出异常:</ipython-input-10-25f049caebb0></p>
<figure class="highlight Python"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div></pre></td><td class="code"><pre><div class="line">print(<span class="string">'Python'</span>, python_version())</div><div class="line"><span class="keyword">raise</span> IOError(<span class="string">"file error"</span>)</div></pre></td></tr></table></figure>