使用python爬取網站數據的時候,總會遇到各類各樣的反爬蟲策略,有很大一部分都和JavaScript(如下簡稱爲JS)python
有關。在破解這些JS代碼的過程當中,常常會遇到模擬JS正則表達式的狀況,所以,今天總結一下如何使用python來模擬JS正則表達式
中的正則。數組
關於JS中正則表達式的詳細教程,能夠看一下W3School的教程 JavaScript RegExp 對象。函數
簡單來講,不管是那種語言的正則表達式,其基本的元字符含義都是同樣的,區別之處只在於語法、函數、語言特點、網站
內部實現方式等,下面咱們就來看一下 JS 和 python 的正則表達式有什麼不同吧。加密
1、正則表達式的書寫語法spa
python代碼示例 code
#coding:utf8
import re # 目標字符串
_string = 'Today is 2016-11-17'
# 定義正則表達式規則
regex_str = '\d+'
# 編譯爲Pattern對像
pattern = re.compile(regex_str) # 開始匹配
print pattern.search(_string).group() # 輸出 #>>> 2016
JS代碼示例regexp
// 目標字符串
var _string='Today is 2016-11-17'; // 定義正則表達式規則
var regex_str=/\d+/; // 編譯爲Pattern對像
pattern = new RegExp(regex_str); // 開始匹配
var result = pattern.exec(_string); document.write(result); // 2016
從上面的例子來看,拋開兩種語言自己的語法,單看正則表達式的話,有如下幾點不一樣:對象
1.python中的正則表達式本質上是一個字符串,JS中則必須以斜槓符號 / 包圍,而且不能書寫爲 '/\d+/', 只
能寫成 /\d+/ 。
2.若是你看了W3School中JS教程的話,就會發現,JS的 RegExp 對象僅支持 compile、exec、test 這三個
方法,而search、match、replace、split 這些更經常使用的方法放到了 String 類型中。但在python中的Pattern
對象卻能夠支持全部經常使用正則表達式操做。
2、匹配模式或者說修飾符
python代碼示例
#coding:utf8
import re # 目標字符串
_string = 'Today is 2016-11-17'
# 定義正則表達式規則
regex_str = '\d+'
# 編譯爲Pattern對像 # 指定使用各類模式
pattern = re.compile(regex_str, re.I | re.L | re.M | re.S | re.X | re.U) # 開始匹配
print pattern.search(_string).group() # 輸出 #>>> 2016
JS 代碼示例
// 目標字符串
var _string='Today is 2016-11-17'; // 定義正則表達式規則
var regex_str=/\d+/; // 編譯爲Pattern對像
pattern = new RegExp(regex_str, 'g') // pattern = new RegExp(regex_str, 'i') // pattern = new RegExp(regex_str, 'm')
// 開始匹配
var result = pattern.exec(_string) document.write(result) // 2016
在匹配模式上,python支持的模式比較多,而JS僅支持 g 全局搜索、i 忽略大小寫、m 多行匹配這三種模式,而且
這三種模式也不是任什麼時候候均可以使用的,具體請往下面看。
3、JS 的 String 類型支持的正則表達式操做 replace
python的字符串處理能力很強,而JS中關於字符串的各類操做也是比較複雜、使人頭疼,通常狀況下反爬蟲的JS代碼
都是經過一系列的字符串操做達到混淆視聽的目的,或者將字符串加密解密,而其中最特殊的就是replace方法。python
中的字符串類型也有replace方法,這個是基於字符串自己的,和正則表達式沒有任何關係,想要實現基於正則表達式的替
換須要使用re模塊中的sub函數。而JS中的replace函數則直接支持兩種替換方式,其根據傳入的參數類型來決定。
python示例代碼
#coding:utf8
import re # 目標字符串
_string = 'Today is 2016-11-17 \d+ \d+'
# 定義正則表達式規則
regex_str = '\d+'
# 編譯爲Pattern對像
pattern = re.compile(regex_str) # 開始匹配
print pattern.sub('2017', _string) # 輸出 #>>> Today is 2017-2017-2017 \d+ \d+
# 使用字符串自己的方法
print _string.replace(regex_str, '2017') # 輸出 #>>> Today is 2016-11-17 2017 2017
JS 示例代碼
// 目標字符串
var _string='Today is 2016-11-17 \d+ \d+'; // 定義正則表達式規則
var regex_str=/\d+/;
var result = _string.replace(regex_str, '2017') document.write(result) // Today is 2017-11-17 \d+ \d+
// 不使用正則表達式
var result = _string.replace('\d+', '2017') document.write(result) // Today is 2016-11-17 2017 \d+
// 定義正則表達式規則 增長全局匹配模式 g
var regex_str=/\d+/g;
var result = _string.replace(regex_str, '2017') document.write(result) // Today is 2017-2017-2017 \d+ \d+
在這個例子裏面能夠發現,python 的每一個模塊分工很明確,而JS則混用比較嚴重,但這樣也增長了易用性。而後總結
一下幾個區別:
1.JS 以 / 來標識正則表達式,以引號來標示字符串,根據參數類型決定進行何種替換。
2.JS的replace不管使用正則表達式仍是字符串自己,默認狀況下僅替換第一個匹配項,但正則表達式能夠經過使用增
加修飾符 g 實現全局替換,而字符串卻不能夠。
4、JS 的 String 類型支持的正則表達式操做 match
python中的re模塊有一個match函數,從字符串的開始處匹配正則表達式,但JS中的match卻不同,更相似於
python的re模塊的findall函數。
python示例代碼
#coding:utf8
import re # 目標字符串
_string = 'Today is 2016-11-17 \d+ \d+'
# 定義正則表達式規則
regex_str = '\d+'
# 編譯爲Pattern對像
pattern = re.compile(regex_str) # match 匹配
print pattern.match(_string) # 輸出 #>>> None
# findall 匹配
print pattern.findall(_string) # 輸出 #>>> ['2016', '11', '17']
JS示例代碼
// 目標字符串
var _string='Today is 2016-11-17 \d+ \d+'; // 定義正則表達式規則
var regex_str=/\d+/;
var result = _string.match(regex_str) document.write(result) // 2016
// 定義正則表達式規則 增長全局搜索修飾符
var regex_str=/\d+/g;
var result = _string.match(regex_str) document.write(result) // 2016,11,17
// 匹配字符串
var result = _string.match('2016') document.write(result) // 2016
其實這個方法徹底可使用python的findall來代替,只須要注意:
1. JS中match接受的參數是字符串仍是正則表達式,字符串的話最好使用python的字符串操做方法,正則表達式的話
轉換一下寫法就能夠了。
2. JS中是否使用了修飾符 g, 使用了的話和使用python的findall獲得的結果是同樣的,不然就只是findall返回
值中的前一個元素。
4、JS 的 String 類型支持的正則表達式操做 search
search方法用於檢索字符串中指定的子字符串,或檢索與正則表達式相匹配的子字符串。它的返回值是尋找到的子字符
串的起始位置的索引,這個方法在python裏面對應了字符串的find方法和正則表達式re模塊中的search方法。
python示例代碼
#coding:utf8
import re # 目標字符串
_string = 'Today is 2016-11-17 \d+ \d+'
# 定義正則表達式規則
regex_str = '\d+'
# 編譯爲Pattern對像
pattern = re.compile(regex_str) # search 方法尋找第一個數字出現的位置
print pattern.search(_string).start() # 輸出 #>>> 9
# find
print _string.find('2016') # 輸出 #>>> 9
JS代碼示例
// 目標字符串
var _string='Today is 2016-11-17 \d+ \d+'; // 定義正則表達式規則
var regex_str=/\d+/;
var result = _string.search(regex_str) document.write(result) // 9
// 匹配字符串
var result = _string.search('2016') document.write(result) // 9
這個裏面須要注意的可能就只是參數的類型還有返回值了,要注意JS只是返回了一個索引,而不是一個字符串
5、JS 的 String 類型支持的正則表達式操做 split
split方法用於把一個字符串分割成字符串數組,能夠指定返回的數組長度,JS中可接受正則表達式和字符串兩種參數,
而python與之對應的是字符串的split方法與正則表達式re模塊中的split方法
python代碼示例
#coding:utf8 import re # 目標字符串 _string = 'Today is 2016-11-17 \d+ \d+' # 定義正則表達式規則 regex_str = '\d+' # 編譯爲Pattern對像 pattern = re.compile(regex_str) # split 根據正則切分 print pattern.split(_string, 2) # 輸出 #>>> ['Today is ', '-', '-', ' \\d+ \\d+'] # 徹底模擬JS print pattern.split(_string, 2)[:2] # 輸出 #>>> ['Today is ', '-'] # split 根據字符串切分 print _string.split('2016', 1) # 輸出 #>>> ['Today is ', '-11-17 \\d+ \\d+'] # 徹底模擬JS print _string.split('2016', 1)[:1] # 輸出 #>>> ['Today is ']
JS 代碼示例
// 目標字符串 var _string='Today is 2016-11-17 \d+ \d+'; // 定義正則表達式規則 var regex_str=/\d+/; var result = _string.split(regex_str, 2) document.write(result) // Today is ,- // 匹配字符串 var result = _string.split('2016', 1) document.write(result) // Today is
這個在轉換的時候須要注意的就是JS返回的數組的長度了,默認狀況下徹底返回和徹底分割,python和JS的結果是同樣
的。
關於python和JS的正則表達式轉換,就介紹到這裏了。其實真正模擬JS代碼的時候正則並非最麻煩的,最麻煩的是如下幾個:
1.各類位移操做
2.JS特有的數字和字符類型相加規則
3.[]、~~、!、{}等這些數據類型和操做符如何轉化爲數字
還有啥暫時想不起來了,這些東西會在後續的文章中逐一介紹,歡迎交流!!!