3.2. BeautifulSoup有时候会遇到非法的,不支持的html源码而导致无法解析或无法正常解析html

在使用Beautifulsoup过程中,对于大多数html源码,通过指定正确的编码,或者本身是默认UTF-8编码而无需指定编码类型,其都可以正确解析html源码,得到对应的soup变量。

然后就接着去利用soup实现你所想要的功能了。

但是有时候会发现,有些html解析后,有些标签等内容丢失了,即所得到的soup不是所期望的完整的html的内容。

这时候,很可能遇到了非法的html,即其中可能包含了一些不合法的html标签等内容,导致Beautifulsoup虽然可以解析,没有报错,但是实际上得到的soup变量,内容缺失了一部分了。

比如我就遇到过不少这样的例子:

  1. 部分Blogbus的帖子的html中非html5和html5的代码混合导致Beautifulsoup解析错误

    之前在为BlogsToWordPress添加Blogbus支持过程中去解析Blogbus的帖子的时候,遇到一个特殊的帖子:http://ronghuihou.blogbus.com/logs/89099700.html,其中一堆的非html5的代码中,包含了这样一段html5的代码的写法,即标签属性值不加括号的:

    
    <SCRIPT language=JavaScript> 
    document.oncontextmenu=new Function("event.returnValue=false;"); //禁止右键功能,单击右键将无任何反应 
    document.onselectstart=new Function( "event.returnValue=false;"); //禁止先择,也就是无法复制 
    </SCRIPT language=JavaScript>
    
                

    结果导致Beautifulsoup解析错误,得到的soup中,找不到所需要的各种class等属性值。

    对应的解决办法就是,把这部分的代码删除掉,然后再解析就可以了:

    其中一堆的非html5的代码中,包含了这样一段html5的代码的写法,即标签属性值不加括号的:

    
    foundInvliadScript = re.search("<SCRIPT language=JavaScript>.+</SCRIPT language=JavaScript>", html, re.I | re.S );
    logging.debug("foundInvliadScript=%s", foundInvliadScript);
    if(foundInvliadScript):
        invalidScriptStr = foundInvliadScript.group(0);
        logging.debug("invalidScriptStr=%s", invalidScriptStr);
        html = html.replace(invalidScriptStr, "");
        logging.debug("filter out invalid script OK");
    
    soup = htmlToSoup(html);
    
                
  2. 判断浏览器版本的相关代码,导致Beautifulsoup解析不正常

    之前在给BlogsToWordpress添加新浪博客的支持的过程中

    遇到很多新浪博客的帖子的html中,包含很多判断浏览器版本的相关代码:

    
    <!–[if lte IE 6]>
    xxx
    xxx
    <![endif]–>
    
                

    由此导致Beautifulsoup解析html不正常。

  3. font标签嵌套层次太多,导致Beautifulsoup无法解析html

    接上面那个解析新浪博客帖子的例子,期间又遇到另外一个问题,对于一些特殊帖子:http://blog.sina.com.cn/s/blog_5058502a01017j3j.html

    其包含特殊的好几十个font标签且是一个个嵌套的代码,导致无法Beautifulsoup无法解析html,后来把对应嵌套的font标签删除掉,才可以正常解析。

    相关python代码为:

    
    # handle special case for http://blog.sina.com.cn/s/blog_5058502a01017j3j.html
    processedHtml = processedHtml.replace('<font COLOR="#6D4F19"><font COLOR="#7AAF5A"><font COLOR="#7AAF5A"><font COLOR="#6D4F19"><font COLOR="#7AAF5A"><font COLOR="#7AAF5A">', "");
    processedHtml = processedHtml.replace("</FONT></FONT></FONT></FONT></FONT></FONT>", "");
    
                

遇到其他类似的问题,也可以去删除或替换出错代码,即可解决问题。

不过需要说明的是,很多时候,你未必很容易就找到出错的代码。

想要找到出错的代码,更多的时候,需要你一点点调试,一点点的删除看似可疑的一些html源码,然后最终才能定位到出错的代码,然后删除掉后,才可以正常工作的。