Beautifulsoup4学习笔记

beautifulsoup4学习小记
pip安装

pip install beautifulsoup4

或easy_install

easy_install beautifulsoup4

或源码安装

python setup.py install

BeautifulSoup除了内置HTML解析器,还支持一些第三方解析去,比如html5lib,lxml等,可以安装之后,在初始化BeautifulSoup对象的时候构建

构建BeautifulSoup对象

一般可以处理两种html文件,一种是在线获取再处理,一种是直接处理本地文件

import requests
from bs4 import BeautifulSoup
# 通过requests获取
html = requests.get('http://www.pm25.com/xian.html')
soup = BeautifulSoup(html.text)
# 处理本地文件
soup = BeautifulSoup(open('test.html'))

四种对象

BeautifulSoup主要有四类对象 Tag,NavigableString,BeautifulSoup,Comment

Tag

Tag有两种重要的属性 name和attrs
soup.p.name
soup.p.attrs 包括class在内的p标签的所有属性
soup.p[‘class’] class属性
soup.p.get(‘class’) 与上一个作用相同,获取class属性
soup.p[‘class’] = ‘newClass’ 修改class属性

获取标签的内容使用 .string或get_text()

BeautifulSoup

BeautifulSoup 对象表示的是一个文档的全部内容

Comment

打印前可以判断一下是否为注释

if type(soup.a.string)==bs4.element.Comment:
    print(soup.a.string)

遍历文档树

  1. 直接子节点
    .contents可以将tag的子节点以列表的方式输出
    .children 返回一个list生成器对象,可以通过迭代输出
for child in soup.body.children:
    print(child)
  1. 所有子孙节点
    .contents和.children都是针对的直接子节点,.descendants针对的是所有子节点。它返回的也是一个迭代器,对所有tag的子孙节点进行递归循环,可以通过迭代输出
for child in soup.body.descendants:
    print(child)
  1. 节点内容
    一个标签里面没有标签了,那么 .string 就会返回标签里面的内容
    print(soup.title.string)
    注意:如果一个tag仅有一个子节点,那么这个tag也可以使用 .string 方法,输出结果与当前唯一子节点的 .string 结果相同。
  2. 多个内容
    .string可以获取多个内容,不过需要遍历获取
for string in soup.strings:
    print(repr(string))

.string可能会包含很多空格或空行,.stripped_strings可以去除多余空白内容

for string in soup.stripped_strings:
    print(repr(string))
  1. 父节点
content = soup.head.title.string
print content.parent.name
#title
  1. 全部父节点
content = soup.head.title.string
for parent in  content.parents:
    print parent.name
输出
title
head
html
[document]
  1. 兄弟节点
    .next_sibling 属性获取了该节点的下一个兄弟节点,.previous_sibling 则与之相反,如果节点不存在,则返回 None

  2. 全部兄弟节点
    通过 .next_siblings 和 .previous_siblings 属性可以对当前节点的兄弟节点迭代输出
    for sibling in soup.a.next_siblings:
    print(repr(sibling))

  3. 前后节点
    与.next_sibling .previous_sibling 不同,它并不是针对于兄弟节点,而是在所有节点,不分层次
    比如

<head><title>The Dormouse's storytitle>head>
print(soup.head.next_element)

它的下一个节点便是 title

  1. 所有前后节点
for element in last_a_tag.next_elements:
    print(repr(element))

搜索文档树

  1. find_all( name , attrs , recursive , text , **kwargs )
    1) name 参数可以查找所有名字为 name 的tag,
    A. 传字符串
    查找所有标签
soup.find_all('b')

B. 传正则表达式

import re
for tag in soup.find_all(re.compile('^b')):
    print(tag.name)

C. 传列表
soup.find_all([‘a’, ‘b’])
D. 传方法
如果没有合适过滤器,那么还可以定义一个方法,方法只接受一个元素参数 ,如果这个方法返回 True 表示当前元素匹配并且被找到,如果不是则反回 False

def has_class_but_no_id(tag):
    return tag.has_attr('class') and not tag.has_attr('id')
# 将这个方法作为参数传入find_all()方法,将得到所有

标签 soup.find_all(has_class_but_no_id)

2) 关键字参数

# 查找id为link2
soup.find_all(id='link2')
# 传入href参数,搜索每个tag的‘href’属性
soup.find_all(href=re.compile('elseid'))
# 可以使用多个指定名字的参数,同时过滤tag的多个属性
soup.find_all(href=re.compile('elseid'),id='link1')
# 如果想用class过滤,但是class是python的关键词,怎么办? 加个下划线就可以
soup.find_all('a', class_="sister")
# 有些tag属性在搜索不能使用,比如html5的data-*属性,可以通过find_all()的attrs参数定义一个字典来搜索包含特殊属性的tag
soup.find_all(attrs={'data-foo': 'value'})

3) text参数
通过 text 参数可以搜搜文档中的字符串内容.与 name 参数的可选值一样, text 参数接受 字符串 , 正则表达式 , 列表, True

4) limit参数
limit参数与SQL中的limit关键字类似,当搜索到的结果数量达到 limit 的限制时,就停止搜索返回结果.

soup.find_all('a', limit=2)

5) recursive参数
调用tag的 find_all() 方法时,Beautiful Soup会检索当前tag的所有子孙节点,如果只想搜索tag的直接子节点,可以使用参数 recursive=False .

soup.html.find_all("title", recursive=False)
  1. find( name , attrs , recursive , text , **kwargs )
    与 find_all() 方法唯一的区别是 find_all() 方法的返回结果是值包含一个元素的列表,而 find() 方法直接返回结果
  2. find_parents() find_parent()
    find_parents() 和 find_parent() 用来搜索当前节点的父辈节点
  3. find_next_siblings() find_next_sibling()
    find_next_siblings() 方法返回所有符合条件的后面的兄弟节点,find_next_sibling() 只返回符合条件的后面的第一个tag节点
  4. find_previous_siblings() find_previous_sibling()
    find_previous_siblings() 方法返回所有符合条件的前面的兄弟节点, find_previous_sibling() 方法返回第一个符合条件的前面的兄弟节点
  5. find_all_next() find_next()
    find_all_next() 方法返回所有符合条件的节点, find_next() 方法返回第一个符合条件的节点
  6. find_all_previous() 和 find_previous()
    find_all_previous() 方法返回所有符合条件的节点, find_previous()方法返回第一个符合条件的节点

CSS选择器

写css时,标签名不加修饰,类名前加点,id名前加#,可以利用类似的方法筛选元素,用到的方法是soup.select(),返回list

# 通过标签名查找
soup.select('title')
# 通过类名查找
soup.select('.sister')
# 通过id名查找
soup.select('#link1')
# 组合查找
soup.select('p #link1')
# 直接子标签查找
soup.select("head > title")
# 组合查找
soup.select('a[class="sister"]')
soup.select('a[href="http://example.com/elseid"]')
soup.select('p a[href="http://example.com/elseid"]')

以上的select方法范湖IDE结果都是列表形式i,可以遍历形式输出,然后用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(repr(title))

本文参考 http://cuiqingcai.com/1319.html

你可能感兴趣的:(python,爬虫)