python爬虫之BeautifulSoup

BeautifulSoup

一个灵活又方便的网页解析库,处理高效,支持多种解析器。利用它就不用编写正则表达式也能方便的实现网页信息的抓取。html

Beautiful Soup支持多种解析器, Python有默认的解析器,推荐安装lxml 解析器,效率高,速度快。前端

用法

from bs4 import BeautifulSoup

html = '''
<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>
'''
soup = BeautifulSoup(html,'lxml')
print(soup.prettify())
print(soup.title)
print(soup.title.name)
print(soup.title.string)
print(soup.title.parent.name)
print(soup.p)
print(soup.p["class"])
print(soup.a)
print(soup.find_all('a'))
print(soup.find(id='link3'))

标签选择器

print(soup.title)
print(soup.head)
print(soup.p)python

经过这种soup.标签名 咱们就能够得到这个标签的内容
这里有个问题须要注意,经过这种方式获取标签,若是文档中有多个这样的标签,返回的结果是第一个标签的内容,如上面咱们经过soup.p获取p标签,而文档中有多个p标签,可是只返回了第一个p标签内容正则表达式

获取名称

当咱们经过soup.title.name的时候就能够得到该title标签的名称,即titlespa

获取属性

print(soup.p.attrs['name'])
print(soup.p['name'])
上面两种方式均可以获取p标签的name属性值code

获取内容

print(soup.p.string)
结果就能够获取第一个p标签的内容:
The Dormouse's storyorm

嵌套选择

咱们直接能够经过下面嵌套的方式获取xml

print(soup.head.title.string)htm

子节点

1.contents对象

print(soup.p.contents)

结果是将p标签下的全部子标签存入到了一个列表中

2.children

经过children和经过contents获取的结果是同样的,可是不一样的地方是soup.p.children是一个迭代对象,而不是列表,只能经过循环的方式获取素有的信息

print(soup.p.children)
for i,child in enumerate(soup.p.children):
    print(i,child)

子孙节点

descendants

print(soup.descendants)

同时这种获取的结果也是一个迭代器

父节点和祖先节点

经过soup.a.parent就能够获取父节点的信息

经过list(enumerate(soup.a.parents))能够获取祖先节点,这个方法返回的结果是一个列表,会分别将a标签的父节点的信息存放到列表中,以及父节点的父节点也放到列表中,而且最后还会讲整个文档放到列表中,全部列表的最后一个元素以及倒数第二个元素都是存的整个文档的信息

兄弟节点

soup.a.next_siblings 获取后面的兄弟节点
soup.a.previous_siblings 获取前面的兄弟节点
soup.a.next_sibling 获取下一个兄弟标签
souo.a.previous_sinbling 获取上一个兄弟标签

标准选择器

find

find(name,attrs,recursive,text,**kwargs)
find返回的匹配结果的第一个元素

find_all

find_all(name,attrs,recursive,text,**kwargs)
能够根据标签名,属性,内容查找文档,返回全部

1.name
html='''
<div class="panel">
    <div class="panel-heading">
        <h4>Hello</h4>
    </div>
    <div class="panel-body">
        <ul class="list" id="list-1">
            <li class="element">Foo</li>
            <li class="element">Bar</li>
            <li class="element">Jay</li>
        </ul>
        <ul class="list list-small" id="list-2">
            <li class="element">Foo</li>
            <li class="element">Bar</li>
        </ul>
    </div>
</div>
'''
from bs4 import BeautifulSoup
soup = BeautifulSoup(html, 'lxml')
print(soup.find_all('ul'))
print(type(soup.find_all('ul')[0]))

同时咱们是能够针对结果再次find_all,从而获取全部的li标签信息

for ul in soup.find_all('ul'):
    print(ul.find_all('li'))
2.attrs

attrs能够传入字典的方式来查找标签,可是这里有个特殊的就是class,由于class在python中是特殊的字段,因此若是想要查找class相关的能够更改attrs={'class_':'element'}或者soup.find_all('',{"class":"element}),特殊的标签属性能够不写attrs,例如id

html='''
<div class="panel">
    <div class="panel-heading">
        <h4>Hello</h4>
    </div>
    <div class="panel-body">
        <ul class="list" id="list-1" name="elements">
            <li class="element">Foo</li>
            <li class="element">Bar</li>
            <li class="element">Jay</li>
        </ul>
        <ul class="list list-small" id="list-2">
            <li class="element">Foo</li>
            <li class="element">Bar</li>
        </ul>
    </div>
</div>
'''
from bs4 import BeautifulSoup
soup = BeautifulSoup(html, 'lxml')
print(soup.find_all(attrs={'id': 'list-1'}))
print(soup.find_all(attrs={'name': 'elements'}))
3.text

结果返回的是查到的全部的text='Foo'的文本

html='''
<div class="panel">
    <div class="panel-heading">
        <h4>Hello</h4>
    </div>
    <div class="panel-body">
        <ul class="list" id="list-1">
            <li class="element">Foo</li>
            <li class="element">Bar</li>
            <li class="element">Jay</li>
        </ul>
        <ul class="list list-small" id="list-2">
            <li class="element">Foo</li>
            <li class="element">Bar</li>
        </ul>
    </div>
</div>
'''
from bs4 import BeautifulSoup
soup = BeautifulSoup(html, 'lxml')
print(soup.find_all(text='Foo'))

4.select

经过select()直接传入CSS选择器就能够完成选择
熟悉前端的人对CSS可能更加了解,其实用法也是同样的
.表示class #表示id
标签1,标签2 找到全部的标签1和标签2
标签1 标签2 找到标签1内部的全部的标签2
[attr] 能够经过这种方法找到具备某个属性的全部标签
[atrr=value] 例子[target=_blank]表示查找全部target=_blank的标签

 

html='''
<div class="panel">
    <div class="panel-heading">
        <h4>Hello</h4>
    </div>
    <div class="panel-body">
        <ul class="list" id="list-1">
            <li class="element">Foo</li>
            <li class="element">Bar</li>
            <li class="element">Jay</li>
        </ul>
        <ul class="list list-small" id="list-2">
            <li class="element">Foo</li>
            <li class="element">Bar</li>
        </ul>
    </div>
</div>
'''
from bs4 import BeautifulSoup
soup = BeautifulSoup(html, 'lxml')
print(soup.select('.panel .panel-heading'))
print(soup.select('ul li'))
print(soup.select('#list-2 .element'))
print(type(soup.select('ul')[0]))

 

其余一些相似的用法:
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()返回第一个符合条件的节点

内容获取

1..string 用来获取标签的内容 

2.get_text() 用来获取标签中全部字符串包括子标签的。

可是须要了解选择器获得的数据是什么类型,find获得的是<class 'bs4.element.Tag'> ,find_all获得的是<class 'bs4.element.ResultSet'> 

1.<class 'bs4.element.ResultSet'>  这里是字典外套了一个列表

2.<class 'bs4.element.Tag'> 直接为一个字典

因此find_all获得的内容须要先选择列表索引,而后再按照字典去取值

相关文章
相关标签/搜索