一、BeautifulSoup_demo
>>> from urllib.request import urlopen
>>> from bs4 import BeautifulSoup
>>> html = urlopen("http://www.pythonscraping.com/pages/page1.html")
>>> bs0bj = BeautifulSoup(html.read(),'lxml')
# 加不加 .read() 好像没差,但一次请求只能 read 一次
>>> bs0bj
A Useful Page
An Interesting Title
Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
#HTML节点附近的信息都可以提取
#获取bs0bj里面的title标签里的内容
>>> print(bs0bj.title)
A Useful Page
>>> print(bs0bj.html.body.h1)
An Interesting Title
>>> print(bs0bj.div)
Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
#可以用节点不同的方法调用到同一标签
>>> print(bs0bj.html.body.h1)
An Interesting Title
>>> print(bs0bj.body.h1)
An Interesting Title
>>> print(bs0bj.html.h1)
An Interesting Title
#get_text()去除标签获取纯文本内容
>>> print(bs0bj.html.body.h1.get_text())
An Interesting Title
解析器
解析器 | 使用方法 | 优劣势 |
---|---|---|
Python标准库 | BeautifulSoup(markup, "html.parser") | 速度适中,内置标准库 |
lxml HTML 解析器 | BeautifulSoup(markup, "lxml") , BeautifulSoup(markup, "xml") | 速度快,推荐这个 |
lxml XML 解析器 | BeautifulSoup(markup, ["lxml", "xml"]) | 速度快 |
html5lib | BeautifulSoup(markup, "html5lib") | 生成HTML5格式的文档 |
二、基本元素
- Tag 标签
- Name 标签名
- Attributes 属性
- NavigableString .string
- Comment 注释
三、遍历功能
(一)下行遍历
.contents
.children
.descendants
(二)上行遍历
.parent
.parents
(三)平行遍历
.next_sibling
.previous_sibling
.next_siblings
.previous_siblings
(四)find_all()
find_all(name, attrs, recursive, text, **kwargs)
find_all方法搜索当前tag的所有tag子节点,并判断是否符合过滤器的条件.这里有几个例子(返回的是列表):
soup.find_all("title")
[
soup.find_all("p", "title")
[
The Dormouse's story
]soup.find_all("a")
soup.find_all(id="link2")
[Lacie]
import re
soup.find(text=re.compile("sisters"))
u'Once upon a time there were three little sisters; and their names were\n'
1、name参数 (name)
name参数可以查找所有名字为 name 的 tag,字符串对象会被自动忽略掉
soup.find_all("title")
[The Dormouse's story ]
2、keyword参数 (attr, **kwargs)
搜索 tag 标签内指定属性的参数 ,如 id='link2', href='href=re.compile("elsie")。class属性要用 class_ ,因为 class 是类的关键字,见按 css 搜索。
soup.find_all(id='link2')
[Lacie]
soup.find_all(href=re.compile("elsie"))
[Elsie]
参数值可以为字符串,正则表达式,列表,True
下面的例子在文档树中查找所有包含 id 属性的tag,无论 id 的值是什么:
也可以这样
soup.find_all("a", {"class":"sister"})
a->标签,{}->标签的属性和其对应值
images = bs0bj.find_all("img", {"src":re.compile(".?")})
找出img标签里src属性里的所有东西re.compile(".?")匹配所有
使用多个指定名字的参数可以同时过滤tag的多个属性:
soup.find_all(href=re.compile("elsie"), id='link1')
[three]
对于一些其他属性,可以通过 find_all() 方法的 attrs 参数定义一个字典参数来搜索包含特殊属性的tag:
data_soup.find_all(attrs={"data-foo": "value"})
[foo!]
3、按CSS搜索 (attr, **kwargs)
class_ 参数同样接受不同类型的 过滤器 ,字符串,正则表达式,方法或 True :
也可以这样搜索查找:
soup.find_all("a", {"class":"sister"})
[Elsie,
Lacie,
Tillie]
4、text参数 (text)
通过 text 参数可以搜索文档中的字符串内容,与 name 参数的可选值一样,text 参数接受字符串,正则表达式,列表,True :
soup.find_all(text="Elsie")
[u'Elsie']
soup.find_all(text=["Tillie", "Elsie", "Lacie"])
[u'Elsie', u'Lacie', u'Tillie']
soup.find_all(text=re.compile("Dormouse"))
[u"The Dormouse's story", u"The Dormouse's story"]
当然也可以与其他参数混合使用来过滤 tag
soup.find_all("a", text="Elsie")
[Elsie]
5、limit参数 (limit)
该参数限制返回数量
6、recursive 参数 (recursive)
递归,循环参数。调用tag的 find_all() 方法时,Beautiful Soup会检索当前tag的所有子孙节点,如果只想搜索tag的直接子节点,可以使用参数 recursive=False
7、像调用find_all()一样调用tag
简写方法:
soup.find_all("a")
soup("a")
这两行代码也是等价的:
soup.title.find_all(text=True)
soup.title(text=True)
(五)find()
find(name, attrs, recursive, text, **kwargs)
find()只返回一个结果
下面两行代码是等价的:
>>> soup.find_all('title', limit=1)
[The Dormouse's story ]
>>> soup.find('title')
The Dormouse's story
唯一的区别是 find_all() 方法的返回结果是值包含一个元素的列表,而 find() 方法直接返回结果.
find_all() 方法没有找到目标是返回空列表, find() 方法找不到目标时,返回 None .
(六)CSS选择器
可以通过浏览器的审查元素的 copy selector 定位,Beautiful不支持Xpath
在 Tag 或 BeautifulSoup 对象的 .select() 方法中传入字符串参数,即可使用CSS选择器的语法找到tag:
soup.select("title")
[The Dormouse's story ]
soup.select("p nth-of-type(3)")
[...
]
通过CSS的类名查找:
通过tag的id查找:
soup.select("#link1")
[Elsie]
soup.select("a#link2")
[Lacie]
通过是否存在某个属性来查找:
通过属性的值来查找:
soup.select('a[href="http://example.com/elsie"]')
[Elsie]
soup.select('a[href^="http://example.com/"]')
[Elsie,
Lacie,
Tillie]
soup.select('a[href$="tillie"]')
[Tillie]
soup.select('a[href*=".com/el"]')
[Elsie]
(七)get_text()
如果只想得到tag中包含的文本内容,那么可以嗲用 get_text() 方法,这个方法获取到tag中包含的所有文版内容包括子孙tag中的内容,并将结果作为Unicode字符串返回:
>>> markup = '\nI linked to example.com\n'
>>> soup = BeautifulSoup(markup, 'lxml')
>>> soup.get_text()
'\nI linked to example.com\n'
>>> soup.i.get_text() #获取 i 标签内的文本
'example.com'
可以通过参数指定tag的文本内容的分隔符:
soup.get_text("|")
'\nI linked to |example.com|\n'
还可以去除获得文本内容的前后空白:
soup.get_text("|", strip=True)
'I linked to|example.com'
或者使用 .stripped_strings 生成器,获得文本列表后手动处理列表:
[text for text in soup.stripped_strings]
['I linked to', 'example.com']
(八)对 ResultSet 的处理
1、.get_text()
2、.get("href")
3、["href"]
3、.find('span').string
4、.text