Python爬虫日记3——解析库(XPath,Beautiful Soup,pyquery)

1、XPath

from lxml import 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>
</ul>
</div>
'''
html = etree.HTML(text)     # 调用HTML类进行初始化,构造了一个XPath解析对像;HTML文本中的最后一个li节点是没有闭合的,但etree模块可以自动修正HTML文本
result = etree.tostring(html)       # 调用tostring方法输出修正后的HTML文本,但结果是bytes类型
print(result.decode('utf-8'))       # 利用decode()方法将其转成str类型

"""
经过处理之后,li节点标签被补全,还自动添加了body、html节点
"""
# Run:
"""
<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>
"""

节点

from lxml import etree

html = etree.parse('./test.html', etree.HTMLParser())       # 自己建立一个test.html的文件用于读取
result = etree.tostring(html)
#print(result.decode('utf-8'))
result = html.xpath('//li/a')   # 要选取所有li节点,可以使用//,直接加上节点名称即可;调用时直接使用xpath()方法即可
# 追加/a即选择了所有li节点的所有直接a子节点;//li用于选中所有li节点,/a用于选中li节点的所有直接子节点a
print(result)

result = html.xpath('//a[@href="link4.html"]/../@class')    # ..找父节点
print(result)

result = html.xpath('//a[@href="link4.html"]/parent::*/@class')     # 通过parent::来获取父节点
print(result)

"""
所有节点:用//开头的XPath规则来选取所有符合要求的节点
子节点:通过/或//可查找元素的子节点或子孙节点
注意:/和//的区别,其中/用于获取直接子节点,//用于获取子孙节点
"""

属性匹配

属性匹配是中括号加属性名和值来限定某个属性,如[@href="linkl.html ”]

# -*- coding=UTF-8 -*-
# 属性匹配
from lxml import etree

html = etree.parse('./test.html', etree.HTMLParser())
result = html.xpath('//li[@class="item-0"]')        # 加入[@class="item-0"],限制了节点的class属性为item-0
print(result)

# Run:
"""
[<Element li at 0x2bbe8156d88>, <Element li at 0x2bbe8156dc8>]
"""

文本获取

# -*- coding=UTF-8 -*-
# 文本获取
from lxml import etree

html = etree.parse('./test.html', etree.HTMLParser())
result = html.xpath('//li[@class="item-0"]/a/text()')        # 获取li节点内部的文本,有两种方式,一种是先选取节点再获取文本,另一种就是使用//
print(result)

result = html.xpath('//li[@class="item-0"]//text()')        # 获取li节点内部的文本,有两种方式,一种是先选取节点再获取文本,另一种就是使用//
print(result)

"""
要获取子孙节点内部的所有文本,可以直接用//加text()的方式,这样可以保证获取到最全面的文本信息,但是可能会夹杂一些换行符等特殊字符;
如果想获取某些特定子孙节点下的所有文本,可以先选取到特定的子孙节点,然后再调用text())方法获取其内部文本.
"""
# Run:
"""
['first item', 'fifth item']
['first item', 'fifth item', '\r\n']
"""

属性获取

用text()可以获取节点内部文本;用@符号可以获得节点属性,以列表形式返回。

# -*- coding=UTF-8 -*-
# 属性获取

from lxml import etree

html = etree.parse('./test.html', etree.HTMLParser())
result = html.xpath('//li/a/@href')        # 获取节点li下所有a节点的href属性
print(result)

# Run:
"""
"""

属性多值匹配

http://www.w3school.com.cn/xpath/xpath_operators.asp
应对某个节点的属性可能有多个值

# -*- coding=UTF-8 -*-
# 属性多值匹配

from lxml import etree

text = '<li class="li li-first"><a href="link.html">first item</a></li>'
html = etree.HTML(text)
# result = html.xpath('//li[@class="li"]/a/text()')        # 此时节点li的class属性有两个值li和li-first,之前的属性匹配已经不能获取
# 需要使用contains()函数
result = html.xpath('//li[contains(@class,"li")]/a/text()')		# contains()方法,第一个参数传入属性名称,第二个参数传入属性值,只要此属性包含传入的属性值,即可完成匹配
print(result)

多属性匹配

一种情况,就是根据多个属性确定一个节点,这时就需要同时匹配多个属性 此时可以使用运算符 and 来连接

# -*- coding=UTF-8 -*-
# 多属性匹配

from lxml import etree

text = '<li class="li li-first" name="item"><a href="link.html">first item</a></li>'
html = etree.HTML(text)

result = html.xpath('//li[contains(@class,"li") and @name="item"]/a/text()')     # 两个属性条件,使用and操作符连接
print(result)

按序选择

http://www.w3school.com. cn/xpath/xpath _functions.asp
.
last(),position()

# -*- coding=UTF-8 -*-
# 按序选择
# 有时候,在选择的时候某些属性可能同时匹配了多个节点,但是只想要其中的某个节点,
# 如第二个节点或者最后一个节点,这时可以利用中括号传入索引的方法获取特定次序的节点

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>
</ul>
</div>
'''
html = etree.HTML(text)
result = html.xpath("//li[1]/a/text()")     # 选中第一个li节点,中括号传入数字1即可
print(result)
result = html.xpath("//li[last()]/a/text()")     # 选中最后li节点,中括号传入last()即可
print(result)
result = html.xpath("//li[position()<3]/a/text()")     # 选中位置小于3的节点,即位置1和2,中括号传入position()<3即可
print(result)
result = html.xpath("//li[last()-2]/a/text()")     # 选中倒数第3个节点,中括号传入last()-2即可
print(result)

节点轴选择

轴的用法参考:http://www.w3school.com.cn/xpath/xpath_axes.asp
查询更多 XPath 的用法:http://www.w3school.com.cn/xpath/index.as
查询更多 Python lxml 库的用法:http://lxml.de/

2、Beautiful Soup

Beautiful Soup是Python的一个HTML或XML 的解析库。
Beautiful Soup提供一些简单的、Python 式的函数来处理导航、搜索、修改分析树等功能。它是一个工具箱,通过解析文档为用户提供需要抓取的数据,因为简单,所以不需要多少代码就可以写出一个完整的应用程序。
Beautiful Soup自动将输入文档转换为Unicode编码,输出文档转换为UTF-8编码。你不需要考虑编码方式,除非文档没有指定一个编码方式,这时你仅仅需要说明一下 原始编码方式就可以了。
Beautiful Soup已成为和lxml、html6lib -样出色的Python解释器,为用户灵活地提供不同的解析策略或强劲的速度。

基本用法

from bs4 import BeautifulSoup
... = BeautifulSoup(*, *)

# -*- coding=UTF-8 -*-
# 基本用法

# 声明变量html,这是一个HTML字符串,但是不完整,body和html节点没有闭合
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>
"""

from bs4 import BeautifulSoup
soup = BeautifulSoup(html, 'lxml')      # html参数传给BeautifulSoup对象,第二个参数为解析器类型(lxml),这样就完成了BeatifulSoup对象的初始化;且能自动更正格式
print(soup.prettify())      # 调用prettify()方法,可以把要解析的字符串以标准的HTML字符串缩进格式输出
print(soup.title.string)    # 输出HTML中title节点的文本内容,soup.title选中title节点,调用string属性得到文本

# Run:
"""
<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 class="sister" href="http://example.com/elsie" id="link1">
    <!-- Elsie -->
   </a>
   ,
   <a class="sister" href="http://example.com/lacie" id="link2">
    Lacie
   </a>
   and
   <a class="sister" href="http://example.com/tillie" id="link3">
    Tillie
   </a>
   ;
and they lived at the bottom of a well.
  </p>
  <p class="story">
   ...
  </p>
 </body>
</html>
The Dormouse's story

"""

节点选择器

1、提取信息

# -*- coding=UTF-8 -*-
# 节点选择器
# 提取信息

# 声明变量html,这是一个HTML字符串,但是不完整,body和html节点没有闭合
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>
"""

from bs4 import BeautifulSoup
soup = BeautifulSoup(html, 'lxml')      # html参数传给BeautifulSoup对象,第二个参数为解析器类型(lxml),这样就完成了BeatifulSoup对象的初始化;且能自动更正格式
print(soup.title)       # 打印输出title节点的选择结果,输出结果正是title加里面的文字内容
print(type(soup.title))     # 输出类型,是bs4.element.Tag类型,这是BeautifulSoup中的一个重要的数据结构
print(soup.title.string)    # 输出节点的文本内容
print(soup.head)        # 选择head节点,打印了节点加其内部的所有内容
print(soup.p)       # 选择head节点,打印了第一个p节点加其内部的所有内容
print(soup.p.string)    # 输出了第一个p节点的文本内容

#Run:
"""
<title>The Dormouse's story</title>
<class 'bs4.element.Tag'>
The Dormouse's story
<head><title>The Dormouse's story</title></head>
<p class="title" name="dromouse"><b>The Dormouse's story</b></p>
The Dormouse's story
"""

"""
上面演示了调用 string 属性来获取文本的值,那么如何获取节点属性的值呢?如何获取节点名称呢?
调用 name,attrs
"""
# (1)获取名称
print(soup.title.name)      # 获取名称
#(2)获取属性
print(soup.p.attrs)     # 调用attrs获取所有属性,attrs的返回形式是字典形式
print(soup.p.attrs['name'], '\n')     # 获取name属性,可以通过attrs['name']获得
# 或者
one = soup.p.attrs
print(one['class'], '\n')
# 或者
# 上面两个方法有点烦琐,还有一种更简单的获取方式:可以不用写attrs,直接在节点元素后面加中括号,传入属性名就可以获取属性值了
print(soup.p['class'])
print(soup.p['name'])

#  Run:
"""
title
{'class': ['title'], 'name': 'dromouse'}
dromouse

['title'] 

['title']
dromouse
"""
# (3)获取内容
# 可以利用 string 属性获取节点元素包含的文本内容,比如要获取第一个p节点的文本
print(soup.p.string)
# Run:
"""The Dormouse's story"""

2、嵌套选择

# -*- coding=UTF-8 -*-
# 嵌套选择

html = '''
<html><head><title>This Dormouse story</title></head>
<body>
'''

from bs4 import BeautifulSoup
soup = BeautifulSoup(html, 'lxml')
print(soup.head.title)      # 获取了head节点元素,可以继续调用head来选取其内部的head节点元素
print(type(soup.head.title))
print(soup.head.title.string)
# Run:
"""
<title>This Dormouse story</title>
<class 'bs4.element.Tag'>
This Dormouse story
"""

3、关联选择
子节点和子孙节点

①选取节点元素之后,如果想要获取它的直接子节点,可以调用 contents 属性;同样,可以调用 children 属性得到相应的结果,返回结果是生成器类型(用于for 循环输出相应的内容)
②要得到所有的子孙节点的话,可以调用 descendants 属性。返回结果是生成器(遍历输出)

父节点和祖先节点

要获取某个节点元素的父节点,可以调用 parent 属性;
获取所有的祖先节点,可以调用 parents 属性。(返回结果是生成器类型,遍历输出)

兄弟节点

next_sibling 和previous_sibling获取节点的下一个和上一个兄弟元素, next_siblings和previos_siblings 则分别返回所有前面和后面的兄弟节点的
成器

4、提取信息

想要获取关联元素节点的一些信息,比如文本、属性等。利用string和attrs

方法选择器

find_all(),find()

# -*- coding=UTF-8 -*-
# 方法选择器
# find_all,查询所有符合条件的元素
# find_all(name, attrs, recursive, text, **kwargs)

# (1)name 根据节点名查询元素
html = '''
<div class="panel">
<div class=" panel-heading">.
<h4>Hello</h4>
</div>
<div class="panel-body">
<ul class="list" id="list-1">
<li class="element">Foo</li>
<li class="element" >Bar</li>
<li class="element">Jay</li>
</ul>
<ul class="list list-small" id="list-2">
<li class="element">Foo</li>
<li class="element">Bar</li>
</ul>
</div>
</div>
'''
from bs4 import BeautifulSoup
soup = BeautifulSoup(html, 'lxml')
print(soup.find_all(name='ul'))     # 调用find_all()方法,传入name参数,其参数值为ul。即查询所ul节点,返回结果是列表类型,长度为2
print(type(soup.find_all(name='ul')[0]))        # 每个元素依然都是bs4.element.Tag类型

# 嵌套选择
for ul in soup.find_all(name='ul'):
    print(ul.find_all(name='li'))
    for li in ul.find_all(name='li'):   # 遍历每个li,获取文本
        print(li.string)

#Run:
"""
[<ul class="list" id="list-1">
<li class="element">Foo</li>
<li class="element">Bar</li>
<li class="element">Jay</li>
</ul>, <ul class="list list-small" id="list-2">
<li class="element">Foo</li>
<li class="element">Bar</li>
</ul>]
<class 'bs4.element.Tag'>
[<li class="element">Foo</li>, <li class="element">Bar</li>, <li class="element">Jay</li>]
Foo
Bar
Jay
[<li class="element">Foo</li>, <li class="element">Bar</li>]
Foo
Bar
"""
# -*- coding=UTF-8 -*-
# 方法选择器
# find_all,查询所有符合条件的元素
# find_all(name, attrs, recursive, text, **kwargs)

# (2)attrs 传入一些属性查询
html = '''
<div class="panel">
<div class=" panel-heading">.
<h4>Hello</h4>
</div>
<div class="panel-body">
<ul class="list" id="list-1" name="elements">
<li class="element">Foo</li>
<li class="element" >Bar</li>
<li class="element">Jay</li>
</ul>
<ul class="list list-small" id="list-2">
<li class="element">Foo</li>
<li class="element">Bar</li>
</ul>
</div>
</div>
'''
from bs4 import BeautifulSoup
soup = BeautifulSoup(html, 'lxml')
# 要查询id为list-1的节点,可以传入attrs={'id': "list-1"}的查询条件,结果是列表类型
print(soup.find_all(attrs={'id': "list-1"}))     # 调用find_all()方法,传入attrs参数,参数的类型是字典类型
print(soup.find_all(attrs={'name': "elements"}))

# 另一种方法
# 对于一些常用的属性,比如id和class等,我们可以不用attrs来传递。比如,要查询id=list-1的节点,可以直接传人id这个参数
print('\n')
print(soup.find_all(id='list-1'))

# Run:
"""
[<ul class="list" id="list-1" name="elements">
<li class="element">Foo</li>
<li class="element">Bar</li>
<li class="element">Jay</li>
</ul>]
[<ul class="list" id="list-1" name="elements">
<li class="element">Foo</li>
<li class="element">Bar</li>
<li class="element">Jay</li>
</ul>]


[<ul class="list" id="list-1" name="elements">
<li class="element">Foo</li>
<li class="element">Bar</li>
<li class="element">Jay</li>
</ul>]
"""
# text参数可用来匹配节点的文本,传入的形式可以是字符串,可以是正则表达式对象
import re

html = '''
<div class="panel">
<div class="panel-body"
<a>Hello, this is a link</a>
<a>Hello, this is a link,too</a>
</div>
</div>
'''
from bs4 import BeautifulSoup
soup = BeautifulSoup(html, 'lxml')
print(soup.find_all(text=re.compile('link')))   # compile()方法,这个方法可以将正则字符串编译成正则表达式对象,以便在后面的匹配中复用
print(soup.find(text=re.compile('link')))       # find()方法,返回的是单个元素,即第一个匹配的元素

#Run:
"""
['Hello, this is a link\n', 'Hello, this is a link,too']
Hello, this is a link
"""

CSS选择器

参考 http://www.w3school.com.cn/cssref/css_selectors.asp
使用css 选择器时,只需要调用 select()方法,传人相应的css 选择器即可

3、pyquery

像Beautiful Soup一样,初始化pyquery的时候,也需要传入HTML文本来初始一个 PyQuery对象。它的初始化方式有多种,比如直接传人字符串,传人URL,传人文件名,等等。

实例——字符串初始化、URL初始化、文件初始化

1-字符串初始化

字符串初始化

from pyquery import PyQuery as pq
html = """..."""
doc = pq(html)
print(doc('li'))
这里首先引人 PyQuery 这个对象,取别名为 pq ,然后声明了一个长 HTML 字符串,并将其当作参数传递给 PyQuery 类,这样就成功完成了初始化。
然后,将初始化的对象传入 css 选择器;在这个实例中,传入 li 节点,这样就可选择所有的 li 节点。

URL初始化

初始化的参数不仅可以字符串的形式传递,还可以传入 URL,此时只需要指定参数为url 即可。

2-URL初始化
# URL初始化
from pyquery import PyQuery as pq

doc = pq(url='https://cuiqingcai.com')
# PyQuery对象会首先请求这个URL,然后用得到的HTML内容完成初始,这其实就相当于用网页的源代码以字符串的形式传递给PyQuery类来初始化
print(doc('title'))


# 下面代码和上面作用相同
from pyquery import PyQuery as pq
import requests
doc = pq(requests.get('https://cuiqingcai.com').text)
print(doc('title'))

#Run:
"""
<title>静觅丨崔庆才的个人博客</title>&#13;

<title>静觅丨崔庆才的个人博客</title>&#13;
"""
3-文件初始化
# 文件初始化
from pyquery import PyQuery as pq

doc = pq(filename='demo.html')      # 要有一个html文件,指定参数filename
print(doc('title'))

基于CCS选择器

# 基本CSS选择器
html = '''
<div id="container">
<ul class="list">
<li class="item-0">first item</li>
<li class="item-1"><a href="link2 .html" >second item</a></li>
<li class="item-0 active"><a href="link3.html"><span class="bold">third item</span></a></li>
<li class="item-1 active"><a href="link4.html">fourth item</a></li>
<li class="item-0"><a href="link5.html">fifth item</a></li>
</ul>
</div>
'''
from pyquery import PyQuery as pq
doc = pq(html)      # 初始化PyQuery对象
print(doc('#container .list li'))   # 传入CSS选择器#container .list li, 意思是先选取id为container的节点,然后再选取其内部的class为list的节点内部的所有li节点
print(type(doc('#container .list li')))     # 类型输出

# Run:
"""
<li class="item-0">first item</li>
<li class="item-1"><a href="link2 .html">second item</a></li>
<li class="item-0 active"><a href="link3.html"><span class="bold">third item</span></a></li>
<li class="item-1 active"><a href="link4.html">fourth item</a></li>
<li class="item-0"><a href="link5.html">fifth item</a></li>

<class 'pyquery.pyquery.PyQuery'>
"""

查找节点——子节点、父节点、兄弟节点

子节点——find()方法、children()方法
# 查找节点
html = '''
<div id="container">
<ul class="list">
<li class="item-0">first item</li>
<li class="item-1"><a href="link2 .html" >second item</a></li>
<li class="item-0 active"><a href="link3.html"><span class="bold">third item</span></a></li>
<li class="item-1 active"><a href="link4.html">fourth item</a></li>
<li class="item-0"><a href="link5.html">fifth item</a></li>
</ul>
</div>
'''
from pyquery import PyQuery as pq
doc = pq(html)
items = doc('.list')    # 选取class为list的节点
print(type(items))      # 类型
print(items)

lis = items.find('li')      # 调用find()方法,传入CSS选择器,选取其内部为li的节点
print(type(lis))
print(lis)


lis = items.children('li')      # find()的查找范围是节点的所有子孙节点,如果只想查找子节点,可以用children()方法
print(type(lis))
print(lis)

lis = items.children('.active')     # 筛选出子节点中class为active的节点,向children()方法中传入CSS选择器.active
print(lis)

# Run:
"""
<class 'pyquery.pyquery.PyQuery'>
<ul class="list">
<li class="item-0">first item</li>
<li class="item-1"><a href="link2 .html">second item</a></li>
<li class="item-0 active"><a href="link3.html"><span class="bold">third item</span></a></li>
<li class="item-1 active"><a href="link4.html">fourth item</a></li>
<li class="item-0"><a href="link5.html">fifth item</a></li>
</ul>

<class 'pyquery.pyquery.PyQuery'>
<li class="item-0">first item</li>
<li class="item-1"><a href="link2 .html">second item</a></li>
<li class="item-0 active"><a href="link3.html"><span class="bold">third item</span></a></li>
<li class="item-1 active"><a href="link4.html">fourth item</a></li>
<li class="item-0"><a href="link5.html">fifth item</a></li>

<class 'pyquery.pyquery.PyQuery'>
<li class="item-0">first item</li>
<li class="item-1"><a href="link2 .html">second item</a></li>
<li class="item-0 active"><a href="link3.html"><span class="bold">third item</span></a></li>
<li class="item-1 active"><a href="link4.html">fourth item</a></li>
<li class="item-0"><a href="link5.html">fifth item</a></li>

<li class="item-0 active"><a href="link3.html"><span class="bold">third item</span></a></li>
<li class="item-1 active"><a href="link4.html">fourth item</a></li>

"""
父节点与祖父节点——parent()和parents()方法

parent()方法来获取某个节点的父节点

from pyquery import PyQuery as pq
doc = pq(html)
items = doc('.list')    # 用.list选取class为list的节点,然后调用parent()方法获取其父节点
container = items.parent()
print(type(container))      # 类型
print(container)

parents()方法获取某个节点的祖父节点

from pyquery import PyQuery as pq
doc = pq(html)
items = doc('.list')    # 用.list选取class为list的节点,然后调用parents()方法获取其祖父节点
parents = items.parents()
print(type(parents))      # 类型
print(parents)

要筛选某个祖父节点,向parents()方法传入CSS选择器,这样就可以返回祖父节点中符合CSS选择器的节点

from pyquery import PyQuery as pq
doc = pq(html)
items = doc('.list')    # 用.list选取class为list的节点,然后调用parents()方法获取其祖父节点
parent = items.parents('.wrap')		# 筛选class为wrap的节点
print(parent)
兄弟节点
from pyquery import PyQuery as pq
doc = pq(html)
li = doc('.list .item-0.active')    # 首先选择class为list的节点内部class为item-0和active的节点,即第三个li节点
print(li.siblings())		# 获取兄弟节点
print(li.siblings('.active')	# 向siblings()方法传入CSS选择器,筛选兄弟节点

遍历——items()方法

pyquery的选择结果可能是多个节点,也可能是单个节点,类型都PyQuery类型,并没有返回像Beautiful Soup那样的列表。
对于单个节点,可以直接打印输出,页而已转成字符串;
对于多个节点,需要遍历来获取;把每一个li节点进行遍历,调用items()方法;

from pyquery import PyQuery as pq
doc = pq(html)
lis = doc('li').items()		# 调用items()方法会得到一个生成器,遍历一下,逐个得到li节点对象
print(type(lis))
for li in lis:
	print(li, type(li))

获取信息——attr()、text()、html()

获取属性——attr()

提取到某个PyQuery类型的节点后,调用attr()方法来获取属性
print(a.attr('href'))
或者print(a.attr.href)

(当返回结果包含多个节点,要遍历一下获取属性)

from pyquery import PyQuery as pq 
doc = pq(html) 
a =doc('.item-0.active a')		# 首先选中class为item-0和active的li节点内的a节点
print(a.attr('href'))	# 调用attr()方法,传入属性名称,获取属性值
# 或者
print(a.attr.href)		# 调用attr属性来获取属性

获取文本——text()

调用text()方法可以获取节点内部的文本信息,但是或忽略掉节点内部包含的所有HTML,只返回纯文字内容。

from pyquery import PyQuery as pq 
doc = pq(html) 
a =doc('.item-0.active a')		# 首先选中class为item-0和active的li节点内的a节点
print(a)
print(a.text())	# 调用text()方法,获取内部的文本信息

获取节点内部的HTML文本——html()方法

from pyquery import PyQuery as pq 
doc = pq(html) 
li =doc('.item-0.active')		# 首先选中class为item-0和active的li节点
print(li)
print(li.html())	# 调用html()方法,返回li节点内的所有HTML文本

注意:

html ()方法返回的是 li 节点的内部 HTML 文本,而 text()则返回了所有 li 节点内部的纯文本,中间用一个空格分割开,即返回结果是一个字符串。

如果得到的结果是多个节点,并且想要获取每个节点的内部 HTML 文本,则需要遍历每个节点 。text ()方法不需要遍历就可以获取,它将所有节点取文本之后合并成一个字符串

节点操作——addClass()、removeClass()和attr()、text()、html()

pyquery 提供了一系列方法来对节点进行动态修改,比如为某个节点添加一个 class ,移除某个节点等

addClass()、removeClass()

addClass()、removeClass()

from pyquery import PyQuery as pq 
doc = pq(html) 
li =doc('.item-0.activ a')		# 首先选中class为item-0和active的li节点
print(li)
li.removeClass('active')	# 调用removeClass(),将li节点的active这个class移除
print(li)
li.addClass('active')		# 调用addClass(),添加class
print(li)
attr()、text()和html()

attr、text和html

用attr()方法对属性进行操作,text()和html()方法来改变节点内部的内容

html = '''
<ul calss="list">
<li class="items-0 active"><a href="link3.html"><span class="bold">third item</span></a></li>
</ul>
'''
from pyquery import PyQuery as pq
doc = pq(html)
li = doc('.items-0.active')
print(li)
li.attr('name', 'link')		# 调用attr()方法修改属性,第一个参数为属性名,第二个参数为属性值
print(li)
li.text('changed item')		# 调用text()方改变节点内部的内容
print(li)
li.html('<sapn>changed item</span>')	# 调用text()方改变节点内部的内容
print(li)
remove()

remove()方法就是移除

html = '''
<div class='wrap'>
	Hello world
<p>This is  a paragraph.</p>
</div>
'''
from pyquery import PyQuery as pq
doc = pq(html)
wrap = doc('.wrap')		# 选中class为warp的节点warp
print(wrap.text())

wrap.find('p').remove()		# 首先选中p节点,然后调用remove()方法将其移除
print(wrap.text())

伪类选择器

CSS选择器支持多种多样的伪类选择器,例如选择第一个节点、最后一个节点、奇偶数节点、包含某一文本的节点.

li = doc('li:first-child')		# 选择第一个li节点

li = doc('li:last-child')		# 选择最后一个li节点

li = doc('li:nth-child(2)')		# 选择第二个li节点

li = doc('li:gt(2)')		# 选择第三个li之后的li节点

li = doc('li:nth-child(2n)')		# 偶数位置的li节点

li = doc('li:contains(second)')		# 包含second文本的li节点

参考 pyquery 的官方文档:http://pyquery.readthedocs.io

参考书籍《Python 3网络爬虫开发实战》

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值