Python爬虫理论

2023-10-29

目录

 

1. 解析HTML格式

2.解析JSON格式

3.解析二进制格式

4. 实战


1. 解析HTML格式

解析HTML格式主要有以下几种方法,我们在之后的学习中重点关注前两种:

1)lxml库:第三方库,支持HTML和XML格式解析,支持XPath解析方式,解析效率非常高。

2)BeautifulSoup库:第三方库,支持HTML/XML的解析,支持Python标准库中的HTML解析器,也支持 lxml的 XML解析器。

3)Pyquery库:第三方库,相当于jQuery的python实现,可以用于解析HTML网页等。它的语法与jQuery几乎完全相同。

4)HtmlParser,XML:python自带的,用于解析Html和XML。

  • lxml 

1)XPath基础

XPath, XML 路径语言,用于在XML 文档中查找信息,同样也适用于HTML 文档的搜索。参考文档

XML:可扩展标记语言(eXtensibleMarkupLanguage)

HTML:超文本标记语言(HyperText Markup Language)

 XML和HTML形式上差不太多,都是由一对对层级嵌套的标签构成,如<a>...</a>,标签内部可以有属性、文本等。XML的标签名称可以自己随意取,而HTML的标签大多都是固定的,比如<a>为链接标签,<li>为列表标签等。

 

在XPath中,有七种类型的节点:文档(根)、元素、属性、文本、命名空间、处理指令、注释节点。XML 文档是被作为节点树来对待的。树的根被称为文档节点或者根节点。

 节点关系:

父(Parent) -- book

子(Children) -- title

同胞(Sibling) -- year

先辈(Ancestor) -- bookstore

后代(Descendant) -- price

2) 常用路径表达式

 

XML实例1:

book.xml文件内容:

<?xml version="1.0" encoding="ISO-8859-1"?>
<bookstore>
<book>
  <title lang="eng">Harry Potter</title>
  <price>29.99</price>
</book>
<book>
  <title lang="ch">Learning XML</title>
  <price>39.95</price>
</book>
</bookstore>

from lxml import etree
xml=etree.parse('./book.xml',etree.XMLParser())
result=etree.tostring(xml)
print(xml.xpath("/bookstore/book[1]"))
print(xml.xpath("/bookstore/book[1]/title/text()"))
#[<Element book at 0x1deba754648>](列表)
#[‘Harry Potter’](文本内容)

3)通配符(用来选取未知的XML元素) 

 XML实例2:

book.xml文件内容:

<?xml version="1.0" encoding="ISO-8859-1"?>
<bookstore>
<book>
  <title lang="eng">Harry Potter</title>
  <price>29.99</price>
</book>
<book>
  <title lang="ch">Learning XML</title>
  <price>39.95</price>
</book>
</bookstore>

from lxml import etree
xml=etree.parse('./book.xml',etree.XMLParser())
result=etree.tostring(xml)
print(xml.xpath("/bookstore/*"))
print(xml.xpath("//*"))
#| 是逻辑或 若前一个条件为真时 后一个就不看了 短路效应
print(xml.xpath("/bookstore/title|//book/price"))
print(xml.xpath("//price|title"))
print(xml.xpath("//title|price"))
print(xml.xpath("/bookstore/book/title|//price"))

 

 

HTML实例1:

test.html文件内容:

<div>
    <ul>
         <li id="flask" 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>
from lxml import etree

html = etree.parse('./test.html', etree.HTMLParser())
result = html.xpath('//a')
print(result)    	#1
result = html.xpath('//a/@href')
print(result)  	#2
result = html.xpath('//a[@href]')
print(result)  	#2
result = html.xpath('//a[@href="link4.html"]/text()')
print(result) 	#3
result = html.xpath('//li[contains(@class, "item-1")]')
print(result) 	#4
result = html.xpath('//@class')
print(result) 	#5

  • BeautifulSoup

BeautifulSoup是python的HTML/XML解析库,最主要的功能是从网页抓取数据。

1)它提供了很多函数,用于处理页面的导航、搜索、修改分析树等功能,通过解析文档为用户提供需要抓取的数据。

2)它的代码简单,不需要多少代码就可以写出一个完整的应用程序。

3)它自动将输入文档转换为Unicode编码,输出文档为utf-8编码。

4)它在解析时依赖解析器,支持Python 标准库中的HTML 解析器及第三方解析器(比如 lxml)。由于lxml解析器功能强大,速度快,通常推荐使用lxml解析器 

 

1) 基本对象 

BeautifulSoup将复杂HTML文档解析为树形结构对象进行处理,每个节点为一个对象(所有对象可以归纳为以下4种:Tag , NavigableString, BeautifulSoup, Comment),可以方便地获取指定标签的对应属性,将全部页面转变为字典或者数组,相对于正则表达式的方式,可以简化处理过程。

2)操作方法 

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

节点选择器:通过遍历文档树,获取标签名或属性信息(如soup.article.li,soup.p.attrs)。

方法选择器:通过搜索文档树,使用find等方法查找相应内容(如soup.find_all(‘li’) )。

CSS选择器—通过搜索文档树,采用CSS格式使用select方法选取特定元素(如soup.select(a[class=‘xxx’]))

节点选择器:

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>;
    </p>
        and they lived at the bottom of a well.
    <p class="story">...</p>
</body>
'''

from bs4 import BeautifulSoup
soup = BeautifulSoup(html, 'lxml')
print("-----1.节点选择器(读取字符串soup)-------")
print("soup.p------------")
print(soup.p)  # 选择节点, 第一个匹配的节点 <p class="title" name="dromouse"><b>The Dormouse's story</b></p>
print("soup.p.name------------")
print(soup.p.name)  # 节点名称 p
print("soup.p.attrs------------")
print(soup.p.attrs)  # 节点属性 {'class': ['title'], 'name': 'dromouse'}
print("soup.p.attrs['class']------------")
print(soup.p.attrs['class'])  # 特定属性 ['title']
print("soup.p.string------------")
print(soup.p.string)   # 节点的文本内容 The Dormouse's story
print("soup.p.b------------")
print(soup.p.b)  # 嵌套选择 <b>The Dormouse's story</b>
print("soup.p.contents------------")
print(soup.p.contents)  # 直接子节点,列表类型 [<b>The Dormouse's story</b>]
print("soup.p.parent------------")
print(soup.p.parent)  # 直接父节点<body> <p.../p> </body>
print("list(soup.p.children)------------")
print(list(soup.p.children))  # 直接子节点,生成器类型 [<b>The Dormouse's story</b>]
print("list(soup.p.descendants)------------")
print(list(soup.p.descendants))  # 所有子孙节点 [<b>The Dormouse's story</b>, "The Dormouse's story"]
print("list(soup.p.parents)------------")
print(list(soup.p.parents))  # 所有祖先节点[<body>...</body>,  <html><head>...</body></html>,<html><head>...</body></html>]
print("list(soup.a.next_siblings)------------")
print(list(soup.a.next_siblings))  # 后面的兄弟节点  [',\n        ', <a class="sister" href="http://example.com/lacie" id="link2">Lacie</a>, ' and\n        ', <a class="sister" href="http://example.com/tillie" id="link3">Tillie</a>, ';\n    ']
print("list(soup.a.previous_siblings)------------")
print(list(soup.a.previous_siblings))  # 前面的兄弟节点 ['Once upon a time there were three little sisters; and their names were\n        ']
print("soup.a.next_sibling------------")
print(soup.a.next_sibling)  # 下一个兄弟节点 ,
print("soup.a.previous_sibling------------")
print(soup.a.previous_sibling)  # 上一个兄弟节点 Once upon a time there were three little sisters; and their names were  

方法选择器:

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

1)功能:返回所有匹配元素组成的列表。

2)主要参数:

name:可以传入字符串查找所有名字为 name 的tag,如‘b’ ;可以传入正则表达式作为参数,如re.compile(“^b”);可以传入列表参数,如[“a”, “b”];可以传入True(匹配所有tag,不会返回字符串节点)

recursive:是否需要搜索所有子孙节点,默认为True,表示会检索当前tag的所有子孙节点

keyword:把该参数当作指定名字tag的属性来搜索,如id=‘link2’或href=re.compile("elsie"), id='link1’

limit:当结果到达 limit 值时停止搜索,如limit=3,只返回前3个元素

注意:如果想用class做过滤,但是 class 是 python 的关键词,这时需要在class后加个下划线,如soup.find_all("a", class_=“title")

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

功能:返回第一个匹配的元素,其余同find_all。

find_parents()和find_parent()

功能:前者返回所有祖先节点, 后者返回直接父节点

find_next_siblings()和find_next_sibling()

 功能:前者返回后面所有的兄弟节点, 后者返回后面第一个兄弟节点 

find_previous_siblings()和find_previous_sibling()

 功能:前者返回前面所有的兄弟节点, 后者返回前面第一个兄弟节点

find_all_next()和find_next()

 功能:前者返回节点后所有符合条件的节点,后者返回第一个符合条件的节点

find_all_previous()和find_previous()

功能:前者返回节点前所有符合条件的节点,后者返回第一个符合条件的节点

 

实例:

test.html内容:

<div>
    <ul>
         <li id="flask" 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>
print("-----2.方法选择器(读取文件soup2)-------")
htmlfile = open('./test.html', 'r', encoding='utf-8')
soup2 = BeautifulSoup(htmlfile.read(), 'lxml')
print("-----find():返回发现的第一个------------")
li = soup2.find('li')
print('find_li:',li) #find_li: <li class="item-0" id="flask"><a href="link1.html">first item</a></li>
print('li.text(返回标签的内容):',li.text) #li.text(返回标签的内容): first item
print('li.attrs(返回标签的属性):',li.attrs) #li.attrs(返回标签的属性): {'id': 'flask', 'class': ['item-0']} 字典形式
print('li.string(返回标签内容为字符串):',li.string) #li.string(返回标签内容为字符串): first item
li = soup2.find(id='flask')
print(li)  #<li class="item-0" id="flask"><a href="link1.html">first item</a></li>
# 因为class是python的保留关键字,所以无法直接查找class这个关键字。有两种方法可以进行class属性查询
# 第一种:在attrs属性用字典进行传递参数
find_class = soup2.find(attrs={'class':'item-1'})
print('findclass:',find_class) #findclass: <li class="item-1"><a href="link2.html">second item</a></li>
# 第二种:使用BeautifulSoup中的特别关键字参数class_
beautifulsoup_class_ = soup2.find(class_ = 'item-1')
print('BeautifulSoup_class_:',beautifulsoup_class_) #BeautifulSoup_class_: <li class="item-1"><a href="link2.html">second item</a></li>
print("-----find_all():返回发现的全部------------")
# find_all 查找所有
li_all = soup2.find_all('li')
for li in li_all:  #1...5(最后一个自动补齐了</li>)
	print('匹配到的li:',li)      #1.<li class="item-0" id="flask"><a href="link1.html">first item</a></li>。。。
	print('li的内容:',li.text)   #1.first item。。。
	print('li的属性:',li.attrs)  #1.{'id': 'flask', 'class': ['item-0']}。。。
# 一种灵活的使用方式
li_quick = soup2.find_all(attrs={'class':'item-1'})
for li in li_quick:
	print('灵活查找:',li)
#灵活查找: <li class="item-1"><a href="link2.html">second item</a></li>
#灵活查找: <li class="item-1"><a href="link4.html">fourth item</a></li>

CSS选择器:

 可以采用CSS的语法格式来筛选元素。

select() :

print("-----3.CSS选择器-------")
print(soup.select('title'))  # title标签 [<title>The Dormouse's story</title>]
print(soup.select("p:nth-of-type(3)"))  # 第三个p节点 [<p class="story">...</p>]
print(soup.select('body a'))  # body下的所有子孙a节点 [<a class="sister" href="http://example.com/elsie" id="link1"><!--Elsie--></a>, <a class="sister" href="http://example.com/lacie" id="link2">Lacie</a>, <a class="sister" href="http://example.com/tillie" id="link3">Tillie</a>]
print(soup.select('p > a'))  # 所有p节点下的所有a直接节点 [<a class="sister" href="http://example.com/elsie" id="link1"><!--Elsie--></a>, <a class="sister" href="http://example.com/lacie" id="link2">Lacie</a>, <a class="sister" href="http://example.com/tillie" id="link3">Tillie</a>]
print(soup.select('p > #link1'))  # 所有p节点下的id=link1的直接子节点 [<a class="sister" href="http://example.com/elsie" id="link1"><!--Elsie--></a>]
print(soup.select('#link1 ~ .sister'))  # id为link1的节点后面class=sister的所有兄弟节点 [<a class="sister" href="http://example.com/lacie" id="link2">Lacie</a>, <a class="sister" href="http://example.com/tillie" id="link3">Tillie</a>]
print(soup.select('#link1 + .sister'))  # id为link1的节点后面class=sister的第一个兄弟节点 [<a class="sister" href="http://example.com/lacie" id="link2">Lacie</a>]
print(soup.select('.sister'))  # class=sister的所有节点 [<a class="sister" href="http://example.com/elsie" id="link1"><!--Elsie--></a>, <a class="sister" href="http://example.com/lacie" id="link2">Lacie</a>, <a class="sister" href="http://example.com/tillie" id="link3">Tillie</a>]
print(soup.select('[class="sister"]'))  # class=sister的所有节点 [<a class="sister" href="http://example.com/elsie" id="link1"><!--Elsie--></a>, <a class="sister" href="http://example.com/lacie" id="link2">Lacie</a>, <a class="sister" href="http://example.com/tillie" id="link3">Tillie</a>]
print(soup.select("#link1"))  # id=link1的节点 [<a class="sister" href="http://example.com/elsie" id="link1"><!--Elsie--></a>]
print(soup.select("a#link1"))  # a节点,且id=link1的节点 [<a class="sister" href="http://example.com/elsie" id="link1"><!--Elsie--></a>]
print(soup.select('a[href]'))  # 所有的a节点,有href属性 [<a class="sister" href="http://example.com/elsie" id="link1"><!--Elsie--></a>, <a class="sister" href="http://example.com/lacie" id="link2">Lacie</a>, <a class="sister" href="http://example.com/tillie" id="link3">Tillie</a>]
print(soup.select('a[href="http://example.com/elsie"]'))  # 指定href属性值的所有a节点 [<a class="sister" href="http://example.com/elsie" id="link1"><!--Elsie--></a>]
print(soup.select('a[href^="http://example.com/"]')) # href属性以指定值开头的所有a节点 [<a class="sister" href="http://example.com/elsie" id="link1"><!--Elsie--></a>, <a class="sister" href="http://example.com/lacie" id="link2">Lacie</a>, <a class="sister" href="http://example.com/tillie" id="link3">Tillie</a>]
print(soup.select('a[href$="tillie"]'))  # href属性以指定值结尾的所有a节点 [<a class="sister" href="http://example.com/tillie" id="link3">Tillie</a>]
print(soup.select('a[href*=".com/el"]'))  # 支持正则匹配 [<a class="sister" href="http://example.com/elsie" id="link1"><!--Elsie--></a>]

 

2.解析JSON格式

json.dumps()和json.loads()是json格式处理函数。

json.loads():将已编码的json字符串解码为字典类型。

json.dumps():将Python数据类型列表(字典)转化为json字符串。

import json 
#json.dumps将字典转化为字符串 
dict1 = {"age": "18"} 
json_info = json.dumps(dict1) 
print("dict1的类型:"+str(type(dict1))) 	#dict
print("通过json.dumps()函数处理:") 
print(“json_info "+ json_info)     	#{"age": "18"} 
print("json_info的类型:"+str(type(json_info))) 	#str
dict2 = json.loads(json_info)
print("dict2的类型:"+str(type(dict2))) 			#dict
print(dict2) 						#{'age': '18'}

#URL请求-响应结果是json
url='http://httpbin.org/get”
r = requests.get(url)
result  = json.loads(r.text)

json.dump()和json.load()主要用来读写json文件函数。

#写文件
json_info = "{'age': '12'}"
file = open('1.json','w',encoding='utf-8')
json.dump(json_info,file)

#读文件
file = open('1.json','r',encoding='utf-8')
print(json.load(file))    	#{'age': '12'}

 

3.解析二进制格式

图片、音频、视频这些文件实际上都是由二进制码组成的。

import os
os.makedirs('./image/', exist_ok=True)
url = "https://www.python.org/static/img/python-logo.png"


#方法1 直接将远程数据下载到本地文件
from urllib.request import urlretrieve
urlretrieve(url, './image/img1.png')


#方法2 将响应结果以二进制形式写入到指定文件中
import requests 
r = requests.get(url)
with open('./image/img2.png', 'wb') as f:  
    f.write(r.content)

#方法3 相对内置的open()来说,codecs.open方法比较不容易在编码上出现问题,返回unicode编码
import urllib
import requests
import os
import codecs

bytes = urllib.request.urlopen(url)
f=codecs.open('./image/img3.png','wb')
f.write(bytes.read())
f.flush() 
f.close()

4. 实战

  • 爬取万方数据库文献摘要

输入指定关键词,分别爬取与该关键词相关的期刊、学位、会议论文的摘要、题目、作者等信息。

网址:http://www.wanfangdata.com.cn

完整项目

  • 爬取百度图片

指定搜索词,爬取与搜索词相关的图片。

网址:http://image.baidu.com

完整项目

  • 爬取搜狗图片

指定搜索词,爬取与搜索词相关的图片。

网址:https://pic.sogou.com/

完整项目

 

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Python爬虫理论 的相关文章

随机推荐

  • 输入函数input

    目录 函数介绍 基本使用 返回值类型转换 函数介绍 作用 接收来自用户的输入 返回值类型 同输入值类型 即str 值的存储 使用赋值符号 即对输入值进行存储 基本使用 变量 input 输入的提示语 name input 你的名字是什么 p
  • Node.js开发框架Express.js做一个简单的Web应用以及代码详解

    目录 Express js的主要特性 搭建 Node js 开发环境 Express js的使用方法 端口和URL的定义和作用 Express js的应用场景 注意 后续技术分享 第一时间更新 以及更多更及时的技术资讯和学习技术资料 将在公
  • [Python人工智能] 十二.循环神经网络RNN和LSTM原理详解及TensorFlow编写RNN分类案例

    从本专栏开始 作者正式开始研究Python深度学习 神经网络及人工智能相关知识 前一篇讲解了TensorFlow如何保存变量和神经网络参数 通过Saver保存神经网络 再通过Restore调用训练好的神经网络 本文将详细讲解循环神经网络RN
  • 开源Go语言数值算法库 An open numerical library purely based on Go programming language

    目录 关于 goNum https github com chfenger goNum 安装环境 安装方法 算法 许可证书 致谢 关于goNum goNum是一款完全以Go语言为基础的开源数值算法库 它可以使你像调用其它go函数一样使用其进
  • 使用CSS实现国际象棋棋盘

    系列文章目录 CSS3实现半透明边框 1 CSS3实现多重边框 2 CSS3如何调整背景图片大小 3 CSS3背景定位 4 CSS3设置条纹背景 5 使用CSS实现国际象棋棋盘 系列文章目录 前言 一 直角三角形 拼成正方形 二 使用步骤
  • c++:异常处理机制

    什么是异常 1 异常是一种程序控制机制 与函数机制独立和互补 函数是一种以栈结构展开的上下函数衔接的程序控制系统 而异常是另一种控制结构 它依附于栈结构 却可以同时设置多 个异常类型作为网捕条件 从而以类型匹配在栈机制中跳跃回馈 异常的设计
  • 用栈实现算数表达式求值(C语言(基础版))

    要求 输入以 为结束的算数表达式 包括 并求值 1 基础的栈结构书写 包括创建栈 判断栈是否为空 以及数据的压栈和出栈 可参考MOOC上陈越姥姥的相关数据结构课程 include
  • 红帽认证-RHCE

    目录 RHCE认证考的是 ansible的内容 重要信息配置 一 安装和配置Ansible 二 创建和运行Ansible 临时命命 三 安装软件包 四 使用RHEL系统角色 五 使用Ansible Galaxy 安装角色 六 创建使用角色
  • PostgreSQL解锁表

    PostgreSQL解锁表 一 查看单表加锁情况 二 取消一个长时间执行的sql 2 1 终止查询 但是连接留在原地 2 2 终止查询 同时杀死连接 三 查看锁表的详细信息 一 查看单表加锁情况 SELECT relation regcla
  • 转眼已走在成为程序猿的路上

    考完研 没有回家 直接找地方实习 虽不是太累可还是不能和上学相比 宿舍只剩孤身一人 转眼四年 加油吧 梦在前方
  • Pytorch raise NotImplementedError NotImplementedError

    我以为是我的网络搭建出错 结果竟是输入格式出错 如果出现这个问题 一般是forward这块出错 我是拼写出错 是forward 修改过后正常 还有可能是tap缩进的时候出错 def没有对齐 如果报错 可以先查查格式
  • 网络安全的基础知识

    1 什么是防火墙 什么是堡垒主机 什么是DMZ 防火墙是在两个网络之间强制实施访问控制策略的一个系统或一组系统 堡垒主机是一种配置了安全防范措施的网络上的计算机 堡垒主机为网络之间的通信提供了一个阻塞点 也可以说 如果没有堡垒主机 网络间将
  • kafka接收消费消息

    三 kafka接收消费消息 本节教程在window下演示 如果是在linux上学习的同学 可以将命令的前缀进行替换即可 比如 window 下的 命令前缀 bin windows kafka topics bat 则linux下的命令前缀为
  • 2023 年你应该知道的 10 个开源项目

    精心策划的 2023 年 GitHub 上最有趣的开发工具和项目列表 1 NetBeans NetBeans 是一个开源的集成开发环境 因其支持多种编程语言和平台而受到开发人员的欢迎 动图 2 OpenCV OpenCV 是一个用于图像和视
  • latex 矩阵_数学作业小工具 MATLAB 到 LaTex

    代码总是能解放生产力 在做数学作业的时候会发现用Word LaTex写矩阵感觉麻烦 同时有时也会因为各种各样的原因写错或者看错 所以我写了一个简单的小脚本可以把MATLAB里的矩阵变成LaTeX代码 直接放到Word或者LaTex编辑器就可
  • Spring Boot 是什么,有什么用。

    见 http www csdn net article a 2016 05 12 15838098 maven Java web bootstrap dataTable app开发QQ群 566862629 希望更多人一起帮助我学习 首先
  • 计算机视觉二 局部图像描述子 SIFT算法

    目录 一 SIFT算法 1 基本介绍 SIFT算法可以解决的问题 2 相关概念 1 尺度空间理论 2 高斯模糊 3 高斯金字塔 4 关键点检测 DOG 5 关键点方向分配 6 关键点描述 7 关键点匹配 二 STFL算法的实现 1 SIFT
  • MATLAB算法实战应用案例精讲-【数据分析】时序异常检测(附实战应用案例)

    目录 前言 算法原理 算法思想 时序异常检测方法 1 统计方法 2 预测方法 机器学习 lt
  • scrapy的深入使用:

    1 区分正常的debug和scrapy中的debug 2 scrapy shell的使用 scrapy shell是scrapy提供的一个终端工具 能够通过它查看scrapy中对象的属性和方法 以及测试xpath 使用方法 scrapy s
  • Python爬虫理论

    目录 1 解析HTML格式 2 解析JSON格式 3 解析二进制格式 4 实战 1 解析HTML格式 解析HTML格式主要有以下几种方法 我们在之后的学习中重点关注前两种 1 lxml库 第三方库 支持HTML和XML格式解析 支持XPat