python爬虫-网页解析beautifulSoup&XPath

前面已经了解过,爬虫具有两大难点:一是数据的获取,二是采集的速度,因为会有很多的反爬(js)措施,导致爬虫并没有想象中那么容易。在python中,我们使用requests库作为核心,谷歌浏览器的检查工具作为辅助,学习如何编写爬虫。既然我们爬取的对象是网页,那自然少不了对网页的解析这一个关键阶段。所以我们接下来将学习解析王爷的python库。

BeautifulSoup

BeautifulSoup是一个可以从HTML或XML文件中提取数据的python库,它的使用方式相对于正则来说更加的简单方便,常常能够节省我们大量的时间。注意:BeautifulSoup类对html文档获取元素的方式能够让我们联想到JS,所以在这里我建议对BeautifulSoup和JS进行相辅相成的学习(复习)。
安装方式:pip install beautifulsoup4
另外也可以附加使用ipython这个终端模块帮助我们进行学习,
安装方式:pip install ipython

from bs4 import BeautifulSoup
soup = BeautifulSoup(html_doc,"解析器名称")
#也可以缺省第二个参数,但会产生警告,不过python解释器会自动帮你添加
#目前最好的解析器lxml

在bs4这个模块中导入BeautifulSoup这个类,用这个类初始化一个带有解析器的对象,BeautifulSoup解析网页需要指定一个可用的解析器,以下是几种主要的解析器:
在这里插入图片描述
由于这个解析的过程在大规模的爬取中是会影响到整个爬虫系统的速度的,所以推荐使用的是lxml,速度会快很多,而lxml需要单独安装:pip install lxml
然后在你的脚本中实例化一个对象

soup = BeautifulSoup(html_doc,'lxml') #指定解析器

需要注意的是:如果一段HTML或XML文档格式不正确的话,那么在不同的解析器中返回的结果可能是不一样的,所以要指定某一个解析器。

BeautifulSoup的四种节点对象

Tag

tag对象可以说是BeautifulSoup中最为重要的对象,通过BeautifulSoup来提取数据基本都围绕着这个对象进行操作。
tag的两个属性一个方法:name属性,Attributes属性,get_text()方法

from bs4 import BeautifulSoup
html_doc='''
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>test</title>
</head>
<body>
<div class="bannerbox">
    <p id="findX" class ="description">hello nice to meet you</p>
</div>
</body>
</html>
'''
html_doc = html_doc.rstrip()
soup = BeautifulSoup(html_doc,'lxml')
p = soup.p  #第一个p子树
print(p.name) #p
print(p['id'])  #findX
print(p['class']) #description
print(p.Attributes) #None
print(p.get_text()) #hello nice to meet you

Tag与遍历文档树-----数据结构中的树形结构
tag对象可以说是BeautifulSoup中最为重要的对象,通过BeautifulSoup来提取数据基本都围绕着这个对象进行操作。
首先,一个节点中是可以包含多个子节点和多个字符串的。例如html结点中包含着head和body结点。所以BeautifulSoup就可以将一个HTML的网页用这样一层层嵌套的结点来表示。!!注意:在html文档中的结点之间的空行也视为结点在这里插入图片描述

p = soup.p #获取一个子树对象

通过这种方法,可以获得一个目标子树,子树有以下属性/方法:

  1. contents和children:通过contents可以获取某个结点的所有(直接)子结点,包括里面的Navigablestring对象。获取的子节点是列表格式。而通过children同样的是获取某个节点的所有子节点,但是返回的是一个迭代器,这种方式会比列表格式更加节省内存。
  2. descendents:content和children获取的是某个结点的直接子结点,而无法获取子孙结点。通过descendents可以获得所有的子孙节点,返回的结构和children一样,需要迭代或转换类型使用。
  3. string和strings:我们常常会遇到需要获取某个节点的文本值得情况,如果这个结点中只有一个字符串,那么使用string就可以将其取出。而这个结点有多个字符串的时候,BeautifulSoupjiu’wu’fa’que’ding要取出哪个字符串,这时候需要用strings。使用stripped_strings可以将全是空白的行去掉。
  4. parent和parents:有时我们也需要去获取某个结点的父结点,使用parent返回直接父结点,使用parents则可以返回一直到根节点的所有父辈节点。
  5. 兄弟节点:next_sibling、previous_sibling、next_siblings、previous_siblings
  6. find_all():find_all()方法默认参数为标签名,查找子树中所有符合条件的结点,参数还可以为**‘标签名’,attrs={‘class’:‘sister’}),text=‘文本内容’**取符合条件的结点交集
  7. re.compile():导入re模块,结合正则表达式查找
  8. select():利用css选择器进行查找,例如soup.select(“div > p”)
NavigableString

NavagableString的意思是可便利的字符串,一般被标签包裹在其中的文本就是NavigableString格式。
from bs4 import BeautifulSoup
html_doc=’’’

test

hello nice to meet you

''' html_doc = html_doc.rstrip() soup = BeautifulSoup(html_doc,'lxml') p = soup.p print(p.name) print(p['id']) print(p['class']) print(p.Attributes) print(p.get_text()) # hello nice to meet you print(p.string) # hello nice to meet you print(type(p.get_text())) #
from lxml import etree
#lxml 是一个模块包 ,而etree是其中的一个模块
#该模块的HTML类可以帮助我们生成html语法树
html_doc = '''<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>test</title></head><body><div class="bannerbox"><p id="findX">hello nice to meet you</p></div></body></html>'''

page = etree.HTML(html_doc) #返回了html结点
#print(page.xpath('head'))
#print(page.xpath('.'))
head = page.xpath('head')[0]
print(head.xpath('/html/body'))#返回虚拟空间地址
print(head.xpath('@属性名') #返回属性值
谓语(条件)

谓语用来查找某个或某些特定节点或者包含某个指定值的结点。位于被嵌在方括号中。下面列出了带有谓语的一些路径表达式,以及表达式的结果:
在这里插入图片描述

通配符

利用通配符可以选取符合条件的未知节点
在这里插入图片描述

| :选取多个路径

通过在路径表达式中使用"|"运算符,您可以选取若干个路径。在下面的表格中,列出了一些路径表达式,以及这些表达式的结果:
在这里插入图片描述

获得结点值
  1. xpath(‘路径表达式/text()’) 调用text方法
  2. xpath(‘string(路径表达式)’)

以下是通过requests库和BeautifulSoup类进行的一个爬取小说案例

import requests
from bs4 import BeautifulSoup
url = "https://www.xs4.cc/dushizhiwozhendewudi/52316.html"
response = requests.get(url)
response.encoding = 'gbk'
html = response.text
soup = BeautifulSoup(html,'lxml')
div = soup.find_all('div',attrs={'id':'content'})[0]
content = ''.join([x.strip() for x in div.stripped_strings])
print(content)

返回了全书网某小说的第一章的第一个html网页小说内容

版权声明:本文为qq_44720314原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/qq_44720314/article/details/103105792