正则剖析只是此中一种,常见的另有BeautifulSoup和lxml,支持HTML元素剖析操纵
1、正则表达式
正则表达式:regular expression
一种字符串匹配模式或规则,可以用来检索、更换那些符合特定规则的文本
step 0:确定页面类型(静态页面或动态页面)
确定要抓取的数据是否存在于页面内。通过欣赏得知要抓取的信息全部存在于源码内,因此该页面输属于静态页面
step 0.5:找出页面的 url 规律
step 1:查察元素来获取网页的大体结构
step 2:使用剖析模块来提取你想要的网页信息
step 3:实现数据抓取
- 测试字符串模式
- 更换文本
- 基于模式匹配从字符串中提取子字符串
1.1 元字符
. 匹配除换行符以外的恣意字符;若要匹配.则使用\.
\w 匹配所以的平凡字符(数字、字母、下划线)
\W 匹配非(字母或数字或下划线)
\s 匹配恣意的空缺符,如空格、换行\n、制表符\t
\S 匹配非空缺符
\d 匹配数字
\D 匹配非数字
\n 匹配一个换行符
\t匹配一个制表符
\b 匹配单词界限。单词界限是单词和空格之间的位置(放置前面则是以子表达式开头;放置背面则是以子表达式末端)
\B非单词界限,即任何其他位置
^ 匹配字符串的开头
$ 匹配字符串的末端
a|b 匹配字符a或字符b
() 正则表达式分组所用符号,匹配括号内的表达式,体现一个组
[……] 匹配字符组中的字符
[^……] 匹配除字符组中字符的全部字符
1.2 量词
* 重复零次大概更多次
+ 重复1次大概更多次
? 重复0次或1次
{n} 重复n次
{n,} 重复n次或更多次
{n,m}重复n到m次
1.3 字符组
[0123456789]在字符组中罗列全部字符,字符组里的恣意一个字符和待匹配字符类似都视为可以匹配
[0-9] 同上
[a-z]匹配全部的小写字母
[A-Z] 匹配多有的大写字母
[0-9a-zA-Z] 匹配全部数组,和巨细写字母
1.4 贪婪模式&非贪婪模式
默认贪婪模式,即尽大概多的匹配字符
如{n,m} 贪婪模式下起首以m为目标;非贪婪模式匹配n次即可
贪婪模式转为非贪婪模式,背面添加?即可
1.5 转义字符
匹配特别字符时,须要在前面添加转义字符
* + ? ^ $ [ ] ( ) { } | \
1.6 ?
但用圆括号会有一个副作用,使相关的匹配会被缓存,此时可用 ?: 放在第一个选项前来消除这种副作用。
此中 ?: 黑白捕捉元之一,另有两个非捕捉元是 ?= 和 ?!,这两个另有更多的寄义,前者为正向预查,在任何开始匹配圆括号内的正则表达式模式的位置来匹配搜索字符串,后者为负向预查,在任何开始不匹配该正则表达式模式的位置来匹配搜索字符串。
?=、?<=、?!、?<! 的使用区别
- exp1(?=exp2):查找背面是 exp2 的 exp1
- exp1(?!exp2):查找背面不是 exp2 的 exp1
- (?<=exp2)exp1:查找 exp2 背面的 exp1
- (?<!exp2)exp1:查找前面不是 exp2 的 exp1
2、re
2.1 re.match
import re"""re.match(pattern, string, flags=0)从字符串的起始位置开始匹配,若不是起始位置匹配乐成的话,返回None;匹配乐成则返回一个匹配的对象- pattern :匹配的正则表达式- string:要匹配的字符串- flags : 标志位,用于控制正则表达式的匹配方式,如是否区分巨细写,多行匹配等待"""# 训练:正则匹配不是以4和7末端的手机号phones = ["13166781234", "15876546657", "15912345678", "1321234567997"]for phone in phones: res = re.match(r"1\d{9}[0-3,5-6,8-9]$", phone) # $体现以什么末端 print(res) if res: print("正则匹配不是以4和7末端的手机号:", res.group()) else: print("%s 不是想要的手机号" % phone)# None# 13166781234 不是想要的手机号# None# 15876546657 不是想要的手机号# <re.Match object; span=(0, 11), match='15912345678'># 正则匹配不是以4和7末端的手机号: 15912345678# None# 1321234567997 不是想要的手机号2.1.1 groups & group
"""groups() 或group(num=0) 获取匹配的值 - group() 匹配乐成的整个字符串,可以一次输入多个组号,在这种情况下将返回一个包罗哪些组对应值的元组 group(n) 第n个匹配乐成的子串- groups() 返回一个包罗全部小组字符串(匹配乐成)的元组,相称于(group(1),group(2)……)span() 获取匹配对象中的span,即匹配乐成的整个字串的下标起始值 span(1):有分组时,第n个匹配乐成的子串的索引"""s = '1234567890QWER'match_obj = re.match(r'\d{2}', s) # \d匹配数字,{n}体现数目print(match_obj) # <re.Match object; span=(0, 2), match='12'>if match_obj: print("match_obj.span() = ", match_obj.span()) # match_obj.span() = (0, 2) print("match_obj.groups() = ", match_obj.groups()) # match_obj.groups() = () print("match_obj.group() = ", match_obj.group()) # match_obj.group() = 12 # print("match_obj.group(1) = ", match_obj.group(1)) # IndexError: no such group 不存在的分组else: print("No Match!")2.2 re.search
"""re.search(pattern, string, flags)Scan through string looking for a match to the pattern, returning a Match object, or None if no match was found.扫描整个字符串,并返回第一个乐成的匹配的Match 对象;无满足要求的返回None"""s = "Cats are smarter than dogs"search_obj = re.search(r'(.*?) are (.*?) (.*?) ', s)# ()分组,| 或,多个匹配表达式其一匹配即可;.单个字符;*体现数目,0以及以上;?关闭贪婪模式print("search_obj = ", search_obj)# search_obj = <re.Match object; span=(0, 22), match='Cats are smarter than '>if search_obj: print("search_obj.groups() =", search_obj.groups()) # search_obj.groups() = ('Cats', 'smarter', 'than') print("search_obj.group() =", search_obj.group()) # search_obj.group() = Cats are smarter than print("search_obj.group(1) =", search_obj.group(1)) # search_obj.group(1) = Cats print("search_obj.span() =", search_obj.span()) # search_obj.span() = (0, 22)else: print("No search!")2.3 re.sub
"""re.sub(pattern, repl, string, count=0, flags=0)更换字符串中的匹配项,返回新的string- pattern:正则表达式对象- repl :更换的字符,也可以是函数- string: 要被查找的原始字符串- count:模式匹配后更换的最大次数,默认0体现更换全部的匹配- flags:代表功能标志位,扩展正则表达式的匹配"""phone = "158-2765-1234 # 手机号码"# 移除非数字内容num = re.sub(r'\D', "", phone) # \D 匹配非数字;\d匹配数字print("更换后的phone:", num)print(phone) # 158-2765-1234 # 手机号码 【即本身不改变】# repl 还可以是一个函数# If it is a callable, it's passed the Match object and must return a replacement string to be used. def double(matched): v = int(matched.group()) print(v) return str(v*2)# print(re.sub("\D+?", lambda x: x * 2, num))# TypeError: unsupported operand type(s) for *: 're.Match' and 'int'print(re.sub("\D+?", lambda x: x.group() * 2, num)) # 158--2567--9876print(re.sub(r"(\d+)", double, phone)) # double是自界说函数print("repl是函数:", num)2.4 re.compile
regex = re.compile(pattern="\w+", flags=0)# Compile a regular expression pattern, returning a Pattern object(正则表达式对象).- pattern:正则表达式对象- flags:代表功能标志位,扩展正则表达式的匹配print(regex) # re.compile('\\d+')2.5 regex.findall
# regex.findall(string,pos,endpos)# findall(self, string: AnyStr, pos: int = ..., endpos: int = ...) -> list[Any]# string:目标字符串# pos/endpos:截取目标字符串的开始匹配位置/竣事匹配位置print(regex.findall(s)) # ['h1', 'Python', 're模块用法详解', 'h1']"""regex = re.compile(pattern, flags)regex.findall(string)两者团结等同于re.findall(pattern,string)"""2.6 re.findall
def findall(pattern, string, flags=0): Return a list of all non-overlapping matches in the string. # 返回匹配到的内容列表 If one or more capturing groups are present in the pattern, return # 如果有子组,则只能获取到子组对应内容 a list of groups; this will be a list of tuples if the pattern has more than one group. Empty matches are included in the result. - pattern:正则表达式 - string:目标字符串 - flags:代表功能标志位,扩展正则表达式的匹配
- re.finditer
re.finditer(pattern, string, flags=0)
和 findall 类似,在字符串中找到正则表达式所匹配的全部子串,并把它们作为一个迭代器返回。
2.7 re.split
split(pattern, string, maxsplit=0, flags=0)# 切割即删除目标字符串中匹配处,返回切割后的子字符串列表# 实现效果与re.findall()相反 - pattern:正则表达式 - string:目标字符串 - maxsplit:不是0时,则最多分割maxsplit分,将字符串的别的部门作为列表的末了一个元素返回。 - flags:代表功能标志位,扩展正则表达式的匹配print(re.findall("\w+", s)) # ['h1', 'Python', 're模块用法详解', 'h1']res = re.split("\w+",s) # ['<', '>', ' ', '</', '>']print(res)res = re.split("\w+",s, 3) # ['<', '>', ' ', '</h1>']2.8 flags 功能标志位
"""flags 正则表达式修饰符re.A 原元符只能匹配ASCII字符(让 \w, \W, \b, \B, \d, \D, \s 和 \S 只匹配ASCII,而不是Unicode)re.I 使得匹配对巨细写不敏感(即IGNORECASE)re.L 体现特别字符集\w,\W,\b,\B,\s,\S依赖当前情况(即LOCALE)re.M 多行模式re.S 即为 . 包罗换行符在内的恣意字符(. 默认匹配模式下不包罗换行符)re.U 体现特别字符集 \w,\W,\b,\B,\s,\S依赖于Unicode字符属性库re.X 为了增长可读性,忽略空格和# 背面的解释多个标志,使用 |如 re.I | re.M 被设置成I和M标志"""
html = """<divre--- 正则表达式操纵
2、Python3 正则表达式
3、正则表达式根本语法
4、re模块
5、正则表达式 - 教程</p> |