废话少说

为什么用BeautifulSoup提取xml的link标签中的url总为空呢

闲言少叙,直接上代码:

#!/usr/bin/env python3
# coding=utf-8

import requests
from bs4 import BeautifulSoup

def get_soup():
    url = 'https://www.solidot.org/index.rss'
    rss_xml = requests.get(url).text
    soup = BeautifulSoup(rss_xml, 'html5lib')
    return soup

def get_mail_body():
    contents = get_soup().select('item')[0:9]
    contents_list = []
    for c in contents:
        title = c.select_one('title').get_text()
        link = c.select_one('link').get_text()
        contents_list.append(title + '  ' + link)
    return '\n'.join(contents_list)

print(get_mail_body())

 

假如上述代码保存在了一个名为solidot.py 的py文件中,然后运行python3 solidot.py,结果会如下:

为什么用BeautifulSoup提取xml的link标签中的url总为空呢
这时候你该好奇了明明提取了下面的xml源码中的link标签,为什么紧随着title后面却啥也没有呢

<item>
<title><![CDATA[微软放弃继续开发 Visual Basic]]></title>
<link><![CDATA[https://www.solidot.org/story?sid=63817]]></link>
<description><![CDATA[微软 DevBlogs <a href="https://devblogs.microsoft.com/vbteam/visual-basic-support-planned-for-net-5-0/">
宣布</a>从 .NET 5 开始,Visual Basic 将支持  Class Library、Console、Windows Forms、WPF、Worker Service 和 ASP.NET Core Web API 等,
为想要将现有应用迁移到 .NET Core 的 VB 客户提供一条路径,而 Visual Basic 语言本身将不会继续发展或引入新特性,未来将主要着重于稳定性和兼容性。
当微软发布 Visual Basic .NET 和  C# 开启 .NET 时代时,两种语言是并行发展的,有着几乎相同的功能集。但随着时间的迁移,专业的开发者接受了 C# ,经典 
VB 的粉丝则放弃了越来越复杂而强大的 .NET 版本。现在微软的开发文档基本上只提供 C#,而没有 VB 示例了。C#/VB 的同步发展策略在 2017 年结束,只有 C# 
获得新的功能,微软事实上放弃了 VB。本周的声明只是<a href="https://www.thurrott.com/dev/232268/microsoft-plots-the-end-of-visual-basic">
正式承认</a>。<p><img src="https://img.solidot.org//0/446/liiLIZF8Uh6yM.jpg" height="120" style="display:block"/></p>]]>
</description>
<pubDate>Sat, 14 Mar 2020 14:18:40 +0800</pubDate>
</item>

 

解决方法

经过各种尝试,鄙人终于找到了解决方法,也明白了为什么会出现这种情况,全拜一篇国外的文章所赐,

下面的内容为收费内容,会直接给出解决方案和简单描述原因,以及我所参考的那篇国外的文章链接,

本人保证解决方案切实有效,无效的话可以微信搜索Baksmali言明来意加好友,

经鄙人的鉴定后会以红包的形式退还你在本篇博客的花费。

[$]

在说出解决方案之前,我们先来看另一种情况,

我们将soup = BeautifulSoup(rss_xml, 'html5lib')中的html5lib改为lxml

会出现什么情况呢,结果更令人惊讶,这次连title都没有了,如下:

为什么用BeautifulSoup提取xml的link标签中的url总为空呢

其实原因是因为当BeautifulSoup的parser为lxmlhtml5lib时,均是为解析html而存在的,像很多标签如<link></link><meta></meta>中的内容在用get_text()方法提取时会默认为空,具体请参考 这篇文章 的末尾所描述的。

说了这么多闲话,该说一下真正的解决方法了,其实很简单,就是把paser换成xml就好了,具体如下:

soup = BeautifulSoup(rss_xml, 'xml')

其实,认真看BeautifulSoup的官方文档的话,文档的这里也有提到解析xml时parser要换成xml

[/$]

写在最后

相信大家看完上面的付费内容后会觉得这么简单的解决方案真不值这点钱,这就让我想起小时候看的那个故事了,想必大家也都知道,就是一个工程师在一个电机上画了一条白线解决了一个工程难题的故事,于是我想说:

用粉笔画一条线1美元,知道在哪里画这条线9999美元=1万美元