Crawler Learning (03): Data Analysis_re

1. Introduction to re module

1.1 re regularization

Regular Expression, regular expression, a grammatical rule that uses expressions to match strings. What
we grab on the webpage 页面源代码is essentially one 超长的字符串. If you want to extract content from it, it 正则is perfect to use.

Regular advantages:
速度快效率高准确性高
Regular syntax:
Use metacharacters for permutations and combinations 匹配字符串 .

Common Metacharacters

 .     √匹配除换行符以外的任意字符,  未来在python的re模块中是一个坑. 
 \w    √匹配字母或数字或下划线.
 \s    匹配任意的空白符
 \d    √匹配数字
 \n    匹配一个换行符
 \t    匹配一个制表符
 
 ^     匹配字符串的开始
 $     匹配字符串的结尾
 
 \W    匹配非字母或数字或下划线
 \D    匹配非数字
 \S    匹配非空白符
 a|b   匹配字符a或字符b
 ()    √匹配括号内的表达式,也表示一个组
 [...]    √匹配字符组中的字符
 [^...]    匹配除了字符组中字符的所有字符

Quantifier: Controls the number of occurrences of the preceding metacharacter

 *    重复零次或更多次
 +    重复一次或更多次
 ?    重复零次或一次
 {n}    重复n次 
 {n,}    重复n次或更多次 
 {n,m}    重复n到m次

Greedy matching and lazy matching (emphasis)

 .*     贪婪匹配,  尽可能多的去匹配结果
 .*?    惰性匹配,  尽可能少的去匹配结果 -> 回溯

General flags (modifier

value illustrate
re.I is match case insensitive
re.M Multi-line matching, affecting ^ and $
re.S make . match all characters including newlines

1.2 re module

In the re module, we only need to remember the following functions for us to use.

1.2.1 findall() function (return list)

Scans the entire string string, and returns a string list of all matching pattern pattern results ( findall 查找所有. 返回list)
parameter

parameter illustrate
pattern The regular expression to match (a pattern of strings)
string string to match
flags Identification bit, used to control the matching mode of the regular expression
import re
lst = re.findall("m", "mai le fo len, mai ni mei!") 
print(lst)    # ['m', 'm', 'm'] 
lst = re.findall(r"\d+", "5点之前. 你要给我5000万")
print(lst)   # ['5', '5000']

1.2.2 search() function

searchWill match. But if it matches 第一个结果, it will return this result. If it does not match, searchit will returnNone

import re
ret = re.search(r'\d', '5点之前. 你要给我5000万').group()
print(ret)  # 5

1.2.3 match() function

matchonly from the string开头进行匹配

ret = re.match('a', 'abc').group()  
print(ret)     # a

1.2.4 finditer() function

finditerand findallabout the same. Except this returns 迭代器(emphasis added)

it = re.finditer("m", "mai le fo len, mai ni mei!")
for el in it:
    print(el.group()) # 依然需要分组

运行结果
insert image description here

1.2.5 compile() function

compile()A long regular expression can be carried out 预加载. Convenient后面的使用

obj = re.compile(r'\d{3}')  # 将正则表达式编译成为一个 正则表达式对象, 规则要匹配的是3个数字
ret = obj.search('abc123eeee') # 正则表达式对象调用search, 参数为待匹配的字符串
print(ret.group())  # 结果: 123

1.2.6 Regular content is extracted separately

To obtain the specific content in the regex separately, you can give 分组起名字( ?P<name>xxx)

s = """
<div class='西游记'><span id='10010'>中国联通</span></div>
"""
obj = re.compile(r"<span id='(?P<id>\d+)'>(?P<name>\w+)</span>", re.S)

result = obj.search(s)
print(result.group())  # 结果: <span id='10010'>中国联通</span>
print(result.group("id"))  # 结果: 10010 # 获取id组的内容
print(result.group("name"))  # 结果: 中国联通 # 获取name组的内容

Here we can see that we can use 使用分组. to further carry out the content matched by the regular expression 筛选.

1.2.7 String Replacement

Regular expressions are used by themselves 提取字符串中的内容. Can also be used as字符串的替换

import re
r = re.split(r"\d+", "我今年19岁了, 你知道么, 19岁就已经很大了. 周杰伦20岁就得奖了")
print(r)  # ['我今年', '岁了, 你知道么, ', '岁就已经很大了. 周杰伦', '岁就得奖了']
# 替换
r = re.sub(r"\d+", "18", "我今年19岁了, 你知道么, 19岁就已经很大了. 周杰伦20岁就得奖了")
print(r)  # 我今年18岁了, 你知道么, 18岁就已经很大了. 周杰伦18岁就得奖了

​ Oh, regular. These things are enough.

Two, re practical operation

2.1 The distinction between greedy and non-greedy

We can find such a rule: .*?it means as few matches as possible, .*and it means as many matches as possible. For the time being, remember this rule first. It will be used later when writing crawlers

str: 玩儿吃鸡游戏, 晚上一起上游戏, 干嘛呢? 打游戏啊
 reg: 玩儿.*?游戏
 
 此时匹配的是: 玩儿吃鸡游戏
 
 reg: 玩儿.*游戏   
 此时匹配的是: 玩儿吃鸡游戏, 晚上一起上游戏, 干嘛呢? 打游戏    
     
                 
 str: <div>胡辣汤</div>
 reg: <.*>
 结果: <div>胡辣汤</div>
 
 
 str: <div>胡辣汤</div>
 reg: <.*?>
 结果: 
     <div>
     </div>
 
 str: <div class="abc"><div>胡辣汤</div><div>饭团</div></div>
 reg: <div>.*?</div>
 结果:
     <div>胡辣汤</div>
	 <div>饭团</div>

2.2 Exercises with metacharacters

[] 原子表
[a]  # 匹配a
[ab]  # 匹配a或者b
[abc]  # 匹配a或者b或者c
[123]  # 匹配1或者2或者3
[0-9]  # 匹配任意一位数字
[a-z]  # 匹配任意一位小写字母
[A-Z]  # 匹配任意一位大写字母
[a-zA-Z]  # 匹配任意大小写字母

[][]
[abc][0-9]  匹配a或者b或者c和任意一个数字->a1,b2,c3...

匹配手机号码
1[3-9][0-9]{
    
    9}  # {9} 代表前面的[0-9]9位 共11位

 ^ 限制开头 $ 限制结尾 一般用于组合
^1[3-9][0-9]{
    
    9}$  # 完全匹配 匹配的字符串中,必须完全符合才算匹配成功
13134534681  # 符合
131345346812 # 不符合 因为多了一位

{
    
    } 代表前面正则匹配的n词
[a-z]{
    
    2}  # 匹配两位小写字母
[a-z][a-z] # 等同于上方

{
    
    m,n} m-n之间的
[a-z]{
    
    2,5} # 匹配2-5个小写字母

 {
    
    m,} #至少匹配m个
[a-z]{
    
    2,} # 至少匹配2个小写字母

?可有可无
-?[1-9] # 匹配正负1-9

 . 匹配换行符以外的任意字符(不单独使用)
a   b   c  # 都能匹配

* 代表前面的0次或多次(不单独使用)

.*?组合 非贪婪匹配 (重要!!!) #匹配换行符以外的任意字符任意次

.*组合 贪婪匹配 #匹配换行符以外的任意字符任意次

 + 匹配一次到多次{
    
    1,}

.+? 非贪婪匹配 #匹配换行符以外的任意字符至少1次

| 代表或
[a-z]|[0-9] # 匹配字母或数字、

() #1. 作为一个单元  2. 作为子存储

2.3 re modifier exercises

import re
#  re.I 是匹配队大小写不敏感
#  re.M 多行匹配,影响到^和$
#  re.S 使.匹配包括换行符在内的所有字符
mystr = """
<a href="http://www.baidu.com">百度</a>
<A href="http://www.baidu.com">百度</A>
<a href='http://www.sogou.com'>搜狗</a>
<a href="http://www.tengxun.com">腾
讯</a>
"""

# 首先匹配所有的正常a链接->小写
# print(re.findall("<a href=\"http://www.baidu.com\">百度</a>")) #内部用转义
print(re.findall('<a href="(.*?)">(.*?)</a>', mystr))  # 外部用单引号
# 可以发现,只能匹配出一个结果来
# >>>[('http://www.baidu.com', '百度')]

# re.I 不区分大小写
print(re.findall('<a href="(.*?)">(.*?)</a>', mystr, re.I))
# 可以发现,匹配出两个结果来了
# >>>[('http://www.baidu.com', '百度'), ('http://www.baidu.com', '百度')]

#  匹配大小写 多行匹配 可以匹配换行符 中间用|隔开
print(re.findall('<a href="(.*?)">(.*?)</a>', mystr, re.I | re.M | re.S))
# >>> [('http://www.baidu.com', '百度'), ('http://www.baidu.com', '百度'), ('http://www.tengxun.com', '腾\n讯')]
# 可以发现匹配出来了三个结果,但唯独少一个搜狗,因为搜狗是用单引号扩起来的

# 在上面的案例基础上匹配单双引号 [] 表示或,表示双引号或者单引号
print(re.findall('<a href=[\'"](.*?)[\'"]>(.*?)</a>', mystr, re.I | re.M | re.S))
# >>> 匹配出来了全部结果
print('*'*20)
myStr = """asadasdd1\nbsadasdd2\ncsadasdd3"""
print(re.findall('^[a-z]',myStr))  # 匹配以字母开头
# >>> ['a']
print(re.findall('\A[a-z]',myStr))  # 匹配以字母开头 (整段)
# >>> ['a']
print(re.findall('\d$',myStr))  # 匹配以数字结尾
# >>> ['3']
print(re.findall('\d\Z',myStr))  # 匹配以数字结尾 (整段)
# >>> ['3']

# re.M
print(re.findall('^[a-z]',myStr, flags=re.M))
# >>> ['a', 'b', 'c']
print(re.findall('\A[a-z]',myStr, flags=re.M))
# >>> ['a']
print(re.findall('\d$',myStr, flags=re.M))
# >>> ['1', '2', '3']
print(re.findall('\d\Z',myStr, flags=re.M))
# >>> ['3']

2.4 match_search_findall exercise

import re

# r"" 专业写正则,没有转义的烦恼

# search re.search(正则,字符串) 会进行匹配. 但是如果匹配到了第一个结果. 就会返回这个结果. 如果匹配不上search返回的则是None
print('search')
print()
print(re.search(r'a', '123456'))  # None
# group() 若匹配成功则返回匹配数值
print(re.search(r'[a-z]','123c423').group())  # c
print(re.search(r'[a-z][a-z]', '12321a21'))  # None
print(re.search(r'1[3-9][0-9]{9}','1345643256543').group())  # 13456432565
print(re.search(r'1[3-9][0-9]{9}','b1345643256543b').group())  # 13456432565
print(re.search(r'^1[3-9][0-9]{9}','x1345643256543'))  # None

print('-'*30)
print('match')
print()
# match 只匹配一次,必须从第一位开始,类似于search('^')
print(re.match(r'a','a213131').group())  # a
print(re.match(r'a','213131'))  # None
print(re.match(r'[a-z]','123x456'))  # None
print(re.match(r'1[1-3][0-9]{9}','b1345643256543b'))  # None
print(re.match(r'1[1-3][0-9]{9}','1345643256543b').group())  # 1345643256543

print('-'*30)
print('findall')
# 查找所有 结果返回列表
print(re.findall(r"\d+","我有1000万,不给你话,给你1块钱拿去"))  # ['1000', '1']

3. About re summary

  1. .*?-> lazy matching / *-> greedy matching
  2. searce()Function: scan the entire string string, and return 第一个the successful match of the pattern pattern, and return if the match failsNone
  3. findall()函数Scans the entire string string and returns a string list of all matching pattern results
  4. match()函数If the match is successful, the matched object will be returned
    ; if the match fails, the object will be returnedNone
  5. reThe best 常用place -> Get one of js in html 部分代码(in string)

Guess you like

Origin blog.csdn.net/m0_48936146/article/details/127308765