前言
时间的关系,这篇文章只记录了相关库的使用,没有进行深入分析,各位看官请见谅(还是因为懒。。。。。)
requests使用
发送无参数的get请求
r = requests.get('http://httpbin.org/get')
print(r.text)
发送带参数的get请求
load = {'key1': 'value1', 'key2': 'value2'}
r = requests.get("http://httpbin.org/get",params = load)
print(r.url)
u'http://httpbin.org/get?key2=value2&key1=value1'
发送带参数的post请求
想要发送一些编码为表单形式的数据,表现形式非常像一个HTML表单。要实现这个,只需简单地传递一个字典给 data 参数。你的数据字典 在发出请求时会自动编码为表单形式。
load = {'key1': 'value1', 'key2': 'value2'}
r = requests.post("http://httpbin.org/post", data=load)
print(r.text)
{
...
"form": {
"key2": "value2",
"key1": "value1"
},
...
}
很多时候你想要发送的数据并非编码为表单形式的。如果你传递一个string而不是一个dict,那么数据会被直接发布出去。
例如,Github API 3接受编码为JSON的POST/PATCH数据:
>>> url = 'https://api.github.com/some/endpoint'
>>> load = {'some': 'data'}
>>> r = requests.post(url, data=json.dumps(load))
发送文件的post类型
这个相当于向网站上传一张图片,文档等操作,这时要使用files参数
url = 'http://httpbin.org/post'
files = {'file': open('touxiang.png', 'rb')}
r = requests.post(url, files=files)
定制headers,使用headers参数来传递
url = 'https://api.github.com/some/endpoint'
load = {'some': 'data'}
headers = {'content-type': 'application/json'}
r = requests.post(url, data=json.dumps(load), headers=headers)
编码类型
可以找出Requests使用了什么编码,并且能够改变它
r.encoding
'utf-8'
r.encoding = 'ISO-8859-1'
如果改变了编码,每当访问r.text时,Request都将会使用r.encoding的新值。
响应内容
响应状态码
r = requests.get(‘http://httpbin.org/get‘)
print(r.status_code)
响应头
print(r.headers)
也可以取到这个个别的响应头用来做一些判断,这里的参数是不区分大小写的
r.headers[‘Content-Type’]
r.headers.get(‘Content-Type’)
响应内容
# 被encoding解码后内容
r.text
# 以字节的方式访问请求响应体
r.content
获取响应中的cookies
r = requests.get('http://www.baidu.com')
r.cookies['BAIDUID']
也可以自已定义请求的COOKIES
url = 'http://httpbin.org/cookies'
cookies = {'cookies_are':'working'}
r = requests.get(url,cookies = cookies)
print(r.text)
{
"cookies": {
"cookies_are": "working"
}
}
设置超时时间
requests.get('http://github.com', timeout=1)
访问中使用session
先初始化一个session对象
s = requests.Session()
然后使用这个session对象来进行访问
r = s.post(url,data = user)
JSON相应内容
requests中也有一个内置的JSON解码器,助你处理JSON数据
r = requests.get('https://github.com/timeline.json')
r.json()
[{u'repository': {u'open_issues': 0, u'url': 'https://github.com/...
如果JSON解码失败,r.json就会抛出一个异常
原始响应内容
在罕见的情况下你可能想获取来自服务器的原始套接字响应,那么你可以访问r.raw 如果你确实想这么干,那请你确保在初始请求中设置了stream=True
>>> r = requests.get('https://github.com/timeline.json', stream=True)
>>> r.raw
<requests.packages.urllib3.response.HTTPResponse object at 0x101194810>
>>> r.raw.read(10)
'x1fx8bx08x00x00x00x00x00x00x03'
错误与异常
遇到网络问题(如:DNS查询失败、拒绝连接等)时,Requests会抛出一个ConnectionError 异常。
遇到罕见的无效HTTP响应时,Requests则会抛出一个 HTTPError 异常。
若请求超时,则抛出一个 Timeout 异常。
若请求超过了设定的最大重定向次数,则会抛出一个 TooManyRedirects 异常。
所有Requests显式抛出的异常都继承自 requests.exceptions.RequestException 。
Beautiful Soup使用方法
创建 beautifulsoup 对象
soup = BeautifulSoup(html)
另外,我们还可以用本地 HTML 文件来创建对象,例如
soup = BeautifulSoup(open('index.html'))
上面这句代码便是将本地 index.html 文件打开,用它来创建 soup 对象
下面我们来打印一下 soup 对象的内容,格式化输出
print(soup.prettify())
四大对象种类
Beautiful Soup将复杂HTML文档转换成一个复杂的树形结构,每个节点都是Python对象,所有对象可以归纳为4种:
- Tag
- NavigableString
- BeautifulSoup
- Comment
Tag
Tag 通俗点讲就是 HTML 中的一个个标签
打印标题标签内容
print(soup.title)
#<title>The Dormouse's story</title>
打印属性
print(soup.a.attrs)
{'href': '#main', 'class': ['skip-link', 'screen-reader-text']}
打印特定属性
print(soup.a['class'])
['skip-link', 'screen-reader-text']
或者
print(soup.a.get('href'))
#main
修改属性
soup.a['href']='#'
print(soup.a)
<a class="skip-link screen-reader-text" href="#">Skip to content</a>
删除属性
del soup.a['class']
print(soup.a)
<a href="#main">Skip to content</a>
NavigableString
用 .string 即可获取标签内部的文字,它的类型是一个NavigableString
print(soup.a.string)
Skip to content
BeautifulSoup
BeautifulSoup对象表示的是一个文档的全部内容.大部分时候,可以把它当作Tag对象,是一个特殊的Tag,我们可以分别获取它的类型,名称,以及属性
Comment
Comment对象是一个特殊类型的NavigableString对象,其实输出的内容仍然不包括注释符号,但是如果不好好处理它,可能会对我们的文本处理造成意想不到的麻烦。
遍历文档树
直接子节点
-
.contents
tag 的 .content 属性可以将tag的子节点以列表的方式输出
print(soup.a.contents) ['Skip to content']
-
.children
它返回的不是一个list,不过我们可以通过遍历获取所有子节点。
我们打印输出.children看一下,可以发现它是一个list生成器对象
所有子孙节点
.descendants
.contents和.children属性仅包含tag的直接子节点,.descendants属性可以对所有tag的子孙节点进行递归循环,和children类似,我们也需要遍历获取其中的内容。
for child in soup.descendants:
print("------->")
print(child)
节点内容
如果tag只有一个NavigableString类型子节点,那么这个tag可以使用.string得到子节点。如果一个tag仅有一个子节点,那么这个tag也可以使用.string方法,输出结果与当前唯一子节点的.string 结果相同。
如果tag包含了多个子节点,tag就无法确定,string方法应该调用哪个子节点的内容,.string的输出结果是None
多个内容
.strings获取多个内容,不过需要遍历获取
for string in soup.head.strings:
print("------->")
print(string)
.stripped_strings
输出的字符串中可能包含了很多空格或空行,使用.stripped_strings可以去除多余空白内容
for string in soup.head.stripped_strings:
print("------->")
print(string)
父节点
p=soup.p
print(p.parent.name)
全部父节点
.parents
通过元素的.parents属性可以递归得到元素的所有父辈节点,例如
p=soup.p
for parent in p.parents:
print('------->')
print(parent.name)
兄弟节点
兄弟节点可以理解为和本节点处在统一级的节点,.next_sibling属性获取了该节点的下一个兄弟节点,.previous_sibling则与之相反,如果节点不存在,则返回None
注意:实际文档中的tag的.next_sibling和.previous_sibling属性通常是字符串或空白,因为空白或者换行也可以被视作一个节点,所以得到的结果可能是空白或者换行
全部兄弟节点
通过.next_siblings和.previous_siblings属性可以对当前节点的兄弟节点迭代输出
前后节点
.next_element和.previous_element属性,与.next_sibling和.previous_sibling不同,它并不是针对于兄弟节点,而是在所有节点,不分层次
所有前后节点
通过.next_elements和.previous_elements的迭代器就可以向前或向后访问文档的解析内容,就好像文档正在被解析一样
搜索文档树
find_all( name , attrs , recursive , text , **kwargs )
find_all() 方法搜索当前tag的所有tag子节点,并判断是否符合过滤器的条件
- name 参数
name参数可以查找所有名字为name的tag,字符串对象会被自动忽略掉
- keyword 参数
如果一个指定名字的参数不是搜索内置的参数名,搜索时会把该参数当作指定名字tag的属性来搜索,如果包含一个名字为 id 的参数,Beautiful Soup会搜索每个tag的”id”属性
3.text 参数
通过 text 参数可以搜搜文档中的字符串内容.与 name 参数的可选值一样, text 参数接受 字符串 , 正则表达式 , 列表, True
4.limit 参数
find_all()方法返回全部的搜索结构,如果文档树很大那么搜索会很慢.如果我们不需要全部结果,可以使用limit参数限制返回结果的数量.效果与SQL中的limit关键字类似,当搜索到的结果数量达到 limit 的限制时,就停止搜索返回结果.
5.recursive 参数
调用tag的find_all()方法时,Beautiful Soup会检索当前tag的所有子孙节点,如果只想搜索tag的直接子节点,可以使用参数 recursive=False .
find( name , attrs , recursive , text , **kwargs )
它与find_all()方法唯一的区别是find_all()方法的返回结果是值包含一个元素的列表,而 find() 方法直接返回结果
find_parents()/find_parent()
find_all() 和 find() 只搜索当前节点的所有子节点,孙子节点等. find_parents() 和 find_parent() 用来搜索当前节点的父辈节点,搜索方法与普通tag的搜索方法相同,搜索文档搜索文档包含的内容
find_next_siblings()/find_next_sibling()
这2个方法通过 .next_siblings 属性对当 tag 的所有后面解析的兄弟 tag 节点进行迭代, find_next_siblings() 方法返回所有符合条件的后面的兄弟节点,find_next_sibling() 只返回符合条件的后面的第一个tag节点
find_previous_siblings()/find_previous_sibling()
这2个方法通过 .previous_siblings 属性对当前 tag 的前面解析的兄弟 tag 节点进行迭代, find_previous_siblings() 方法返回所有符合条件的前面的兄弟节点, find_previous_sibling() 方法返回第一个符合条件的前面的兄弟节点
find_all_next()/find_next()
这2个方法通过 .next_elements 属性对当前 tag 的之后的 tag 和字符串进行迭代, find_all_next() 方法返回所有符合条件的节点, find_next() 方法返回第一个符合条件的节点
find_all_previous() 和 find_previous()
这2个方法通过 .previous_elements 属性对当前节点前面的 tag 和字符串进行迭代, find_all_previous() 方法返回所有符合条件的节点, find_previous()方法返回第一个符合条件的节点
CSS选择器
我们在写CS 时,标签名不加任何修饰,类名前加点,id名前加#,在这里我们也可以利用类似的方法来筛选元素,用到的方法是soup.select(),返回类型是list
- 通过标签名查找
print soup.select('title')
#[<title>The Dormouse's story</title>]
print soup.select('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('b')
#[<b>The Dormouse's story</b>]
- 通过类名查找
print soup.select('.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>]
- 通过 id 名查找
print soup.select('#link1')
#[<a class="sister" href="http://example.com/elsie" id="link1"><!-- Elsie --></a>]
- 组合查找
组合查找即和写css文件时,标签名与类名、id名进行的组合原理是一样的,例如查找p 标签中,id等于link1的内容,二者需要用空格分开
print soup.select('p #link1')
#[<a class="sister" href="http://example.com/elsie" id="link1"><!-- Elsie --></a>]
直接子标签查找
print soup.select("head > title")
[The Dormouse's story ]
- 属性查找
查找时还可以加入属性元素,属性需要用中括号括起来,注意属性和标签属于同一节点,所以中间不能加空格,否则会无法匹配到。
print soup.select('a[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('a[href="http://example.com/elsie"]')
#[<a class="sister" href="http://example.com/elsie" id="link1"><!-- Elsie --></a>]
同样,属性仍然可以与上述查找方式组合,不在同一节点的空格隔开,同一节点的不加空格
print soup.select('p a[href="http://example.com/elsie"]')
#[<a class="sister" href="http://example.com/elsie" id="link1"><!-- Elsie --></a>]
以上的 select 方法返回的结果都是列表形式,可以遍历形式输出,然后用 get_text() 方法来获取它的内容。
soup = BeautifulSoup(html, 'lxml')
print type(soup.select('title'))
print soup.select('title')[0].get_text()
for title in soup.select('title'):
print title.get_text()