• 使用 BeautifulSoup 解析 HTML


    对于一个最简单的爬虫结构的代码是这样的。

    也就是抓取出整个页面,然后创建一个BeautifulSoup对象。

    from urllib.request import urlopen
    from bs4 import BeautifulSoup
    html = urlopen("http://www.pythonscraping.com/pages/warandpeace.html")
    bsObj = BeautifulSoup(html)
    

    find()和findAll()

    这两个函数非常相似,是用来通过标签的不同属性来过滤HTML页面,查找需要的标签组或单个标签的。BeautifulSoup文档里两者的定义就是这样:

    findAll(tag, attributes, recursive, text, limit, keywords)
    find(tag, attributes, recursive, text, keywords)
    

    标签参数tag

    你可以传一个标签的名称或多个标签名称组成的Python列表做标签参数。比如:

    bsObj.findAll({"h1","h2","h3","h4"})
    

    属性参数attributes

    它是用一个Python字典封装一个标签的若干属性和对应的属性值。比如,下面这个函数会返回HTML文档里红色和绿色两种颜色的span标签:

    bsObj.finaAll("span",{"class":{"green", "red"}})
    

    递归参数recursive

    它是一个布尔变量。如果设置为True,findAll就会根据你的要求去查找标签参数的所有子标签,以及子标签的子标签。如果设置为False,findAll就只查找文档的一级标签。默认是支持递归查找的,所以一般这个参数不需要设置。

    文本参数text

    它是用标签的文本去匹配,而不是用标签的属性。比如:

    nameList = bsObj.findAll(text="the prince")
    print(len(nameList))
    

    范围限制参数limit

    find()其实等价于findAll()的limit等于1时的情形。如果你只对网页中获取的前n项结果感兴趣,就可以设置它。

    关键词参数keyword

    它可以让你选择那些具有指定属性的标签。比如:

    allText=bsObj.findAll(id="text")
    print(allText[0].get_text())
    

    但是,keyword偶尔会出现问题,尤其是在用class属性查找标签的时候,因为class是Python中受保护的关键字。但是可以用BeautifulSoup提供的另一种方案,在class后面增加一个下划线

    # 错误
    bsObj.findAll(class="green")
    # 正确
    bsObj.findAll(class_="green")
    bsObj.findAll("",{"class":"green"})
    

    get_text()

    get_text()会把正在处理的HTML文档中所有的标签都清楚,然后返回一个只包含文字的字符串。

    通常在你准备打印、存储和操作数据时,应该最后才使用get_text()。一般情况下,你应该尽可能地保留HTML文档的标签结构。

    导航树

    如果需要通过标签在文档中的位置来查找标签,那么就要用到导航树(Navigating Trees)。

    虚拟的在线购物网站作为要抓取的示例网页,这个HTML页面可以映射成一棵树,如下所示:

    -body
    	-div.wrapper
    		-h1
    		-div.content
    		-table#giftList
    			-tr
    				-th
    				-th
    				-th
    				-th
    			-tr.gift#gitf1
    				-td
    				-td
    					-span.excitingNote
    				-td
    				-td
    					-img
    			-……其他表格行省略了……
    	-div.footer
    

    子标签与后代标签

    在BeautifulSoup库里,孩子(child)后代(descendant)有显著的不同。

    子标签就是一个父标签的下一级,而后代标签是指一个父标签下面所有级别的标签。

    比如,tr标签是table标签的子标签,而tr、th、td、img和span标签都是table标签的后代标签。

    也就是所有的子标签都是后代标签,但不是所有的后代标签都是子标签。

    如果只想找出子标签,可以使用children()函数

    from urllib.request import urlopen
    from bs4 import BeautifulSoup
    
    html = urlopen("http://www.pythonscraping.com/pages/page3.html")
    bsObj = BeautifulSoup(html)
    
    for child in bsObj.find("table",{"id":"giftList"}).children:
        print(child)
    

    这段代码会打印gitfList表格中所有产品的数据行。

    而如果使用的是descendants()函数就会有二十几个标签打印出来,包括img标签等。

    兄弟标签

    next_siblings()函数可以让收集表格数据成为简单的事情,尤其是处理带标题行的表格:

    from urllib.request import urlopen
    from bs4 import BeautifulSoup
    
    html = urlopen("http://www.pythonscraping.com/pages/page3.html")
    bsObj = BeautifulSoup(html)
    
    for sibling in bsObj.find("table",{"id":"giftList"}).tr.next_siblings:
        print(sibling)
    

    这段代码会打印产品列表里所有行的产品,第一行表格标题除外。因为自己不能是自己的兄弟标签,而且这个函数只调用后面的兄弟标签。

    如果一组兄弟标签里的最后一个标签比较好找,也可以用previous_siblings()函数

    获取标签属性

    有时候我们需要的数据在标签属性里,那么我们可以使用下面的代码获取它的全部属性:

    myTag.attrs
    

    这行代码返回的是一个Python字典对象,可以获取和操作这些属性。

    比如要获取图片的资源位置src,可以这样使用:

    myImgTag.attrs["src"]
    

    【参考】

    [1]《Python网络数据收集》Ryan Mitchell

  • 相关阅读:
    前后端分离实践 — 如何解决跨域问题
    bower 和 npm 的区别详细介绍
    yeoman-bower-grunt之间的关系
    软件开发环境-开发环境、测试环境、生产环境的区别
    Tomcat下配置JNDI的三种方式
    SSE
    Java动态代理
    Css之Relative
    多线程之——死锁
    JVM
  • 原文地址:https://www.cnblogs.com/IvyWong/p/10064379.html
Copyright © 2020-2023  润新知