课程地址 https://edu.csdn.net/course/detail/24756/280664
xpath(XML Path Language)是一门在XML和HTML文档中查找信息 的语言,可用来在XML和HTML文档中对元素和属性进行遍历。
在 XPath 中,有七种类型的节点:元素、属性、文本、命名 空间、处理指令、注释以及文档(根)节点。XML 文档是被 作为节点树来对待的。树的根被称为文档节点或者根节点。
使用方式:
使用//获取整个页面当中的元素,然后写标签名,然后再写谓词进行提取,比如:
//title[@lang='en']
需要注意的知识点:
//title[contains(@lang,'en')]
lxml是一个HTML/XML的解析器,主要的功能是如何解析和提取HTML/XML数据。
基本使用:
from lxml import etree
text = '''
'''
# 将字符串解析为html文档
html = etree.HTML(text)
print(html)
# 按字符串序列化html
result = etree.tostring(html).decode('utf-8')
print(result)
从文件中读取html代码:
#读取
html = etree.parse('hello.html')
result = etree.tostring(html).decode('utf-8')
print(result)
<!-- hello.html -->
>>
>
>
- -0">>first item>
>
- -1">>second item>
>
- -inactive">>>third item>>
>
- -1">>fourth item>
>
- -0">>fifth item>
>
>
>
>>
语法练习
from lxml import etree
html = etree.parse('hello.html')
# 获取所有li标签:
result = html.xpath('//li')
print(result)
# for i in result:
# print(etree.tostring(i))
# 获取所有li元素下的所有class属性的值:
# result = html.xpath('//li/@class')
# print(result)
# 获取li标签下href为www.baidu.com的a标签:
# result = html.xpath('//li/a[@href="www.baidu.com"]')
# print(result)
# 获取li标签下所有span标签:
# result = html.xpath('//li//span')
# print(result)
# 获取li标签下的a标签里的所有class:
# result = html.xpath('//li/a//@class')
# print(result)
# 获取最后一个li的a的href属性对应的值:
# result = html.xpath('//li[last()]/a/@href')
# print(result)
# 获取倒数第二个li元素的内容:
# result = html.xpath('//li[last()-1]/a')
# print(result)
# print(result[0].text)
# 获取倒数第二个li元素的内容的第二种方式:
result = html.xpath('//li[last()-1]/a/text()')
print(result)
安装:pip install bs4
中文文档:https://www.crummy.com/software/BeautifulSoup/bs4/doc/index.zh.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>"
soup = BeautifulSoup(html,'lxml')
print(soup.prettify())
返回某个标签下的直接子元素,其中也包括字符串。他们两的区别是:contents返回来的是一个列表,children返回的是一个迭代器。
attrs
属性,将所有的属性以及对应的值放在一个字典中传给attrs
属性。limit
参数。限制提取多少个。 href = a['href']
href = a.attrs['href']
使用以上方法可以方便的找出元素。但有时候使用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())
# 匹配某个字符串:
# text = "abc"
# ret = re.match('b',text)
# print(ret.group())
# 点(.):匹配任意的字符(除了'\n'):
# text = "\nabc"
# ret = re.match('.',text)
# print(ret.group())
# \d:匹配任意的数字:
# text = "aab"
# ret = re.match('\d',text)
# print(ret.group())
# \D:匹配任意的非数字:
# text = "cab"
# ret = re.match('\D',text)
# print(ret.group())
# \s:匹配的是空白字符(包括:\n,\t,\r和空格):
# text = " ab"
# ret = re.match('\s',text)
# print("="*30)
# print(ret.group())
# print("="*30)
# \S:非空白字符:
# text = "\nab"
# ret = re.match('\S',text)
# print("="*30)
# print(ret.group())
# print("="*30)
# \w:匹配的是a-z和A-Z以及数字和下划线:
# text = "+bc"
# ret = re.match('\w',text)
# print("="*30)
# print(ret.group())
# print("="*30)
# \W:匹配的是和\w相反的:
# text = "1bc"
# ret = re.match('\W',text)
# print("="*30)
# print(ret.group())
# print("="*30)
# []组合的方式,只要满足中括号中的某一项都算匹配成功:
# text = "bc"
# ret = re.match('[1b]',text)
# print("="*30)
# print(ret.group())
# print("="*30)
# 使用组合的方式[0-9]\d:
# text = "abc"
# ret = re.match('[^0-9]',text)
# print("="*30)
# print(ret.group())
# print("="*30)
# 使用组合的方式实现\w:
text = "+bc"
ret = re.match('[^a-zA-Z0-9_]',text)
print("="*30)
print(ret.group())
print("="*30)
# *:匹配0个或者多个字符:
# text = "+abc"
# result = re.match('\D*',text)
# print(result.group())
# +:匹配1个或者多个字符:
# text = "1abc"
# result = re.match('\w+',text)
# print(result.group())
# ?:匹配前一个字符0个或者1个:
# text = "+abc"
# result = re.match('\w?',text)
# print(result.group())
# {m}:匹配m个字符:
# text = "+1abc"
# result = re.match('\w{2}',text)
# print(result.group())
# {m,n}:匹配m-n之间的个数的字符:
text = "1abc+"
result = re.match('\w{1,3}',text)
print(result.group())
# 1. 验证手机号码:手机号码的规则是以1开头,第二位可以是34587,后面那9位就可以随意了。
# text = "18677889900"
# result = re.match("1[34587]\d{9}",text)
# print(result.group())
# 2. 验证邮箱:邮箱的规则是邮箱名称是用数字、英文字符、下划线组成的,然后是@符号,后面就是域名了。
# text = "[email protected]"
# result = re.match("\w+@[a-z0-9]+\.[a-z]+",text)
# print(result.group())
# 3. 验证URL:URL的规则是前面是http或者https或者是ftp然后再加上一个冒号,再加上一个斜杠,再后面就是可以出现任意非空白字符了。
# text = "https://baike.baidu.com/item/Python/407313?fr=aladdin"
# result = re.match("(http|https|ftp)://\S+",text)
# print(result.group())
# 4. 验证身份证:身份证的规则是,总共有18位,前面17位都是数字,后面一位可以是数字,也可以是小写的x,也可以是大写的X。
text = "36530019870716234x"
result = re.match("\d{17}[\dxX]",text)
print(result.group())
# ^:以...开头:
# text = "hello world"
# result = re.search("world",text)
# print(result.group())
# $:以...结尾:
# text = "hello world"
# result = re.search("hello$",text)
# print(result.group())
# text = ""
# result = re.search("^$",text)
# print(result.group())
# |:匹配多个字符串或者表达式:
# 贪婪和非贪婪:
# text = "12345"
# result = re.search("\d+?",text)
# print(result.group())
# 案例1:提取html标签名称:
# text = "这是标题
"
# result = re.search("<.+?>",text)
# print(result.group())
# 案例2:验证一个字符是不是0-100之间的数字:
# 0,1,99,100
# 01
text = "101"
result = re.match("0$|[1-9]\d?$|100$",text)
print(result.group())
# Python中的转义字符:
# raw
# text = r"hello\nworld"
# print(text)
# 正则表达式中的转义字符:
# text = "apple price is $99,range price is $88"
# result = re.findall("\$\d+",text)
# print(result)
# 原生字符串和正则表达式:
# 正则表达式的字符串解析规则:
# 1. 先把这个字符串放在Python语言层面进行解析。
# 2. 把Python语言层面解析的结果再放到正则表达式层间进行解析。
text = "\cba c"
# result = re.match("\\\\c",text) # \\\\c =(Python语言层面)> \\c =(正则表达式层面)> \c
result = re.match(r"\\c",text) # \\c =(正则表达式层面)> \c
print(result.group())
text = "apple price is $99,orange price is $88"
result = re.search('.+(\$\d+).+(\$\d+)',text)
print(result.groups())
# group()/group(0):匹配整个分组
# group(1):匹配第一个分组
# group(2):匹配第二个分组
# groups():获取所有的分组
# findall:查找所有满足条件的
# text = "apple price is $99,orange price is $88"
# result = re.findall(r'\$\d+',text)
# print(result)
# sub:根据规则替换其他字符串
# text = "nihao zhongguo,hello world"
# new_text = text.replace(" ","\n")
# new_text = re.sub(r' |,','\n',text)
# print(new_text)
# html = """
#
# 1. 3年以上相关开发经验 ,全日制统招本科以上学历
# 2. 精通一门或多门开发语言(Python,C,Java等),其中至少有一门有3年以上使用经验
# 3. 熟练使用ES/mysql/mongodb/redis等数据库;
# 4. 熟练使用django、tornado等web框架,具备独立开发 Python/Java 后端开发经验;
# 5. 熟悉 Linux / Unix 操作系统
# 6. 熟悉 TCP/IP,http等网络协议
# 福利:
# 1、入职购买六险一金(一档医疗+公司全额购买商业险)+开门红+全额年终奖(1年13薪,一般会比一个月高)
# 2、入职满一年有2次调薪调级机会
# 3、项目稳定、团队稳定性高,团队氛围非常好(汇合员工占招行总员工比例接近50%);
# 4、有机会转为招商银行内部员工;
# 5、团队每月有自己的活动经费,法定节假日放假安排;
# 6、办公环境优良,加班有加班费(全额工资为计算基数,加班不超过晚上10点,平日加班为时薪1.5倍,周末加班为日薪2倍,周末加班也可优先选择调休,管理人性化)。
#
# """
# new_html = re.sub(r'<.+?>',"",html)
# print(new_html)
# split:根据规则分割字符串
# text = "nihao zhongguo,hello world"
# result = re.split(r' |,',text)
# print(result)
# compile:编译正则表达式
text = "apple price is 34.56"
# r = re.compile(r"""
# \d+ # 整数部分
# \.? # 小数点
# \d* # 小数部分
# """,re.VERBOSE)
# result = re.search(r,text)
result = re.search(r"""
\d+ # 整数部分
\.? # 小数点
\d* # 小数部分
""",text,re.VERBOSE)
print(result.group())
如果想要在正则表达式中加注释,那么需要在正则表达式的函数最后加一个re.VERBOSE
。