# 一、request 库
Requests 是一个常用的 HTTP 请求库,可以方便地向网站发送 HTTP 请求,并获取响应结果。这是官方的文档:request 官方文档(官方文档不太容易看懂😹)可以选择菜鸟教程里面的 requests 库讲解菜鸟教程。
| 属性或方法 | 说明 |
|---|---|
| apparent_encoding | 编码方式 |
| close() | 关闭与服务器的连接 |
| content | 返回响应的内容,以字节为单位 |
| cookies | 返回一个 CookieJar 对象,包含了从服务器发回的 cookie |
| elapsed | 返回一个 timedelta 对象,包含了从发送请求到响应到达之间经过的时间量,可以用于测试响应速度。比如 r.elapsed.microseconds 表示响应到达需要多少微秒。 |
| encoding | 解码 r.text 的编码方式 |
| headers | 返回响应头,字典格式 |
| history | 返回包含请求历史的响应对象列表(url) |
| is_permanent_redirect | 如果响应是永久重定向的 url,则返回 True,否则返回 False |
| is_redirect | 如果响应被重定向,则返回 True,否则返回 False |
| iter_content() | 迭代响应 |
| iter_lines() | 迭代响应的行 |
| json() | 返回结果的 JSON 对象 (结果需要以 JSON 格式编写的,否则会引发错误) |
| links | 返回响应的解析头链接 |
| next | 返回重定向链中下一个请求的 PreparedRequest 对象 |
| ok | 检查 “status_code” 的值,如果小于 400,则返回 True,如果不小于 400,则返回 False |
| raise_for_status() | 如果发生错误,方法返回一个 HTTPError 对象 |
| reason | 响应状态的描述,比如 “Not Found” 或 “OK” |
| request | 返回请求此响应的请求对象 |
| status_code | 返回 http 的状态码,比如 404 和 200(200 是 OK,404 是 Not Found) |
| text | 返回响应的内容,unicode 类型数据 |
| url | 返回响应的 URL |
# 二、Beautiful soup 库
Beautiful Soup 是一个可以从 HTML 或 XML 文件中提取数据的 Python 库。它能够通过你喜欢的转换器实现惯用的文档导航,查找,修改文档的方式.Beautiful Soup 会帮你节省数小时甚至数天的工作时间.
下表列出了主要的解析器,以及它们的优缺点:
| 解析器 | 使用方法 | 优势 | 劣势 |
|---|---|---|---|
| Python 标准库 | BeautifulSoup(markup, "html.parser") |
Python 的内置标准库执行速度适中文档容错能力强 | Python 2.7.3 or 3.2.2) 前 的版本中文档容错能力差 |
| lxml HTML 解析器 | BeautifulSoup(markup, "lxml") |
速度快文档容错能力强 | 需要安装 C 语言库 |
| lxml XML 解析器 | BeautifulSoup(markup, ["lxml-xml"])``BeautifulSoup(markup, "xml") |
速度快唯一支持 XML 的解析器 | 需要安装 C 语言库 |
| html5lib | BeautifulSoup(markup, "html5lib") |
最好的容错性以浏览器的方式解析文档生成 HTML5 格式的文档 | 速度慢不依赖外部扩展 |
将一段文档传入 BeautifulSoup 的构造方法,就能得到一个文档的对象,可以传入一段字符串或一个文件句柄.
from bs4 import BeautifulSoup | |
soup = BeautifulSoup(open("index.html")) | |
soup = BeautifulSoup("<html>data</html>") |
# Beautiful Soup 的 4 种对象
Beautiful Soup 将复杂 HTML 文档转换成一个复杂的树形结构,每个节点都是 Python 对象,所有对象可以归纳为 4 种: Tag , NavigableString , BeautifulSoup , Comment .
html_doc = """ | |
<html><head><title>The Dormouse's story</title></head> | |
<body> | |
<p class="title"><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> | |
""" |
以下代码块中 `#` 后面的内容一般代指输出结果
- Tag
Tag 对象与 XML 或 HTML 原生文档中的 tag 相同:
soup = BeautifulSoup('<b class="boldest">Extremely bold</b>') | |
tag = soup.b | |
type(tag) | |
# <class 'bs4.element.Tag'> |
tag 中最重要的属性: name 和 attributes
- Name: 每个 tag 都有自己的名字,通过
.name来获取:
soup.a.name | |
# a |
如果改变了 tag 的 name, 那将影响所有通过当前 Beautiful Soup 对象生成的 HTML 文档:
soup.a.name='你好' #只会修改第一个 a 标签 | |
print(soup.你好) | |
#< 你好 class="sister" href="http://example.com/elsie" id="link1">Elsie</ 你好 > |
- Attributes: 一个 tag 可能有很多个属性. tag
<a href="http://example.com/elsie" class="sister" id="link1">Elsie</a>,有一个 “class” 的属性,值为 “sister” . tag 的属性的操作方法与字典相同;可以使用.attrs老获取全部属性
soup.a['class'] | |
#['sister'] | |
soup.a['id'] | |
# link1 | |
soup.a.attrs | |
# {'href': 'http://example.com/elsie', 'class': ['sister'], 'id': 'link1'} |
tag的属性可以被添加,删除或修改.tag的属性操作方法与字典一样
以下方法 只针对遇到的第一个标签的属性
#新增 | |
soup.a['insert']='增加' | |
print(soup.a) | |
# <a class="sister" href="http://example.com/elsie" id="link1" insert="增加">Elsie</a> | |
#删除 | |
del soup.a['class'] | |
print(soup.a) | |
# <a href="http://example.com/elsie" id="link1">Elsie</a> | |
# 修改 | |
soup.a['class']='brother' | |
print(soup.a.attrs) | |
# {'href': 'http://example.com/elsie', 'class': 'brother', 'id': 'link1'} |
- NavigableString(可以遍历的字符串)
字符串常被包含在 tag 内.Beautiful Soup 用 NavigableString 类来包装 tag 中的字符串:
soup.a.string | |
# Elsie | |
type(soup.a.string) | |
<class 'bs4.element.NavigableString'> |
tag 中包含的字符串不能编辑,但是可以被替换成其它的字符串,用 replace_with () 方法
soup.a.string.replace_with('你好') | |
print(soup.a) | |
# <a class="sister" href="http://example.com/elsie" id="link1"> 你好 & lt;/a> |
- BeautifulSoup
BeautifulSoup 对象表示的是一个文档的全部内容。大部分时候,可以把它当作 Tag 对象,它支持 遍历文档树 和 搜索文档树中描述的大部分的方法。
- comment
Tag , NavigableString , BeautifulSoup 几乎覆盖了 html 和 xml 中的所有内容,但是还有一些特殊对象。容易让人担心的内容是文档的注释部分:
- Coment 对象是一个特殊类型的 NavigableString 对象。
- 如果标签内部的内容是注释,例如:
<!-- Elsie -->。那么该 NavigableSring 对象会转换成 Comment 对象,并且会把注释符号去掉。
markup = "<b><!--Hey, buddy. Want to buy a used parser?--></b>" | |
soup = BeautifulSoup(markup,'lxml') | |
print(soup.b.text+'输出为空') | |
#输出为空 | |
comment = soup.b.string | |
print(comment) | |
# Hey, buddy. Want to buy a used parser? | |
print(type(comment)) | |
# <class 'bs4.element.Comment'> |
# 遍历文档树
- 子结点
一个 Tag 可能包含多个字符串或其它的 Tag, 这些都是这个 Tag 的子节点.Beautiful Soup 提供了许多操作和遍历子节点的属性.
注意: Beautiful Soup 中字符串节点不支持这些属性,因为字符串没有子节点
- tag 的名字
操作文档树最简单的方法就是告诉它你想获取的 tag 的 name. 如果想获取
标签,只要用soup.head :
soup.head
# <head><title>The Dormouse's story</title></head>
soup.title
# <title>The Dormouse's story</title>
这是个获取 tag 的小窍门,可以在文档树的 tag 中多次调用这个方法。下面的代码可以获取 <body> 标签中的第一个 <b> 标签:
soup.body.b | |
# <b>The Dormouse's story</b> |
Tip:通过点取属性的方式只能获得当前名字的第一个tag:
如果想要得到所有的 <a> 标签,或是通过名字得到比一个 tag 更多的内容的时候,就需要用到 Searching the tree 中描述的方法,比如: find_all ()
soup.find_all('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>] | |
type(soup.find_all('a')) | |
# <class 'bs4.element.ResultSet'> |
- .contents 和 .children
tag 的 .contents 属性可以将 tag 的子节点以列表的方式输出:
soup.body.contents | |
# ['\n', <p class="title"><b>The Dormouse's story</b></p>, '\n', <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>, '\n', <p class="story">...</p>, '\n'] |
通过 tag 的 .children 生成器,可以对 tag 的子节点进行循环:
print(type(soup.body.children)) | |
# <class 'list_iterator'> 迭代器 | |
for child in soup.body.children: | |
print(child) | |
print(type(child)) | |
# < 第一行数据为空 > | |
# <class 'bs4.element.NavigableString | |
#<p class="title"><b>The Dormouse's story</b></p> | |
#<class 'bs4.element.Tag'> | |
# <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> | |
# <class 'bs4.element.Tag'> |
- .descendants
.contents 和 .children 属性仅包含 tag 的直接子节点。例如,
head_tag.contents
# [<title>The Dormouse's story</title>]
但是
.descendants 属性可以对所有 tag 的子孙节点进行递归循环