xpath(XML Path Language)是一门在XML和HTML文档中查找信息的语言,可用来在XML和HTML文档中对元素和属性进行遍历。css
XPath 使用路径表达式来选取 XML 文档中的节点或者节点集。这些路径表达式和咱们在常规的电脑文件系统中看到的表达式很是类似。html
表达式 | 描述 | 示例 | 结果 |
---|---|---|---|
nodename | 选取此节点的全部子节点 | bookstore | 选取bookstore下全部的子节点 |
/ | 若是是在最前面,表明从根节点选取。不然选择某节点下的某个节点 | /bookstore | 选取根元素下全部的bookstore节点 |
// | 从全局节点中选择节点,随便在哪一个位置 | //book | 从全局节点中找到全部的book节点 |
@ | 选取某个节点的属性 | //book[@price] | 选择全部拥有price属性的book节点 |
. | 当前节点 | ./a | 选取当前节点下的a标签 |
谓语用来查找某个特定的节点或者包含某个指定的值的节点,被嵌在方括号中。
在下面的表格中,咱们列出了带有谓语的一些路径表达式,以及表达式的结果:前端
路径表达式 | 描述 |
---|---|
/bookstore/book[1] | 选取bookstore下的第一个子元素 |
/bookstore/book[last()] | 选取bookstore下的倒数第二个book元素。 |
bookstore/book[position()<3] | 选取bookstore下前面两个子元素。 |
//book[@price] | 选取拥有price属性的book元素 |
//book[@price=10] | 选取全部属性price等于10的book元素 |
*表示通配符。vue
通配符 | 描述 | 示例 | 结果 |
---|---|---|---|
* | 匹配任意节点 | /bookstore/* | 选取bookstore下的全部子元素。 |
@* | 匹配节点中的任何属性 | //book[@*] | 选取全部带有属性的book元素。 |
经过在路径表达式中使用“|”运算符,能够选取若干个路径。
示例以下:html5
//bookstore/book | //book/title # 选取全部book元素以及book元素下全部的title元素
运算符 | 描述 | 实例 | 返回值 |
| | 计算两个节点集 | //book | //cd | 返回全部拥有 book 和 cd 元素的节点数 |
+ | 加法 | 6 + 4 | 10 |
- | 减法 | 6 - 4 | 2 |
* | 乘法 | 6 * 4 | 24 |
div | 除法 | 8 div 4 | 2 |
= | 等于 | price=9.80 | 若是 price 是9.80 , 则返回 true 。若是 price 是9.90 , 则返回的是 false. |
!= | 不等于 | price!=9.80 | 若是 price 是9.90 , 则返回 true 。若是 price 是9.80 , 则返回的是 false. |
< | 小于 | price < 9.80 | 若是 price 是9.00 , 则返回 true 。若是 price 是9.90 , 则返回的是 false. |
<= | 小于等于 | price <= 9.80 | 若是 price 是9.80 , 则返回 true 。若是 price 是9.90 , 则返回的是 false. |
> | 大于 | price > 9.80 | 若是 price 是9.90 , 则返回 true 。若是 price 是9.70 , 则返回的是 false. |
or | 或 | price=9.80 or price=9.70 | 若是 price 是9.80 , 则返回 true 。若是 price 是9.50 , 则返回的是 false. |
and | 与 | price>9.80 and price<9.99 | 若是 price 是9.90 , 则返回 true 。若是 price 是8.50 , 则返回的是 false. |
mod | 计算除法的余数 | 5 mod 2 | 1 |
lxml 是 一个HTML/XML的解析器,主要的功能是如何解析和提取 HTML/XML 数据。node
lxml和正则同样,也是用 C 实现的,是一款高性能的 Python HTML/XML 解析器,咱们能够利用以前学习的XPath语法,来快速的定位特定元素以及节点信息。python
lxml python 官方文档:http://lxml.de/index.htmlweb
须要安装C语言库,可以使用 pip 安装:pip install lxml正则表达式
咱们能够利用他来解析HTML代码,而且在解析HTML代码的时候,若是HTML代码不规范,他会自动的进行补全。示例代码以下:chrome
# 使用 lxml 的 etree 库 from lxml import etree text = ''' <div> <ul> <li class="item-0"><a href="link1.html">first item</a></li> <li class="item-1"><a href="link2.html">second item</a></li> <li class="item-inactive"><a href="link3.html">third item</a></li> <li class="item-1"><a href="link4.html">fourth item</a></li> <li class="item-0"><a href="link5.html">fifth item</a> # 注意,此处缺乏一个 </li> 闭合标签 </ul> </div> ''' #利用etree.HTML,将字符串解析为HTML文档 html = etree.HTML(text) # 按字符串序列化HTML文档 result = etree.tostring(html) print(result)
输入结果以下:
<html><body> <div> <ul> <li class="item-0"><a href="link1.html">first item</a></li> <li class="item-1"><a href="link2.html">second item</a></li> <li class="item-inactive"><a href="link3.html">third item</a></li> <li class="item-1"><a href="link4.html">fourth item</a></li> <li class="item-0"><a href="link5.html">fifth item</a></li> </ul> </div> </body></html>
能够看到。lxml会自动修改HTML代码。例子中不只补全了li标签,还添加了body,html标签。
除了直接使用字符串进行解析,lxml还支持从文件中读取内容。咱们新建一个hello.html文件:
<!-- hello.html --> <div> <ul> <li class="item-0"><a href="link1.html">first item</a></li> <li class="item-1"><a href="link2.html">second item</a></li> <li class="item-inactive"><a href="link3.html"><span class="bold">third item</span></a></li> <li class="item-1"><a href="link4.html">fourth item</a></li> <li class="item-0"><a href="link5.html">fifth item</a></li> </ul> </div>
而后利用etree.parse()
方法来读取文件。示例代码以下:
from lxml import etree # 读取外部文件 hello.html html = etree.parse('hello.html') result = etree.tostring(html, pretty_print=True) print(result)
输入结果和以前是相同的。
获取全部li标签:
from lxml import etree html = etree.parse('hello.html') print type(html) # 显示etree.parse() 返回类型 result = html.xpath('//li') print(result) # 打印<li>标签的元素集合
获取全部li元素下的全部class属性的值:
from lxml import etree html = etree.parse('hello.html') result = html.xpath('//li/@class') print(result)
获取li标签下href为www.baidu.com
的a标签:
from lxml import etree html = etree.parse('hello.html') result = html.xpath('//li/a[@href="www.baidu.com"]') print(result)
获取li标签下全部span标签:
from lxml import etree html = etree.parse('hello.html') #result = html.xpath('//li/span') #注意这么写是不对的: #由于 / 是用来获取子元素的,而 <span> 并非 <li> 的子元素,因此,要用双斜杠 result = html.xpath('//li//span') print(result)
获取li标签下的a标签里的全部class:
from lxml import etree html = etree.parse('hello.html') result = html.xpath('//li/a//@class') print(result)
获取最后一个li的a的href属性对应的值:
from lxml import etree html = etree.parse('hello.html') result = html.xpath('//li[last()]/a/@href') # 谓语 [last()] 能够找到最后一个元素 print(result)
获取倒数第二个li元素的内容:
from lxml import etree html = etree.parse('hello.html') result = html.xpath('//li[last()-1]/a') # text 方法能够获取元素内容 print(result[0].text)
获取倒数第二个li元素的内容的第二种方式:
from lxml import etree html = etree.parse('hello.html') result = html.xpath('//li[last()-1]/a/text()') print(result)
示例代码以下:
import requests from lxml import etree BASE_DOMAIN = 'http://www.dytt8.net' HEADERS = { 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/61.0.3163.100 Safari/537.36', 'Referer': 'http://www.dytt8.net/html/gndy/dyzz/list_23_2.html' } def spider(): url = 'http://www.dytt8.net/html/gndy/dyzz/list_23_1.html' resp = requests.get(url,headers=HEADERS) # resp.content:通过编码后的字符串 # resp.text:没有通过编码,也就是unicode字符串 # text:至关因而网页中的源代码了 text = resp.content.decode('gbk') # tree:通过lxml解析后的一个对象,之后使用这个对象的xpath方法,就能够 # 提取一些想要的数据了 tree = etree.HTML(text) # xpath/beautifulsou4 all_a = tree.xpath("//div[@class='co_content8']//a") for a in all_a: title = a.xpath("text()")[0] href = a.xpath("@href")[0] if href.startswith('/'): detail_url = BASE_DOMAIN + href crawl_detail(detail_url) break def crawl_detail(url): resp = requests.get(url,headers=HEADERS) text = resp.content.decode('gbk') tree = etree.HTML(text) create_time = tree.xpath("//div[@class='co_content8']/ul/text()")[0].strip() imgs = tree.xpath("//div[@id='Zoom']//img/@src") # 电影海报 cover = imgs[0] # 电影截图 screenshoot = imgs[1] # 获取span标签下全部的文本 infos = tree.xpath("//div[@id='Zoom']//text()") for index,info in enumerate(infos): if info.startswith("◎年 代"): year = info.replace("◎年 代","").strip() if info.startswith("◎豆瓣评分"): douban_rating = info.replace("◎豆瓣评分",'').strip() print(douban_rating) if info.startswith("◎主 演"): # 从当前位置,一直往下面遍历 actors = [info] for x in range(index+1,len(infos)): actor = infos[x] if actor.startswith("◎"): break actors.append(actor.strip()) print(",".join(actors)) if __name__ == '__main__': spider()
在62版本(目前最新)中有一个bug,在页面302重定向的时候不能记录FormData数据。这个是这个版本的一个bug。详细见如下连接:https://stackoverflow.com/questions/34015735/http-post-payload-not-visible-in-chrome-debugger。
在金丝雀版本中已经解决了这个问题,能够下载这个版本继续,连接以下:https://www.google.com/chrome/browser/canary.html
和 lxml 同样,Beautiful Soup 也是一个HTML/XML的解析器,主要的功能也是如何解析和提取 HTML/XML 数据。
lxml 只会局部遍历,而Beautiful Soup 是基于HTML DOM(Document Object Model)的,会载入整个文档,解析整个DOM树,所以时间和内存开销都会大不少,因此性能要低于lxml。
BeautifulSoup 用来解析 HTML 比较简单,API很是人性化,支持CSS选择器、Python标准库中的HTML解析器,也支持 lxml 的 XML解析器。
Beautiful Soup 3 目前已经中止开发,推荐如今的项目使用Beautiful Soup 4。
pip install bs4
。解析工具 | 解析速度 | 使用难度 |
---|---|---|
BeautifulSoup | 最慢 | 最简单 |
lxml | 快 | 简单 |
正则 | 最快 | 最难 |
Beautiful Soup支持Python标准库中的HTML解析器,还支持一些第三方的解析器,若是咱们不安装它,则 Python 会使用 Python默认的解析器,lxml 解析器更增强大,速度更快,推荐安装。
下面是常看法析器:
推荐使用lxml做为解析器,由于效率更高. 在Python2.7.3以前的版本和Python3中3.2.2以前的版本,必须安装lxml或html5lib, 由于那些Python版本的标准库中内置的HTML解析方法不够稳定.
from bs4 import BeautifulSoup html = """ <html><head><title>The Dormouse's story</title></head> <body> <p class="title" name="dromouse"><b>The Dormouse's story</b></p> <p class="story">Once upon a time there were three little sisters; and their names were <a href="http://example.com/elsie" class="sister" id="link1"><!-- Elsie --></a>, <a href="http://example.com/lacie" class="sister" id="link2">Lacie</a> and <a href="http://example.com/tillie" class="sister" id="link3">Tillie</a>; and they lived at the bottom of a well.</p> <p class="story">...</p> """ #建立 Beautiful Soup 对象 # 使用lxml来进行解析 soup = BeautifulSoup(html,"lxml") print(soup.prettify())
Beautiful Soup将复杂HTML文档转换成一个复杂的树形结构,每一个节点都是Python对象,全部对象能够概括为4种:
Tag 通俗点讲就是 HTML 中的一个个标签。示例代码以下:
from bs4 import BeautifulSoup html = """ <html><head><title>The Dormouse's story</title></head> <body> <p class="title" name="dromouse"><b>The Dormouse's story</b></p> <p class="story">Once upon a time there were three little sisters; and their names were <a href="http://example.com/elsie" class="sister" id="link1"><!-- Elsie --></a>, <a href="http://example.com/lacie" class="sister" id="link2">Lacie</a> and <a href="http://example.com/tillie" class="sister" id="link3">Tillie</a>; and they lived at the bottom of a well.</p> <p class="story">...</p> """ #建立 Beautiful Soup 对象 soup = BeautifulSoup(html,'lxml') print soup.title # <title>The Dormouse's story</title> print soup.head # <head><title>The Dormouse's story</title></head> print soup.a # <a class="sister" href="http://example.com/elsie" id="link1"><!-- Elsie --></a> print soup.p # <p class="title" name="dromouse"><b>The Dormouse's story</b></p> print type(soup.p) # <class 'bs4.element.Tag'>
咱们能够利用 soup 加标签名轻松地获取这些标签的内容,这些对象的类型是bs4.element.Tag。可是注意,它查找的是在全部内容中的第一个符合要求的标签。若是要查询全部的标签,后面会进行介绍。
对于Tag,它有两个重要的属性,分别是name和attrs。示例代码以下:
print soup.name # [document] #soup 对象自己比较特殊,它的 name 即为 [document] print soup.head.name # head #对于其余内部标签,输出的值便为标签自己的名称 print soup.p.attrs # {'class': ['title'], 'name': 'dromouse'} # 在这里,咱们把 p 标签的全部属性打印输出了出来,获得的类型是一个字典。 print soup.p['class'] # soup.p.get('class') # ['title'] #还能够利用get方法,传入属性的名称,两者是等价的 soup.p['class'] = "newClass" print soup.p # 能够对这些属性和内容等等进行修改 # <p class="newClass" name="dromouse"><b>The Dormouse's story</b></p>
若是拿到标签后,还想获取标签中的内容。那么能够经过tag.string
获取标签中的文字。示例代码以下:
print soup.p.string # The Dormouse's story print type(soup.p.string) # <class 'bs4.element.NavigableString'>thon
BeautifulSoup 对象表示的是一个文档的所有内容.大部分时候,能够把它看成 Tag 对象,它支持 遍历文档树 和 搜索文档树 中描述的大部分的方法.
由于 BeautifulSoup 对象并非真正的HTML或XML的tag,因此它没有name和attribute属性.但有时查看它的 .name 属性是很方便的,因此 BeautifulSoup 对象包含了一个值为 “[document]” 的特殊属性 .name
soup.name # '[document]'
Tag , NavigableString , BeautifulSoup 几乎覆盖了html和xml中的全部内容,可是还有一些特殊对象.容易让人担忧的内容是文档的注释部分:
markup = "<b><!--Hey, buddy. Want to buy a used parser?--></b>" soup = BeautifulSoup(markup) comment = soup.b.string type(comment) # <class 'bs4.element.Comment'>
Comment 对象是一个特殊类型的 NavigableString 对象:
comment # 'Hey, buddy. Want to buy a used parser'
html_doc = """ <html><head><title>The Dormouse's story</title></head> <p class="title"><b>The Dormouse's story</b></p> <p class="story">Once upon a time there were three little sisters; and their names were <a href="http://example.com/elsie" class="sister" id="link1">Elsie</a>, <a href="http://example.com/lacie" class="sister" id="link2">Lacie</a> and <a href="http://example.com/tillie" class="sister" id="link3">Tillie</a>; and they lived at the bottom of a well.</p> <p class="story">...</p> """ from bs4 import BeautifulSoup soup = BeautifulSoup(html_doc,'lxml') head_tag = soup.head # 返回全部子节点的列表 print(head_tag.contents) # 返回全部子节点的迭代器 for child in head_tag.children: print(child)
若是tag中包含多个字符串 [2] ,可使用 .strings 来循环获取:
for string in soup.strings: print(repr(string)) # u"The Dormouse's story" # u'\n\n' # u"The Dormouse's story" # u'\n\n' # u'Once upon a time there were three little sisters; and their names were\n' # u'Elsie' # u',\n' # u'Lacie' # u' and\n' # u'Tillie' # u';\nand they lived at the bottom of a well.' # u'\n\n' # u'...' # u'\n'
输出的字符串中可能包含了不少空格或空行,使用 .stripped_strings 能够去除多余空白内容:
for string in soup.stripped_strings: print(repr(string)) # u"The Dormouse's story" # u"The Dormouse's story" # u'Once upon a time there were three little sisters; and their names were' # u'Elsie' # u',' # u'Lacie' # u'and' # u'Tillie' # u';\nand they lived at the bottom of a well.' # u'...'
搜索文档树,通常用得比较多的就是两个方法,一个是find
,一个是find_all
。find
方法是找到第一个知足条件的标签后就当即返回,只返回一个元素。find_all
方法是把全部知足条件的标签都选到,而后返回回去。使用这两个方法,最经常使用的用法是出入name
以及attr
参数找出符合要求的标签。
soup.find_all("a",attrs={"id":"link2"})
或者是直接传入属性的的名字做为关键字参数:
soup.find_all("a",id='link2')
使用以上方法能够方便的找出元素。但有时候使用css
选择器的方式能够更加的方便。使用css
选择器的语法,应该使用select
方法。如下列出几种经常使用的css
选择器方法:
print(soup.select('a'))
经过类名,则应该在类的前面加一个.
。好比要查找class=sister
的标签。示例代码以下:
print(soup.select('.sister'))
经过id查找,应该在id的名字前面加一个#号。示例代码以下:
print(soup.select("#link1"))
组合查找即和写 class 文件时,标签名与类名、id名进行的组合原理是同样的,例如查找 p 标签中,id 等于 link1的内容,两者须要用空格分开:
print(soup.select("p #link1"))
直接子标签查找,则使用 > 分隔:
print(soup.select("head > title"))
查找时还能够加入属性元素,属性须要用中括号括起来,注意属性和标签属于同一节点,因此中间不能加空格,不然会没法匹配到。示例代码以下:
print(soup.select('a[href="http://example.com/elsie"]'))
以上的 select 方法返回的结果都是列表形式,能够遍历形式输出,而后用 get_text() 方法来获取它的内容。
soup = BeautifulSoup(html, 'lxml') print type(soup.select('title')) print soup.select('title')[0].get_text() for title in soup.select('title'): print title.get_text()
第三节:正则表达式和re模块:
通俗理解:按照必定的规则,从某个字符串中匹配出想要的数据。这个规则就是正则表达式。
标准答案:https://baike.baidu.com/item/正则表达式/1700215?fr=aladdin
世界是分为两种人,一种是懂正则表达式的,一种是不懂正则表达式的。
text = 'hello' ret = re.match('he',text) print(ret.group()) >> he
以上即可以在hello
中,匹配出he
。
text = "ab" ret = re.match('.',text) print(ret.group()) >> a
可是点(.)不能匹配不到换行符。示例代码以下:
text = "ab" ret = re.match('.',text) print(ret.group()) >> AttributeError: 'NoneType' object has no attribute 'group'
text = "123" ret = re.match('\d',text) print(ret.group()) >> 1
text = "a" ret = re.match('\D',text) print(ret.group()) >> a
而若是text是等于一个数字,那么就匹配不成功了。示例代码以下:
text = "1" ret = re.match('\D',text) print(ret.group()) >> AttributeError: 'NoneType' object has no attribute 'group'
text = "\t" ret = re.match('\s',text) print(ret.group()) >> 空白
a-z
和A-Z
以及数字和下划线:text = "_" ret = re.match('\w',text) print(ret.group()) >> _
而若是要匹配一个其余的字符,那么就匹配不到。示例代码以下:
text = "+" ret = re.match('\w',text) print(ret.group()) >> AttributeError: 'NoneType' object has no attribute
text = "+" ret = re.match('\W',text) print(ret.group()) >> +
而若是你的text是一个下划线或者英文字符,那么就匹配不到了。示例代码以下:
text = "_" ret = re.match('\W',text) print(ret.group()) >> AttributeError: 'NoneType' object has no attribute
text = "0731-88888888" ret = re.match('[\d\-]+',text) print(ret.group()) >> 0731-88888888
以前讲到的几种匹配规则,其实可使用中括号的形式来进行替代:
*
:能够匹配0或者任意多个字符。示例代码以下:
text = "0731" ret = re.match('\d*',text) print(ret.group()) >> 0731
以上由于匹配的要求是\d
,那么就要求是数字,后面跟了一个星号,就能够匹配到0731这四个字符。
+
:能够匹配1个或者多个字符。最少一个。示例代码以下:
text = "abc" ret = re.match('\w+',text) print(ret.group()) >> abc
由于匹配的是\w
,那么就要求是英文字符,后面跟了一个加号,意味着最少要有一个知足\w
的字符才可以匹配到。若是text是一个空白字符或者是一个不知足\w的字符,那么就会报错。示例代码以下:
text = "" ret = re.match('\w+',text) print(ret.group()) >> AttributeError: 'NoneType' object has no attribute
?
:匹配的字符能够出现一次或者不出现(0或者1)。示例代码以下:
text = "123" ret = re.match('\d?',text) print(ret.group()) >> 1
{m}
:匹配m个字符。示例代码以下:
text = "123" ret = re.match('\d{2}',text) print(ret.group()) >> 12
{m,n}
:匹配m-n个字符。在这中间的字符均可以匹配到。示例代码以下:
text = "123" ret = re.match('\d{1,2}',text) prit(ret.group()) >> 12
若是text只有一个字符,那么也能够匹配出来。示例代码以下:
text = "1" ret = re.match('\d{1,2}',text) prit(ret.group()) >> 1
验证手机号码:手机号码的规则是以1
开头,第二位能够是34587
,后面那9位就能够随意了。示例代码以下:
text = "18570631587" ret = re.match('1[34587]\d{9}',text) print(ret.group()) >> 18570631587
而若是是个不知足条件的手机号码。那么就匹配不到了。示例代码以下:
text = "1857063158" ret = re.match('1[34587]\d{9}',text) print(ret.group()) >> AttributeError: 'NoneType' object has no attribute
验证邮箱:邮箱的规则是邮箱名称是用数字、数字、下划线
组成的,而后是@
符号,后面就是域名了。示例代码以下:
text = "hynever@163.com" ret = re.match('\w+@\w+\.[a-zA-Z\.]+',text) print(ret.group())
验证URL:URL的规则是前面是http
或者https
或者是ftp
而后再加上一个冒号,再加上一个斜杠,再后面就是能够出现任意非空白字符了。示例代码以下:
text = "http://www.baidu.com/" ret = re.match('(http|https|ftp)://[^\s]+',text) print(ret.group())
验证身份证:身份证的规则是,总共有18位,前面17位都是数字,后面一位能够是数字,也能够是小写的x,也能够是大写的X。示例代码以下:
text = "3113111890812323X" ret = re.match('\d{17}[\dxX]',text) print(ret.group())
text = "hello" ret = re.match('^h',text) print(ret.group())
若是是在中括号中,那么表明的是取反操做.
# 匹配163.com的邮箱 text = "xxx@163.com" ret = re.search('\w+@163\.com$',text) print(ret.group()) >> xxx@163.com
text = "hello|world" ret = re.search('hello',text) print(ret.group()) >> hello
贪婪模式:正则表达式会匹配尽可能多的字符。默认是贪婪模式。
非贪婪模式:正则表达式会尽可能少的匹配字符。
示例代码以下:
text = "0123456" ret = re.match('\d+',text) print(ret.group()) # 由于默认采用贪婪模式,因此会输出0123456 >> 0123456
能够改为非贪婪模式,那么就只会匹配到0。示例代码以下:
text = "0123456" ret = re.match('\d+?',text) print(ret.group())
0-100
之间的数字:text = '99' ret = re.match('[1-9]?\d$|100$',text) print(ret.group()) >> 99
而若是text=101
,那么就会抛出一个异常。示例代码以下:
text = '101' ret = re.match('[1-9]?\d$|100$',text) print(ret.group()) >> AttributeError: 'NoneType' object has no attribute 'group'
在正则表达式中,有些字符是有特殊意义的字符。所以若是想要匹配这些字符,那么就必须使用反斜杠进行转义。好比$
表明的是以...结尾,若是想要匹配$
,那么就必须使用\$
。示例代码以下:
text = "apple price is \$99,orange paice is $88" ret = re.search('\$(\d+)',text) print(ret.group()) >> $99
原生字符串:
在正则表达式中,\
是专门用来作转义的。在Python中\
也是用来作转义的。所以若是想要在普通的字符串中匹配出\
,那么要给出四个\
。示例代码以下:
text = "apple \c" ret = re.search('\\\\c',text) print(ret.group())
所以要使用原生字符串就能够解决这个问题:
text = "apple \c" ret = re.search(r'\\c',text) print(ret.group())
从开始的位置进行匹配。若是开始的位置没有匹配到。就直接失败了。示例代码以下:
text = 'hello' ret = re.match('h',text) print(ret.group()) >> h
若是第一个字母不是h
,那么就会失败。示例代码以下:
text = 'ahello' ret = re.match('h',text) print(ret.group()) >> AttributeError: 'NoneType' object has no attribute 'group'
若是想要匹配换行的数据,那么就要传入一个flag=re.DOTALL
,就能够匹配换行符了。示例代码以下:
text = "abc\nabc" ret = re.match('abc.*abc',text,re.DOTALL) print(ret.group())
在字符串中找知足条件的字符。若是找到,就返回。说白了,就是只会找到第一个知足条件的。
text = 'apple price $99 orange price $88' ret = re.search('\d+',text) print(ret.group()) >> 99
在正则表达式中,能够对过滤到的字符串进行分组。分组使用圆括号的方式。
group
:和group(0)
是等价的,返回的是整个知足条件的字符串。groups
:返回的是里面的子组。索引从1开始。group(1)
:返回的是第一个子组,能够传入多个。text = "apple price is $99,orange price is $10" ret = re.search(r".*(\$\d+).*(\$\d+)",text) print(ret.group()) print(ret.group(0)) print(ret.group(1)) print(ret.group(2)) print(ret.groups())
找出全部知足条件的,返回的是一个列表。
text = 'apple price $99 orange price $88' ret = re.findall('\d+',text) print(ret) >> ['99', '88']
用来替换字符串。将匹配到的字符串替换为其余字符串。
text = 'apple price $99 orange price $88' ret = re.sub('\d+','0',text) print(ret) >> apple price $0 orange price $0
sub
函数的案例,获取拉勾网中的数据:
html = """ <div> <p>基本要求:</p> <p>一、精通HTML五、CSS三、 JavaScript等Web前端开发技术,对html5页面适配充分了解,熟悉不一样浏览器间的差别,熟练写出兼容各类浏览器的代码;</p> <p>二、熟悉运用常见JS开发框架,如JQuery、vue、angular,能快速高效实现各类交互效果;</p> <p>三、熟悉编写可以自动适应HTML5界面,能让网页格式自动适应各款各大小的手机;</p> <p>四、利用HTML5相关技术开发移动平台、PC终端的前端页面,实现HTML5模板化;</p> <p>五、熟悉手机端和PC端web实现的差别,有移动平台web前端开发经验,了解移动互联网产品和行业,有在Android,iOS等平台下HTML5+CSS+JavaScript(或移动JS框架)开发经验者优先考虑;
<p>六、良好的沟通能力和团队协做精神,对移动互联网行业有浓厚兴趣,有较强的研究能力和学习能力;</p> <p>七、可以承担公司前端培训工做,对公司各业务线的前端(HTML5\CSS3)工做进行支撑和指导。</p> <p><br></p> <p>岗位职责:</p> <p>一、利用html5及相关技术开发移动平台、微信、APP等前端页面,各种交互的实现;</p> <p>二、持续的优化前端体验和页面响应速度,并保证兼容性和执行效率;</p> <p>三、根据产品需求,分析并给出最优的页面前端结构解决方案;</p> <p>四、协助后台及客户端开发人员完成功能开发和调试;</p> <p>五、移动端主流浏览器的适配、移动端界面自适应研发。</p> </div> """ ret = re.sub('</?[a-zA-Z0-9]+>',"",html) print(ret)
使用正则表达式来分割字符串。
text = "hello world ni hao" ret = re.split('\W',text) print(ret) >> ["hello","world","ni","hao"]
对于一些常常要用到的正则表达式,可使用compile
进行编译,后期再使用的时候能够直接拿过来用,执行效率会更快。并且compile
还能够指定flag=re.VERBOSE
,在写正则表达式的时候能够作好注释。示例代码以下:
text = "the number is 20.50" r = re.compile(r""" \d+ # 小数点前面的数字 \.? # 小数点 \d* # 小数点后面的数字 """,re.VERBOSE) ret = re.search(r,text) print(ret.group())