• 【零基础一看就会】Python爬虫从入门到应用(上)


    目录

    一、beautifulsoup解析

    1.1 beautifulsoup的简单使用

    安装

    解析器

    解析器对比 

    快速开始

    如何使用

    对象的种类

    Tag

    tag的名字

    name和attributes属性

    NavigableString(字符串)

    BeautifulSoup

    Comment

    1.2 beautifulsoup的遍历文档树

    子节点

    contents 和 .children

    descendants

    节点内容

    .string

    .text

    多个内容

    .strings

    .stripped_strings

    父节点

    .parent

    .parents

    1.3 beautifulsoup的搜索文档树

    find_all

    name 参数

    keyword 参数

    text 参数

    limit 参数

    find()

    find_parents() 和 find_parent()

    1.4 beautifulsoup的css选择器

    通过标签名查找

    通过类名查找

    id名查找

    组合查找

    属性查找

    二、xpath解析

    1.1 xpath安装与使用

    1.2 解析流程与使用

    1.3 xpath语法

    路径表达式

    谓语(Predicates)

    选取未知节点

    逻辑运算

    属性查询

    获取第几个标签 索引从1开始

    模糊查询

    内容查询

    属性值获取

    获取所有

    获取节点内容转换成字符串


    一、beautifulsoup解析

    1.1 beautifulsoup的简单使用

    简单来说,Beautiful Soup是python的一个库,最主要的功能是从网页抓取数据。官方解释如下:

    Beautiful Soup提供一些简单的、python式的函数用来处理导航、搜索、修改分析树等功能。 它是一个工具箱,通过解析文档为用户提供需要抓取的数据,因为简单,所以不需要多少代码就可以写出一个完整的应用程序。

    安装

    pip install beautifulsoup4
    解析器

    Beautiful Soup支持Python标准库中的HTML解析器,还支持一些第三方的解析器,如果我们不安装它,则 Python 会使用 Python默认的解析器,lxml 解析器更加强大,速度更快,推荐安装。

    pip install lxml

    解析器对比 

    官网文档

    快速开始

    下面的一段HTML代码将作为例子被多次用到,这是 爱丽丝梦游仙境的 的一段内容(以后内容中简称为 爱丽丝 的文档):

    1. html_doc = """
    2. The Dormouse's story
    3. The Dormouse's story

    4. Once upon a time there were three little sisters; and their names were

    5. Lacie and
    6. and they lived at the bottom of a well.

    7. ...

    8. """

    使用BeautifulSoup解析这段代码,能够得到一个 BeautifulSoup 的对象,并能按照标准的缩进格式的结构输出:

    1. from bs4 import BeautifulSoup
    2. soup = BeautifulSoup(html_doc, 'lxml')
    3. # html进行美化
    4. print(soup.prettify())

    打印代码:

    1. <html>
    2. <head>
    3. <title>
    4. The Dormouse's story
    5. title>
    6. head>
    7. <body>
    8. <p class="title">
    9. <b>
    10. The Dormouse's story
    11. b>
    12. p>
    13. <p class="story">
    14. Once upon a time there were three little sisters; and their names were
    15. <a class="sister" href="http://example.com/elsie" id="link1">
    16. Elsie
    17. a>
    18. ,
    19. <a class="sister" href="http://example.com/lacie" id="link2">
    20. Lacie
    21. a>
    22. and
    23. <a class="sister" href="http://example.com/tillie" id="link3">
    24. Tillie
    25. a>
    26. ;
    27. and they lived at the bottom of a well.
    28. p>
    29. <p class="story">
    30. ...
    31. p>
    32. body>
    33. html>

    几个简单的浏览结构化数据的方法:

    1. soup.title # 获取标签title
    2. # The Dormouse's story
    3. soup.title.name # 获取标签名称
    4. # 'title'
    5. soup.title.string # 获取标签title内的内容
    6. # 'The Dormouse's story'
    7. soup.title.parent # 获取父级标签
    8. soup.title.parent.name # 获取父级标签名称
    9. # 'head'
    10. soup.p
    11. #

      The Dormouse's story

    12. soup.p['class'] # 获取p的class属性值
    13. # 'title'
    14. soup.a
    15. soup.find_all('a')
    16. # [Elsie,
    17. soup.find(id="link3") # 获取id为link3的标签

    从文档中找到所有标签的链接:

    1. for link in soup.find_all('a'):
    2. print(link.get('href'))
    3. # http://example.com/elsie
    4. # http://example.com/lacie
    5. # http://example.com/tillie

    从文档中获取所有文字内容:

    print(soup.get_text())

    如何使用

    将一段文档传入BeautifulSoup 的构造方法,就能得到一个文档的对象, 可以传入一段字符串或一个文件句柄。

    1. from bs4 import BeautifulSoup
    2. soup = BeautifulSoup(open("index.html"), 'lxml')
    3. soup = BeautifulSoup("data", 'lxml')

    然后Beautiful Soup选择最合适的解析器来解析这段文档,如果手动指定解析器那么Beautiful Soup会选择指定的解析器来解析文档。

    对象的种类

    Beautiful Soup将复杂HTML文档转换成一个复杂的树形结构,每个节点都是Python对象,所有对象可以归纳为

    Tag , NavigableString , BeautifulSoup , Comment .

    Tag

    通俗点讲就是 HTML 中的一个个标签,Tag 对象与XML或HTML原生文档中的tag相同:

    1. soup = BeautifulSoup('Extremely bold')
    2. tag = soup.b
    3. type(tag)
    4. #

    tag的名字

    soup对象再以爱丽丝梦游仙境的html_doc为例,操作文档树最简单的方法就是告诉它你想获取的tag的name.如果想获取 标签,只要用 soup.head :

    1. soup.head
    2. # The Dormouse's story
    3. soup.title
    4. # The Dormouse's story

    这是个获取tag的小窍门,可以在文档树的tag中多次调用这个方法。下面的代码可以获取标签中的第一个标签:

    1. soup.body.b
    2. # The Dormouse's story

    通过点取属性的方式只能获得当前名字的第一个tag:

    1. soup.a

    如果想要得到所有的标签,或是通过名字得到比一个tag更多的内容的时候,就需要用到 Searching the tree 中描述的方法,比如: find_all()

    1. soup.find_all('a')

    我们可以利用 soup加标签名轻松地获取这些标签的内容,注意,它查找的是在所有内容中的第一个符合要求的标签。

    name和attributes属性

    Tag有很多方法和属性,现在介绍一下tag中最重要的属性:nameattributes

    每个tag都有自己的名字,通过 .name 来获取:

    1. tag.name
    2. # 'b'
    3. tag['class']
    4. # 'boldest'
    5. tag.attrs
    6. # {'class': 'boldest'}

    tag的属性可以被添加,删除或修改。再说一次,tag的属性操作方法与字典一样(了解)。

    1. tag['class'] = 'verybold'
    2. tag['id'] = 1
    3. tag
    4. #
      Extremely bold
    5. del tag['class']
    6. del tag['id']
    7. tag
    8. #
      Extremely bold
    9. tag['class']
    10. # KeyError: 'class'
    11. print(tag.get('class'))
    12. # None

    既然我们已经得到了标签的内容,那么问题来了,我们要想获取标签内部的文字怎么办呢?很简单,用 .string 即可。

    字符串常被包含在tag内.Beautiful Soup用 NavigableString 类来包装tag中的字符串:

    1. tag.string
    2. # 'Extremely bold'
    3. type(tag.string)
    4. #

    BeautifulSoup

    BeautifulSoup 对象表示的是一个文档的全部内容。大部分时候,可以把它当作 Tag 对象,是一个特殊的 Tag,我们可以分别获取它的类型,名称,以及属性。

    1. print(type(soup.name))
    2. #
    3. print(soup.name)
    4. # [document]
    5. print(soup.attrs)
    6. # {} 空字典

    Comment

    如果字符串内容为注释 则为Comment。

    1. html_doc=''
    2. soup = BeautifulSoup(html_doc, 'html.parser')
    3. print(soup.a.string) # Elsie
    4. print(type(soup.a.string)) #

    a 标签里的内容实际上是注释,但是如果我们利用 .string 来输出它的内容,我们发现它已经把注释符号去掉了,所以这可能会给我们带来不必要的麻烦。

    1.2 beautifulsoup的遍历文档树

    还拿”爱丽丝梦游仙境”的文档来做例子:

    1. html_doc = """
    2. The Dormouse's story
    3. The Dormouse's story

    4. Once upon a time there were three little sisters; and their names were

    5. Lacie and
    6. and they lived at the bottom of a well.

    7. ...

    8. """
    9. from bs4 import BeautifulSoup
    10. soup = BeautifulSoup(html_doc, 'html.parser')

    通过这段例子来演示怎样从文档的一段内容找到另一段内容。

    子节点

    一个Tag可能包含多个字符串或其它的Tag,这些都是这个Tag的子节点。Beautiful Soup提供了许多操作和遍历子节点的属性。

    注意:Beautiful Soup中字符串节点不支持这些属性,因为字符串没有子节点。

    contents 和 .children

    tag的 .contents 属性可以将tag的子节点以列表的方式输出:

    1. head_tag = soup.head
    2. head_tag
    3. # The Dormouse's story
    4. head_tag.contents
    5. [The Dormouse<span class="hljs-string"><span class="hljs-string">'s story]
    6. title_tag = head_tag.contents[0]
    7. title_tag
    8. # The Dormouse'</span>s story
    9. title_tag.contents
    10. # [u'The Dormouse's story']

    字符串没有 .contents 属性,因为字符串没有子节点:

    1. text = title_tag.contents[0]
    2. text.contents
    3. # AttributeError: 'NavigableString' object has no attribute 'contents'

    .children它返回的不是一个 list,不过我们可以通过遍历获取所有子节点。我们打印输出 .children 看一下,可以发现它是一个 list 生成器对象。

    通过tag的 .children 生成器,可以对tag的子节点进行循环:

    1. print(title_tag.children) #
    2. print(type(title_tag.children)) #
    3. for child in title_tag.children:
    4. print(child)
    5. # The Dormouse's story

    descendants

    .contents.children 属性仅包含tag的直接子节点。例如标签只有一个直接子节点</p> <pre data-index="23" class="set-code-show" name="code"><code class="language-python hljs"><ol class="hljs-ln" style="width:100%"><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="1"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line">head_tag.contents</div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="2"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"><span class="hljs-comment"># [<title>The Dormouse's story]

  • 但是标签也包含一个子节点:字符串 “The Dormouse’s story”,这种情况下字符串 “The Dormouse’s story”也属于<head>标签的子孙节点。</p> <p><code>.descendants</code> 属性可以对所有tag的子孙节点进行递归循环 。</p> <pre data-index="24" class="set-code-show" name="code"><code class="language-python hljs"><ol class="hljs-ln" style="width:100%"><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="1"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"><span class="hljs-keyword">for</span> child <span class="hljs-keyword">in</span> head_tag.descendants:</div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="2"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"> <span class="hljs-built_in">print</span>(child)</div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="3"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"> <span class="hljs-comment"># <title>The Dormouse's story

  • # The Dormouse's story
  • 上面的例子中,标签只有一个子节点,但是有2个子孙节点:节点和的子节点,BeautifulSoup 有一个直接子节点(节点),却有很多子孙节点:

    1. len(list(soup.children))
    2. # 1
    3. len(list(soup.descendants))
    4. # 25

    节点内容

    .string

    如果tag只有一个 NavigableString 类型子节点,那么这个tag可以使用 .string 得到子节点。如果一个tag仅有一个子节点,那么这个tag也可以使用 .string 方法,输出结果与当前唯一子节点的 .string 结果相同。

    通俗点说就是:如果一个标签里面没有标签了,那么 .string 就会返回标签里面的内容。如果标签里面只有唯一的一个标签了,那么 .string 也会返回最里面的内容。例如:

    1. print (soup.head.string)
    2. #The Dormouse's story
    3. # <b>The Dormouse's story</b>
    4. print (soup.title.string)
    5. #The Dormouse's story

    如果tag包含了多个子节点,tag就无法确定,string 方法应该调用哪个子节点的内容,.string 的输出结果是 None。

    1. print (soup.html.string)
    2. #None

    .text

    如果tag包含了多个子节点,text则会返回内部所有文本内容。

    print (soup.html.text)

    注意:

    strings和text都可以返回所有文本内容

    区别:text返回内容为字符串类型 strings为生成器generator

    多个内容

    .strings .stripped_strings 属性

    .strings

    获取多个内容,不过需要遍历获取,比如下面的例子:

    1. for string in soup.strings:
    2. print(repr(string))
    3. '''
    4. '\n'
    5. "The Dormouse's story"
    6. '\n'
    7. '\n'
    8. "The Dormouse's story"
    9. '\n'
    10. 'Once upon a time there were three little sisters; and their names were\n'
    11. 'Elsie'
    12. ',\n'
    13. 'Lacie'
    14. ' and\n'
    15. 'Tillie'
    16. ';\nand they lived at the bottom of a well.'
    17. '\n'
    18. '...'
    19. '\n'
    20. '''

    .stripped_strings

    输出的字符串中可能包含了很多空格或空行,使用 .stripped_strings 可以去除多余空白内容

    1. for string in soup.stripped_strings:
    2. print(repr(string))
    3. '''
    4. "The Dormouse's story"
    5. "The Dormouse's story"
    6. 'Once upon a time there were three little sisters; and their names were'
    7. 'Elsie'
    8. ','
    9. 'Lacie'
    10. 'and'
    11. 'Tillie'
    12. ';\nand they lived at the bottom of a well.'
    13. '...'
    14. '''

    父节点

    继续分析文档树,每个tag或字符串都有父节点被包含在某个tag中

    .parent

    通过 .parent 属性来获取某个元素的父节点。在例子“爱丽丝”的文档中,标签是标签的父节点:</p> <pre data-index="32" class="set-code-show" name="code"><code class="language-python hljs"><ol class="hljs-ln" style="width:100%"><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="1"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line">title_tag = soup.title</div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="2"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line">title_tag</div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="3"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"><span class="hljs-comment"># <title>The Dormouse's story

  • title_tag.parent
  • # The Dormouse's story
  • 文档的顶层节点比如的父节点是 BeautifulSoup 对象:

    1. html_tag = soup.html
    2. type(html_tag.parent)
    3. #

    .parents

    通过元素的 .parents 属性可以递归得到元素的所有父辈节点,下面的例子使用了 .parents 方法遍历了标签到根节点的所有节点。

    1. link = soup.a
    2. link
    3. for parent in link.parents:
    4. if parent is None:
    5. print(parent)
    6. else:
    7. print(parent.name)
    8. # p
    9. # body
    10. # html
    11. # [document]
    12. # None

    1.3 beautifulsoup的搜索文档树

    find_all

    find_all( name , attrs , recursive , string , **kwargs )

    find_all() 方法搜索当前tag的所有tag子节点,并判断是否符合过滤器的条件:

    1. soup.find_all("title")
    2. # [The Dormouse's story]
    3. soup.find_all("p", "title")
    4. # [

      The Dormouse's story

      ]
    5. soup.find_all("a")
    6. # [Elsie,
    7. soup.find_all(id="link2")
    8. # [Lacie]
    9. import re
    10. # 模糊查询 包含sisters的就可以
    11. soup.find(string=re.compile("sisters"))
    12. # 'Once upon a time there were three little sisters; and their names were\n'

    有几个方法很相似,还有几个方法是新的,参数中的 stringid 是什么含义? 为什么 find_all("p", "title") 返回的是CSS Class为”title”的

    标签? 我们来仔细看一下 find_all() 的参数。

    name 参数

    name 参数可以查找所有名字为 name 的tag,字符串对象会被自动忽略掉。

    简单的用法如下:

    1. soup.find_all("title")
    2. # [The Dormouse's story]

    搜索 name 参数的值可以使任一类型的过滤器 、字符串、正则表达式、列表、方法或是 True 。

    <1> 传字符串

    最简单的过滤器是字符串。在搜索方法中传入一个字符串参数,Beautiful Soup会查找与字符串完整匹配的内容,下面的例子用于查找文档中所有的标签

    1. soup.find_all('b')
    2. # [The Dormouse's story]

    <2> 传正则表达式

    如果传入正则表达式作为参数,Beautiful Soup会通过正则表达式的 match() 来匹配内容。下面例子中找出所有以b开头的标签,这表示和标签都应该被找到

    1. import re
    2. for tag in soup.find_all(re.compile("^b")):
    3. print(tag.name)
    4. # body
    5. # b

    <3> 传列表

    如果传入列表参数,Beautiful Soup会将与列表中任一元素匹配的内容返回。下面代码找到文档中所有标签和标签

    1. soup.find_all(["a", "b"])
    2. # [The Dormouse's story,

    keyword 参数

    如果一个指定名字的参数不是搜索内置的参数名,搜索时会把该参数当作指定名字tag的属性来搜索,如果包含一个名字为 id 的参数,Beautiful Soup会搜索每个tag的”id”属性。

    1. soup.find_all(id='link2')
    2. # [Lacie]
    3. import re
    4. # 超链接包含elsie标签
    5. print(soup.find_all(href=re.compile("elsie")))
    6. # [Elsie]
    7. # 以The作为开头的字符串
    8. print(soup.find_all(text=re.compile("^The")))
    9. # ["The Dormouse's story", "The Dormouse's story"]
    10. # class选择器包含st的节点
    11. print(soup.find_all(class_=re.compile("st")))

    搜索指定名字的属性时可以使用的参数值包括字符串、正则表达式、列表、True。

    下面的例子在文档树中查找所有包含 id 属性的tag,无论 id 的值是什么:

    1. soup.find_all(id=True)
    2. # [Elsie,

    使用多个指定名字的参数可以同时过滤tag的多个属性:

    1. soup.find_all(href=re.compile("elsie"), id='link1')
    2. # [three]

    在这里我们想用 class 过滤,不过 class 是 python 的关键词,这怎么办?加个下划线就可以

    1. print(soup.find_all("a", class_="sister"))
    2. '''
    3. ]
    4. '''

    通过 find_all() 方法的 attrs 参数定义一个字典参数来搜索包含特殊属性的tag:

    1. data_soup.find_all(attrs={"data-foo": "value"})
    2. # [
      foo!
      ]

    注意:如何查看条件id和class同时存在时的写法

    1. print(soup.find_all('b', class_="story", id="x"))
    2. print(soup.find_all('b', attrs={"class":"story", "id":"x"}))

    text 参数

    通过 text 参数可以搜搜文档中的字符串内容。与 name 参数的可选值一样,text 参数接受字符串、正则表达式 、列表、True。

    1. import re
    2. print(soup.find_all(text="Elsie"))
    3. # ['Elsie']
    4. print(soup.find_all(text=["Tillie", "Elsie", "Lacie"]))
    5. # ['Elsie', 'Lacie', 'Tillie']
    6. # 只要包含Dormouse就可以
    7. print(soup.find_all(text=re.compile("Dormouse")))
    8. # ["The Dormouse's story", "The Dormouse's story"]

    limit 参数

    find_all() 方法返回全部的搜索结构,如果文档树很大那么搜索会很慢。如果我们不需要全部结果,可以使用 limit 参数限制返回结果的数量。效果与SQL中的limit关键字类似,当搜索到的结果数量达到 limit 的限制时,就停止搜索返回结果。

    1. print(soup.find_all("a",limit=2))
    2. print(soup.find_all("a")[0:2])
    3. '''
    4. '''

    find()

    find(name , attrs , recursive , string , **kwargs )

    find_all() 方法将返回文档中符合条件的所有tag,尽管有时候我们只想得到一个结果。比如文档中只有一个标签,那么使用 find_all() 方法来查找标签就不太合适,使用 find_all 方法并设置 limit=1 参数不如直接使用 find() 方法。下面两行代码是等价的:

    1. soup.find_all('title', limit=1)
    2. # [The Dormouse's story]
    3. soup.find('title')
    4. # The Dormouse's story

    唯一的区别是 find_all() 方法的返回结果是值包含一个元素的列表,而 find() 方法直接返回结果。

    find_all() 方法没有找到目标是返回空列表,find() 方法找不到目标时,返回 None。

    1. print(soup.find("nosuchtag"))
    2. # None

    soup.head.title 是 tag的名字方法的简写。这个简写的原理就是多次调用当前tag的 find() 方法:

    1. soup.head.title
    2. # The Dormouse's story
    3. soup.find("head").find("title")
    4. # The Dormouse's story

    find_parents() 和 find_parent()

    1. a_string = soup.find(text="Lacie")
    2. print(a_string) # Lacie
    3. print(a_string.find_parent())
    4. print(a_string.find_parents())
    5. print(a_string.find_parent("p"))
    6. '''
    7. Once upon a time there were three little sisters; and their names were
    8. Lacie and
    9. and they lived at the bottom of a well.
    10. '''

    1.4 beautifulsoup的css选择器

    我们在写 CSS 时,标签名不加任何修饰,类名前加点,id名前加 #,在这里我们也可以利用类似的方法来筛选元素,用到的方法是 soup.select(),返回类型是 list

    通过标签名查找

    1. print(soup.select("title")) #[The Dormouse's story]
    2. print(soup.select("b")) #[The Dormouse's story]

    通过类名查找

    1. print(soup.select(".sister"))
    2. '''
    3. '''

    id名查找

    1. print(soup.select("#link1"))
    2. # [Elsie]

    组合查找

    组合查找即和写 class 文件时,标签名与类名、id名进行的组合原理是一样的,例如查找 p 标签中,id 等于 link1的内容,二者需要用空格分开

    1. print(soup.select("p #link2"))

    直接子标签查找

    1. print(soup.select("p > #link2"))
    2. # [Lacie]

    查找既有class也有id选择器的标签

    a_string = soup.select(".story#test")

    查找有多个class选择器的标签

    a_string = soup.select(".story.test")

    查找有多个class选择器和一个id选择器的标签

    a_string = soup.select(".story.test#book")

    属性查找

    查找时还可以加入属性元素,属性需要用中括号括起来,注意属性和标签属于同一节点,所以中间不能加空格,否则会无法匹配到。

    1. print(soup.select("a[href='http://example.com/tillie']"))

    select 方法返回的结果都是列表形式,可以遍历形式输出,然后用 get_text() 方法来获取它的内容:

    1. for title in soup.select('a'):
    2. print (title.get_text())
    3. '''
    4. Elsie
    5. Lacie
    6. Tillie
    7. '''

    二、xpath解析

    1.1 xpath安装与使用

    安装

    • 安装lxml库

      pip install lxml -i pip源

    1.2 解析流程与使用

    解析流程

    • 实例化一个etree的对象,把即将被解析的页面源码加载到该对象

    • 调用该对象的xpath方法结合着不同形式的xpath表达进行标签定位和数据提取

    使用

    • 导入lxml.etree

      from lxml import etree

    • etree.parse()

      解析本地html文件

      html_tree = etree.parse('XX.html')

    • etree.HTML()(建议)

      解析网络的html字符串

      html_tree = etree.HTML(html字符串)

    • html_tree.xpath()

      使用xpath路径查询信息,返回一个列表

    注意:如果lxml解析本地HTML文件报错可以安装如下添加参数。

    1. parser = etree.HTMLParser(encoding="utf-8")
    2. selector = etree.parse('./lol_1.html',parser=parser)
    3. result=etree.tostring(selector)

    1.3 xpath语法

    XPath 是一门在 XML 文档中查找信息的语言。XPath 用于在 XML 文档中通过元素和属性进行导航。

    路径表达式

    表达式描述
    /从根节点选取。
    //从匹配选择的当前节点选择文档中的节点,而不考虑它们的位置。
    ./当前节点再次进行xpath
    @选取属性。

    实例

    在下面的表格中,我们已列出了一些路径表达式以及表达式的结果:

    路径表达式结果
    /html选取根元素 bookstore。注释:假如路径起始于正斜杠( / ),则此路径始终代表到某元素的绝对路径!
    //li选取所有li 子元素,而不管它们在文档中的位置。
    //ul//a选择属于 ul元素的后代的所有 li元素,而不管它们位于 ul之下的什么位置。
    节点对象.xpath('./div')选择当前节点对象里面的第一个div节点

    谓语(Predicates)

    谓语用来查找某个特定的节点或者包含某个指定的值的节点。

    谓语被嵌在方括号中。

    实例

    在下面的表格中,我们列出了带有谓语的一些路径表达式,以及表达式的结果:

    路径表达式结果
    /ul/li[1]选取属于 ul子元素的第一个 li元素。
    /ul/li[last()]选取属于 ul子元素的最后一个 li元素。
    /ul/li[last()-1]选取属于 ul子元素的倒数第二个 li元素。
    //ul/li[position()<3]选取最前面的两个属于 ul元素的子元素的 li元素。
    //a[@title]选取所有拥有名为 title的属性的 a元素。
    //a[@title='xx']选取所有 a元素,且这些元素拥有值为 xx的 title属性。
    //a[@title>10] > < >= <= !=选取 a元素的所有 title元素,且其中的 title元素的值须大于 10。
    /bookstore/book[price>35.00]/title选取 bookstore 元素中的 book 元素的所有 title 元素,且其中的 price 元素的值须大于 35.00。

    选取未知节点

    XPath 通配符可用来选取未知的 XML 元素。

    通配符描述
    *匹配任何元素节点。 一般用于浏览器copy xpath会出现
    @*匹配任何属性节点。
    node()匹配任何类型的节点。

    实例

    在下面的表格中,我们列出了一些路径表达式,以及这些表达式的结果:

    路径表达式结果
    /ul/*选取 bookstore 元素的所有子元素。
    //*选取文档中的所有元素。
    //title[@*]选取所有带有属性的 title 元素。
    //node()获取所有节点

    选取若干路径

    通过在路径表达式中使用“|”运算符,您可以选取若干个路径。

    实例

    在下面的表格中,我们列出了一些路径表达式,以及这些表达式的结果:

    路径表达式结果
    //book/title | //book/price选取 book 元素的所有 title 和 price 元素。
    //title | //price选取文档中的所有 title 和 price 元素。
    /bookstore/book/title | //price选取属于 bookstore 元素的 book 元素的所有 title 元素,以及文档中所有的 price 元素。

    逻辑运算

    查找所有id属性等于head并且class属性等于s_down的div标签

    //div[@id="head" and @class="s_down"]

    选取文档中的所有 title 和 price 元素。

    //title | //price

    注意: “|”两边必须是完整的xpath路径

    属性查询

    查找所有包含id属性的div节点

    //div[@id]

    查找所有id属性等于maincontent的div标签

    //div[@id="maincontent"]

    查找所有的class属性

    //@class

    //@attrName

    //li[@name="xx"]//text()  # 获取li标签name为xx的里面的文本内容

    获取第几个标签 索引从1开始

    1. tree.xpath('//li[1]/a/text()') # 获取第一个
    2. tree.xpath('//li[last()]/a/text()') # 获取最后一个
    3. tree.xpath('//li[last()-1]/a/text()') # 获取倒数第二个

    模糊查询

    查询所有id属性中包含he的div标签

    //div[contains(@id, "he")]

    查询所有id属性中包以he开头的div标签

    //div[starts-with(@id, "he")]

    内容查询

    查找所有div标签下的直接子节点h1的内容

    //div/h1/text()

    属性值获取

    //div/a/@href   获取a里面的href属性值

    获取所有

    1. //* #获取所有
    2. //*[@class="xx"] #获取所有class为xx的标签

    获取节点内容转换成字符串

    1. c = tree.xpath('//li/a')[0]
    2. result=etree.tostring(c, encoding='utf-8')
    3. print(result.decode('UTF-8'))

  • 相关阅读:
    创建自己的cli
    redis集群最少使用三个主节点和使用16384个槽以及主节点数量不超过1000的原因
    PPT NO.2 ​插入透明校徽
    kafka(一:分区数据不均衡(数据倾斜),分区分配策略)
    Raiden Network(二)—— Mediated transfers(多跳支付里的中介传输)
    Kotlin编程实战——类与对象(05)
    java中stringbuffer用法:StringBuffer实现高效字符串拼接
    【自然语言处理(NLP)实战】LSTM网络实现中文文本情感分析(手把手与教学超详细)
    实现退出确认和销毁所有活动
    分类预测 | MATLAB实现WOA-CNN-BiGRU鲸鱼算法优化卷积双向门控循环单元数据分类预测
  • 原文地址:https://blog.csdn.net/qq_38196449/article/details/139551051