BeautifulSoup :一些常用功能的使用和测试

BeautifulSoup :一些常用功能的使用和测试

也懒得转Markdown语法了,评论都在代码里了。其中句子后面写着OK的,那就说明测试通过,可以正常使用。

# -*- coding: utf-8 -*-
'''
    # Author    : Solomon Xie
    # Usage     : 测试BeautifulSoup一些用法及容易出bug的地方
    # Enviroment: Python 2.7, Windows 7 (32bit), Chinese Language Pack
'''

import time, re
import bs4 # 必须导入,因为需要做一些bs4专有类型的判断
from bs4 import BeautifulSoup


def test_BeautifulSoup():
    """
        # BeautifulSoup的一些问题实在让人蛋大。
        # 这里研究下吧。
    """
    '''
        # 基础部分
        # 关于bs4的解析速度 #################
        # 仔细阅读文档后发现,文档解析器对速度至关重要!
        # 如果没有安装cchardet模块,那么光一个网页就要7秒!!
        # 还不包括获取网页时间。然而试过后,如过山车一般:
        # 安装了cchardet以后7秒变成了一瞬。
        # 然而,用了几天后又变回了7秒,卸载了cchardet又变回了一瞬间!
        # 另外,BeautifulSoup升级到4以后,导入方法变了,如下:
    '''
    from bs4 import BeautifulSoup

    '''
        # 关于被解析文档的编码格式 ##########
        # 又不淡定了,官方说无论被传入什么编码的文档,都会被统一为unicode
        # 实际上有时候我发现,必须以unicode传入才能获得正确结果。。。
        # 这里试验发现,还真的是如此!必须传入decode过的码
    '''
    html_doc = open('test-Zhilian-list-page-sm1.html', 'r').read().decode('utf-8')
    # ^ 这个html文件其实是智联招聘搜索页的源码,可以自己保存下来直接试一试。

    '''
        # 关于bs4的文档解析器 ##############
        # 又是一个大坑:bs升级到4后,实例化时需要明确指定文档解析器,如:
        # soup = BeautifulSoup(html_doc, 'lxml')
        # 但是著名的lxml在这里就是个大坑啊,
        # 因为它会直接略过html所有没写规范的tag,而不管人家多在乎那些信息
        # 因为这个解析器的事,我少说也折腾了好几个小时才找到原因吧。
        # 总结:记住,选择html5lib!效率没查多少,最起码容错率强,不会乱删你东西!
    '''
    soup = BeautifulSoup(html_doc, 'html5lib')

    
    '''
        # 关于bs4的输出格式 #################
        # prettify()官方解释是一律输出utf-8格式,
        # 其实却是unicode类型!!所以必须在prettify()里面指定编码。
    '''
    # output = soup.prettify('utf-8')
    # print repr(output)

    '''
        # 所谓的多种搜索节点方式##############
        就是不知道为什么:
        无论怎么测验,find()和find_all()就是死活不管用!
        只有用官方文档里的英文版《爱丽丝》测试才没问题。
        也就是说,问题还是出在了文字编码上?
        可是当我试着查找英文时,搜索结果还是为零-_-!
        到了最后,bs4中众多的搜索工具上,
        唯一能用的就是select()了,即CSS选择器。
        虽然极其好用,但还是有限制性。
        不死心,所以我还是再试验一下find_all()的毛病吧。
    '''
    # == find_all()之搜索标签名称 ============ OK
    # result = soup.find_all('dl') # OK

    # == find_all()之搜索标签属性 ============ not all OK
    # result = soup.find_all(id='newlist_list_div') # OK
    # result = soup.find_all(href=re.compile('.htm')) # Failed 竟然不支持href搜索,和官方说的不一样
    # result = soup.find_all(name='vacancyid') # Failed 不支持标签的name属性搜索

    # == find_all()之按CSS搜索 ============ OK
    # result = soup.find_all('div', class_='clearfix') # OK
    # result = soup.find_all('div', class_=re.compile('newlist_detail')) # OK
    # result = soup.find_all(class_=re.compile('newlist_detail')) # OK

    # == find_all()之按内容text搜索 ============ 
    # find_all()加上text参数后,
    # 返回的是字符串!而不是tag!!
    # 类型为:<class 'bs4.element.NavigableString'>
    # result = soup.find_all(text='会计') # OK 内容必须完全相等才算!(不含子标签) 
    # result = soup.find_all(text=u'数据') # OK 内容必须完全相等 无所谓unicode了
    # result = soup.find_all(text=re.compile(u'学历:')) # OK unicode是绝对要!否则不行!

    # == select() , CSS选择器搜索引擎 ============ 
    '''
        CSS选择器的语法请看w3cschool的文档:
        http://www.w3school.com.cn/cssref/selector_nth-of-type.asp
        下面总结了在BeautifulSoup中的语法搜索:
        标签搜索,如:'input' ,搜索所有标签为input的元素
        宽泛路径,如:'body a' ,就是body内所有a元素
        绝对路径,如:'body > div > div > p' ,必须完全符合路径才能搜到
        ID搜索  ,如:'#tag-1' ,搜索id为tag1的标签
        混合搜索,如:'div #tag1', 搜索id为xx的div标签
            'div[class*=newlist_detail] ~ div[class*=newlist_detail]' ,大混合
        属性存在,如:'a[href]' ,搜索所有存在href属性的a标签
        类名搜索,如:'[class=clearfix]' ,找到class名等于clearfix的标签
            '[class^=newlist_detail]' ,找到class名中以"newlist_detail"开头的标签
            '[class$=zwmc]'           ,找到class名中以"zwmc"结尾的标签
            '[class*=clearfix]'       ,找到class名中包含"zwmc"的标签
        兄弟搜索,如:
            '#links ~ .clearfix' ,找到id为links标签的所有class等于"clearfix"的兄弟标签
            '#links + .clearfix' ,找到id为links标签的下一个class等于"clearfix"的兄弟标签
        序列搜索,如:'p nth-of-type(3)' ,这个说白了就是选择第3个p标签
            'p nth-of-type(odd)' 表示奇数的p标签
            'p nth-of-type(even)' 表示偶数的p标签
            'p nth-of-type(n)' 表示所有的p标签
            'p nth-of-type(3n)' 表示3的倍数的p标签
            'p nth-of-type(4n+1)' 表示4的倍数加1的p标签,如第5个、第9个
    '''
    # result = soup.select('dl > p') # OK tag路径搜索
    # result = soup.select('div[class*=newlist_detail] ~ div') # OK 各种混合搜索
    # result = soup.select('[class*=zwmc]') # OK 各种混合搜索
    con = soup.select('div[class^=newlist_detail]')[0]
    result = con.select('[class*=zwmc]')
    # print type(result[0])

    print len(result) 

    # out = soup.select('[class*=zwmc]')
    # print len(out)
    # for item in out:
    #   print item.get_text().encode('utf-8')

def bsText(tags=[], info=''):
    if len(tags):
        t = tags[0] # 因为只会有一个对象
        # select()选择器返回的是tag标签
        # 而find_all()用text查询是返回的是字符串!
        if isinstance(t, bs4.element.Tag):
            return t.get_text().encode('utf-8')
        elif isinstance(t, bs4.element.NavigableString):
            return t.string.encode('utf-8')
    else:
        return '无[%s]信息'%info

# 计算时间
def timeup(func):
    start = time.clock()
    func()
    end = time.clock()
    timeuse = end-start
    print '\n[%s()]函数一共使用了%d秒时间。\n' %(func.__name__, timeuse)
    return timeuse

if __name__ == '__main__':
    timeup(test_BeautifulSoup)


最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 195,980评论 5 462
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 82,422评论 2 373
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 143,130评论 0 325
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,553评论 1 267
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,408评论 5 358
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,326评论 1 273
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,720评论 3 386
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,373评论 0 254
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,678评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,722评论 2 312
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,486评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,335评论 3 313
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,738评论 3 299
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,009评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,283评论 1 251
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,692评论 2 342
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,893评论 2 335

推荐阅读更多精彩内容

  • 硬件也是,你看arduino是对avr单片机的简化 而dfrobot这些接口是对杜邦线接线的简化Makeblock...
    少儿创客阅读 275评论 0 2
  • 记2017年清明节佛山之行
    Leo_JH阅读 214评论 0 0
  • 我们临汾市的文化旅游业,有丁村文化,帝尧文化,晋国文化,根祖文化,黄河文化,我们还有红色文化。 近年来,我们临汾大...
    许的阅读 389评论 0 1
  • 01.太刀子嘴言语刻薄的人,没资格惋惜 听过了许多道理,却依旧过不好这一生。失去爱人的前调是歇斯里底,中调是...
    乐乐妖阅读 3,496评论 0 6