#34;VBA信息获取与处理"教程中第八个专题"VBA与HTML文档"的第七节"HTML DOM的对象事件及关联"太枯燥了,希望想掌握这方面知识的朋友能参考我的教程学习。我们今天 开始第九个专题的学习"利用IE抓取网络数据"。
我们的网抓部分在讲解了XMLHTTP方法后,利用两个专题的进度进行了一些和VBA关系不是很大的有关网络知识的讲解,这两个专题对于我们重新认识网抓数据有着非常重要的意义,虽然我的讲解还不能面面俱到,但对于我经常倡导的VBA定位来说,是足够的,再者,学习是个不断积累前进的过程,要掌握的是一些基本的理论,然后把这些应用到自己的实际中去,这才是关键。从这个专题开始我们继续网抓的学习。这个专题是利用IE抓取网络数据。其实就是利用控件来完成我们的工作。
为了获取网页的数据,我们可以通过创建IE控件或webbrowser控件,结合htmlfile对象的方法和属性,模拟浏览器操作,获取浏览器页面的数据。
这种方法可以模拟大部分的浏览器操作。浏览器能看到的数据就能用代码获取,但是有个致命的缺点:除去各种弹窗相当烦人外,兼容性也确实是个很伤脑筋的问题。在我自己的实践中感觉这种方法不是很稳定(仅仅是感觉)。
我们在实际工作中遇到网站和网页相关问题,例如:如何下载网页数据?网页之间的通讯是怎么实现的、它们能不能被控制等等。如果你是用VB/VBA/脚本或其它支持自动化对象(AUTOMATION)的语言编程,有一个值得了解的方法是掌握对象模型:将网页视为对象来控制,这个方法需要了解的是IE的自动化对象(InternetExplorer.Application)或IE控件(Microsoft Internet Controls),以及标准的文档对象模型(Document)。相关的知识我在前两个专题中做了大量的讲解,这里就不再详细的说明了。
我给出下面的代码:
Set ie = CreateObject("InternetExplorer.Application") '创建对象
ie.Visible = True '使IE页面可见,做完这一步,在VBA之外可以看到一个新的IE
ie.navigate "about:blank" '建立一个空白页
上面这几行代码的作用是创建一个IE应用程序对象,并打开一个空白的网页。这个网页独立于VBA的应用程序(WORD或EXCEL)之外,事实上,你必须自已关掉它,或者用ie.Quit下令退出——注意一下,单纯的关闭VBA或SET ie=nothing是不会退出这个网页的。我们经常用的是将第3行的字符串替换成一个网站的名字,或者替换成一个你主机中的文档名,也可以是一个图片名,都是可以的。和你在IE地址栏输入名称浏览这些文档是一样效果。
如果仅仅是创建了一个空的模型是没有任何利用的价值的,我们需要真正的网页,这时就需要我们在VBA的应用程序外打开一个完整的网页了,直到网页完全加载我们的操作才能向下进行。
我们修正一下上面的那段打开空网页的代码:
Sub mynz()
Set ie = CreateObject("InternetExplorer.Application") '创建对象
ie.Visible = True '使IE页面可见,做完这一步,在VBA之外可以看到一个新的IE
ie.navigate " https://baijiahao.baidu.com" '建立一个空白页
Do Until .ReadyState = 4 '检查网页是否加载完毕(4表示完全加载)
DoEvents '循环中交回工作权限给系统,以免"软死机"
Loop
End sub
在上面的代码中增加了几行:
Do Until .ReadyState = 4 '检查网页是否加载完毕(4表示完全加载)
DoEvents '循环中交回工作权限给系统,以免"软死机"
Loop
这几行代码可以保证网页的加载完成,这是根据ie.ReadyState的返回值来判断的。
readyState一共有5中状态:
状态 含义 说明
0 未初始化 对象已建立,但是尚未初始化(尚未调用open方法)
1 初始化 对象已建立,尚未调用send方法
2 发送数据 send()方法已调用,但是当前的状态及http头未知
3 数据传送中 已接收部分数据,因为响应及http头不全,这时通过responseBody和responseText获取部分数据会出现错误
4 数据接收完毕 此时可以通过通过responseBody和responseText获取完整的回应数据
通过以上的分析,我们可以看出,只用当.ReadyState = 4时网页的数据才是有效的数据。
当网页加载完毕,剩下的工作就是从网页中抓取数据了,数据的抓取主要是利用控件对象的属性和方法。
1)用Set doc = ie.Document 取得网页的文档对象
从文档对象(Document)以下展开的对象模型,它代表网页的内容,和前面那个IE的应用程序不是同一个体系.
Documnet(文档)是文档对象模型,相当于OFFICE对象中的APPLICATION,取得Document之后,不论修改网页还是读写网页,还是触发事件,一切都好说,每个URL都对应有一个Documnet(这是假如定成功导航Navigate到那个URL完成,因此之前要求确定IE对象READSTATE,以确定对应URL的Document打开了)
2) 在Documnet之下可以取得documentElement和body两个节点。
可以用下面的语句:
set xbody=doc.Body '取得body对象
set xDoc=doc. documentElement '取得根节点
body前面已经说过,相当于标记的对象,根节点相当于网页中的标记元素的对象,MHTML的类型库定义里,它们都属于HTMLHtmlElement类型的对象,下面我把这种类型的对象称为一个"节点",不过要注意的是文档对象不是节点对象,它是HTMLDocument类型。根节点和body节点不同的是根节点包括整个网页,在HTML的文档对象模型中,这类对象有几种属性可以取得其中的内容:
对象.innerHtml '对象内部的HTML文本
对象.OuterHtml '对象中的HTML文本,包括对象本身的HTML标记在内
对象.innerText '对象内部的TEXT,不包括HTML标记
对象.OuterText '同上,包括对象本身的文本
所以,如果我们要抓取某个网站的所有HTML内容,代码可以这样写:
set doc=ie.Document
set xDoc=doc. documentElement '取得根节点
strX=xDoc.OuterHtml '取得所有的HTML内容
3) 每一个标记节点对象之下都有一个名为ChildNodes的集合,它包含了"直属于本节点下的标记",就象是文件目录,根目录下的子目录.
我们可以看到:HTML标记是文档的根节点,是Document的Childnodes集合中的一个成员(Document不是节点,是另一种类型对象,上一级文档,但它可以有下级节点集合,正如磁盘可以有下级目录,但它本身不是目录),BODY是根节点的ChildNodes集合中的一个成员,而DIV和P两个节点则是BODY的ChildNodes集合中的两个成员,同样也有自已的Childnoes集合。
我们要注意:文档对象模型中,集合与OFFICE的集合有所不同,集合是从0开始计数的,计数属性是Length而不是Count。
4)除了ChildNodes集合,大家在网页文档对象中还常见到的就是很大气的一种集合:All集合,这是"最糊涂"的一种集合,文档和各级节点都带有这个集合,正如这个名字所示,它是不分层次的,但用起来也很方便:
Set doc=ie.Document
Set xCols=doc.All '取得文档中的所有节点集合
Set xbCols=doc.body.All '取得body节点下所有的节点集合
虽然任何标记节点都有ALL集合,但我们还是喜欢用DOCUMENT的ALL,原因无它,文档最大,一锅烩的ALL找起来也最合适。ALL查找是有条件的:如果这个标记没有ID,你无法查到它的名字。
不过,ALL集合有一个很方便的特性:ID可以挂到ALL集合之下:
strX=doc.All.mytag.innerhtml
5)获得文档对象的getElementsByName集合,可以利用下面的方法:
set mydivs=doc. getElementsByName("div") '取得所有DIV标记,注意还是集合
6) 文档对象的FORMS集合,因为大部分网页的数据提交都是通过FORM标记提交的:
Set myForms=doc.Forms '取得所有的FORM标记
Set frmX=myForms.item(0) '第1个FORM
FORM标记节点代表的对象是很多朋友关心的内容——在网页对象中,它可以发送数据到服务器,使服务器刷新网页(实际上是服务器按某个格式约定发回数据),我们可以把网页的FORM看成是一个远程的函数调用接口,FORM标记中的ACTION指向的URL地址就是函数入口,而FORM标记内的各个INPUT标记节点就是函数的参数,当发出FORM.Submit方法时,就是远程调用函数了,在服务器端,诸如ASP,PHP就是老老实实找FORM的参数,不管你是用GET还是POST:
frmX.submit '相当于用户在页面上按下FORM的发送按键
上面我罗列了获取网页数据的一般的方法,并没有什么特别的使用要求,大家可以根据自己的习惯来利用,这个专题之后的内容就是灵活运用这些知识点来解决实际问题了。
本节知识点回向:
如何提交表单?如何下载图片的地址?如何获得表的数据?
在我的系列书籍中一直在强调"搭积木"的编程思路,这也是学习利用VBA的主要方法,特别是职场人员,更是要采用这种方案。其主要的内涵:
1 代码不要自己全部的录入。你要做的是把积木放在合适的位置然后去修正代码,一定要拷贝,从你的积木库中去拷贝,然后修正代码,把时间利用到高效的思考上。
2 建立自己的"积木库"。平时在学习过程中,把自己认为有用的代码放在一起,多积累,在用到的时候,可以随时拿来。你的积木库资料越多,你做程序的思路就会越广。
VBA是利用Office实现个人小型办公自动化的有效手段(工具)。这是我对VBA的应用界定。在取代OFFICE新的办公软件没有到来之前,谁能在数据处理方面做到极致,谁就是王者。其中登峰至极的技能非VBA莫属!
我记得20年前自己初学VBA时,那时的资料甚少,只能看源码自己琢磨,真的很难。20年过去了,为了不让学习VBA的朋友重复我之前的经历,我根据自己多年VBA实际利用经验,推出了六部VBA专门教程:
第一套:VBA代码解决方案 是VBA中各个知识点的讲解,教程共147讲,覆盖绝大多数的VBA知识点,初学必备;
第二套:VBA数据库解决方案 数据库是数据处理的专业利器,教程中详细介绍了利用ADO连接ACCDB和EXCEL的方法和实例操作,适合中级人员的学习。
第三套:VBA数组与字典解决方案 数组和字典是VBA的精华,字典是VBA代码水平提高的有效手段,值得深入的学习,是初级及中级人员代码精进的手段。
第四套:VBA代码解决方案之视频 是专门面向初学者的视频讲解,可以快速入门,更快的掌握这门技能。这套教程是第一套教程的视频讲解,听元音更易接受。
第五套:VBA中类的解读和利用 这是一部高级教程,讲解类的虚无与肉身的度化,类的利用虽然较少,但仔细的学习可以促进自己VBA理论的提高。这套教程的领会主要是读者的领悟了,领悟一种佛学的哲理。
第六套教程:《VBA信息获取与处理》,这是一部高级教程,涉及范围更广,实用性更强,面向中高级人员。教程共二十个专题,包括:跨应用程序信息获得、随机信息的利用、电子邮件的发送、VBA互联网数据抓取、VBA延时操作,剪切板应用、Split函数扩展、工作表信息与其他应用交互,FSO对象的利用、工作表及文件夹信息的获取、图形信息的获取以及定制工作表信息函数等等内容。
大家可以根据以上资料1→3→2→6→5或者是4→3→2→6→5的顺序逐渐深入的逐渐学习。教程提供讲解的同时提供了大量的积木,如需要可以WeChat: NZ9668
如太白诗云:众鸟高飞尽,孤云独去闲。相看两不厌,只有敬亭山。学习的过程也是修心的过程,修一个平静的心。在代码的世界中,心平静了,心情好了,身体自然而然就好。心静则正,内心里没有那么多邪知邪见,也就没有那么多妄想。利人就是利己。这些教程也是为帮助大家起航,助上我自己之力,我的上述教程是我多的经验的传递,
"水善利万物而不争",绵绵密密,微则无声,巨则汹涌。学习亦如此,知道什么是自己所需要的,不要蜷缩在一小块自认为天堂的世界里,待到暮年时再去做自欺欺人的言论。要努力提高自己,用一颗充满生机的心灵,把握现在,这才是进取。越是有意义的事情,困难会越多。愿力决定始终,智慧决定成败。不管遇到什么,都是风景。看淡纷争,看轻得失。茶,满也好,少也好,不要计较;浓也好,淡也好,其中自有值得品的味道。去感悟真实的时间,静下心,多学习,积累福报。而不是天天混日子,也不是天天熬日子。在后疫情更加严峻的存量残杀世界中,为自己的生存进行知识的储备,特别是新知识的储备。学习时微而无声,利用时则巨则汹涌。
每一分收获都是成长的记录,怎无凭,正是这种执着,成就了朝霞的灿烂。最后将一阙词送给致力于VBA学习的朋友,让大家感受一下学习过程的枯燥与执着:
浮云掠过,暗语无声,
唯有清风,惊了梦中啼莺。
望星,疏移北斗,
奈将往事雁同行。
阡陌人,昏灯明暗,
忍顾长亭。
多少VBA人,
暗夜中,悄声寻梦,盼却天明。
怎无凭!
回向学习利用VBA的历历往事,不胜感慨,谨以这些文字给大家,分享我多年工作实际经验的成果,随喜这些有用的东西,给确实需要利用VBA的同路人。
分享成果,随喜正能量
要使用sed、awk、grep等工具进行尝试(这会导致不可预期的结果)。在许多情况下,你最好选择使用支持XML数据的编程语言进行处理。如果必须使用shell脚本,有一些专门用于解析HTML和XML文件的工具可供使用。
你可能知道Lynx是一个带有极限限制的终端模式Web浏览器。确实如此,但它也是一个可编程的HTML解析器。它特别擅长从文档中提取链接并将其打印出来:
如果你想要包括图像链接,请添加-image_links选项。现在,根据你的需求过滤链接应该相对简单,因为每个链接都在单独的一行上,没有HTML标签的干扰。
$ lynx -dump -listonly -nonumbers http://mywiki.wooledge.org/
http://mywiki.wooledge.org/EnglishFrontPage?action=rss_rc&unique=1&ddiffs=1
http://mywiki.wooledge.org/EnglishFrontPage?action=edit
http://mywiki.wooledge.org/EnglishFrontPage
http://mywiki.wooledge.org/EnglishFrontPage?action=raw
http://mywiki.wooledge.org/EnglishFrontPage?action=print
http://mywiki.wooledge.org/EnglishFrontPage?action=AttachFile&do=view&target=Greg's-wiki.zip
[...]
你可能会认为wget在这方面也很好用,对吧?我的意思是,它有递归镜像模式,所以显然内部做了这种操作。祝你好运,试图找到一种方法让wget将URL打印出来而不是下载全部文件。
我试着尝试了一下,找到了一种方法。没有经过充分测试。我们可以使用--rejected-log和始终匹配的--reject-regex参数。我们使用--spider选项以不保存文件的方式执行。
$ wget -q --spider -r --rejected-log=rejected --reject-regex=^ http://mywiki.wooledge.org/
$ cat rejected
REASON U_URL U_SCHEME U_HOST U_PORT U_PATH U_PARAMS U_QUERY U_FRAGMENT P_URL P_SCHEME P_HOST P_PORT P_PATH P_PARAMS P_QUERY P_FRAGMENT
REGEX http%3A//mywiki.wooledge.org/moin_static198/common/js/common.js SCHEME_HTTP mywiki.wooledge.org 80 moin_static198/common/js/common.js http%3A//mywiki.wooledge.org/ SCHEME_HTTP mywiki.wooledge.org 80
REGEX http%3A//mywiki.wooledge.org/moin_static198/modernized/css/common.css SCHEME_HTTP mywiki.wooledge.org 80 moin_static198/modernized/css/common.css http%3A//mywiki.wooledge.org/ SCHEME_HTTP mywiki.wooledge.org 80
REGEX http%3A//mywiki.wooledge.org/moin_static198/modernized/css/screen.css SCHEME_HTTP mywiki.wooledge.org 80 moin_static198/modernized/css/screen.css http%3A//mywiki.wooledge.org/ SCHEME_HTTP mywiki.wooledge.org 80
REGEX http%3A//mywiki.wooledge.org/moin_static198/modernized/css/print.css SCHEME_HTTP mywiki.wooledge.org 80 moin_static198/modernized/css/print.css http%3A//mywiki.wooledge.org/ SCHEME_HTTP mywiki.wooledge.org 80
REGEX http%3A//mywiki.wooledge.org/moin_static198/modernized/css/projection.css SCHEME_HTTP mywiki.wooledge.org 80 moin_static198/modernized/css/projection.css http%3A//mywiki.wooledge.org/ SCHEME_HTTP mywiki.wooledge.org 80
[...]
要将链接提取到标准输出中:
$ wget -q --spider -r --rejected-log=/dev/stdout --reject-regex=^ http://mywiki.wooledge.org/ | tail -n +2 | cut -f 2
http%3A//mywiki.wooledge.org/moin_static198/common/js/common.js
http%3A//mywiki.wooledge.org/moin_static198/modernized/css/common.css
http%3A//mywiki.wooledge.org/moin_static198/modernized/css/screen.css
http%3A//mywiki.wooledge.org/moin_static198/modernized/css/print.css
http%3A//mywiki.wooledge.org/moin_static198/modernized/css/projection.css
[...]
xmllint是处理大多数XML的最佳选择。不幸的是,使用它需要学习XPath,而我并不知道任何合理的XPath入门教程。以下是一些简单的技巧。它们是使用以下输入文件演示的:
<staff>
<person name="bob"><salary>70000</salary></person>
<person name="sue"><salary>90000</salary></person>
</staff>
请注意,xmllint在输出中不添加换行符。如果你用CommandSubstitution进行捕获,这不是问题。但如果你在交互式shell中测试,这将很快变得很烦人。你可以考虑编写一个包装函数,例如:
xmllint() { command xmllint "$@"; echo; }
简单技巧:
$ xmllint --xpath 'string(//salary)' foo.xml
70000
$ xmllint --xpath '//salary/text()' foo.xml
7000090000
$ xmllint --xpath 'count(//person)' foo.xml
2
$ xmllint --xpath '//person[1]/salary/text()' foo.xml
70000
$ xmllint --xpath '//person[2]/salary/text()' foo.xml
90000
$ xmllint --xpath '//person[@name="bob"]/salary/text()' foo.xml
70000
$ xmllint --xpath 'string(//person[2]/@name)' foo.xml
sue
上述示例显示,当你拥有一个不错的XML解析器时,解析XML是相当容易的,但这违背了XML的目的,即让每个人都感到痛苦。因此,一些聪明人引入了XML命名空间。
一个典型的maven构建文件(称为pom.xml)就是这样的例子,大致如下:
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.codehaus.mojo</groupId>
<artifactId>my-project</artifactId>
<version>1.0-SNAPSHOT</version>
</project>
通常还会有几百行用于依赖项,但我们来保持简洁。
根据前一章的示例,我们知道从该文件中提取版本只需使用xpath /project/version/text():
$ xmllint --xpath '/project/version/text()' pom.xml
XPath set is empty
嗯,不是这样的,因为作者聪明地为这个xmlns="http://maven.apache.org/POM/4.0.0"添加了一个默认命名空间,所以现在你首先必须指定确切的URL,然后才能指明要获取的版本元素内部的文本。
xmllint的--xpath选项没有办法指定命名空间,所以它现在无法使用(除非你编辑文件并删除命名空间声明)。但其shell功能确实允许设置命名空间。
xmllint --shell pom.xml << EOF
setns ns=http://maven.apache.org/POM/4.0.0
cat /ns:project/ns:version/text()
EOF
/ > / > -------
1.0-SNAPSHOT
/ >
耶!我们得到了版本号...外加一些来自xmllint shell的提示和废话,之后必须将其删除。
xmlstarlet对于这个任务来说稍微容易一些
$ xmlstarlet sel -N ns=http://maven.apache.org/POM/4.0.0 -t -v /ns:project/ns:version -n pom.xml
1.0-SNAPSHOT
Python也附带了一个XML解析器,通常比xmllint和xmlstarlet更常用。它也可以以一种笨拙的方式处理命名空间。
$ python -c 'import xml.etree.ElementTree as ET;print(ET.parse("pom.xml").find("{http://maven.apache.org/POM/4.0.0}version").text)'
1.0-SNAPSHOT
xsltproc恰好在大多数Linux系统上安装。例如提取播客的标题和URL:
xslt() {
cat << 'EOX'
<?xml version="1.0"?>
<x:stylesheet version="1.0" xmlns:x="http://www.w3.org/1999/XSL/Transform">
<x:output method="text" />
<x:template match="/">
<x:for-each select="//item">
<x:text># </x:text>
<x:value-of select="./title/text()" /><x:text>
<!-- newline --></x:text>
<x:value-of select="enclosure/@url" /><x:text>
</x:text>
</x:for-each>
</x:template>
</x:stylesheet>
EOX
}
curl -s http://podcasts.files.bbci.co.uk/p02nq0lx.rss | xsltproc <(xslt) -
如果你想学习如何编写更加健壮和可靠的 Shell 脚本,减少生产环境中的错误和故障,那么关注我吧!我会分享 Shell 编程的最佳实践和建议,帮助你提高 Shell 脚本的鲁棒性和可维护性。如果你想深入了解 Shell 编程的实际应用和技巧,可以关注我的《Shell 脚本编程最佳实践》专栏,里面有我在一线互联网大厂的实际生产经验和最佳实践,帮助你高效完成各种自动化任务。
读:本文的目标是介绍一些Python库,帮助你从类似于PDF和Word DOCX 这样的二进制文件中提取数据。我们也将了解和学习如何从网络信息源(web feeds)(如RSS)中获取数据,以及利用一个库帮助解析HTML文本并从文档中提取原始文本。
我们还将学习如何从不同来源提取原始文本,对其进行规范化,并基于它创建一个用户定义的语料库。
在本文中,你将学习7个不同的实例。我们将学习从PDF文件、Word文档和Web中获取数据。PDF和Word文档是二进制文件,通过Web,你将获得HTML格式的数据,因此,我们也会对数据执行规范化和原始文本转换任务。
作者:克里希纳·巴夫萨、纳雷什·库马尔、普拉塔普·丹蒂
如需转载请联系大数据(ID:hzdashuju)
作为一名NLP专家,你将要处理大量的文本内容。当你在处理文本时,你必须知道一些字符串操作。我们将从几个简短的范例入手,帮助你理解str类及其在Python中的相关操作。
1. 准备工作
这里,你仅仅需要Python解释器和一个文本编辑器。我们将使用join(连接)、split(分割)、addition(加法)和multiplication(乘法)运算符以及索引。
2. 如何实现
(1)创建一个新的Python文件,命名为StringOps1.py。
(2)定义以下两个对象:
namesList = ['Tuffy','Ali','Nysha','Tim' ] sentence = 'My dog sleeps on sofa'
第一个对象nameList是一个包含若干名字的字符串列表,第二个对象sentence是一个包含一句话的字符串对象。
(3)首先,我们看看join函数的特点以及它的功能:
names = ';'.join(namesList) print(type(names), ':', names)
join()函数可以被任意一个string对象调用,它的输入参数是一个str对象的列表。通过将调用字符串的内容作为连接分隔符,它将所有str对象连接成一个str对象,并返回连接后的对象。运行这两行代码后,你得到的输出如下:
<class 'str'> : Tuffy;Ali;Nysha;Tim
(4)接下来,我们来看split方法的功能:
wordList = sentence.split(' ') print((type(wordList)), ':', wordList)
当split函数调用一个字符串时,它会将其内容分割为多个str对象,创建一个包含这些字符串对象的列表,并返回该列表。该函数接受单个str对象作为参数,表示分隔符。运行代码,得到如下输出:
<class 'list'> : ['My', 'dog', 'sleeps', 'on', 'sofa']
(5)算术运算符+和*也可以用于字符串。添加以下代码并输出:
additionExample = 'ganehsa' + 'ganesha' + 'ganesha' multiplicationExample = 'ganesha' * 2 print('Text Additions :', additionExample) print('Text Multiplication :', multiplicationExample)
我们首先看一下输出结果,随后讨论其工作原理:
Text Additions: ganehsaganeshaganesha Text Multiplication: ganeshaganesha
+运算符被称为连接符,它将字符串连接为单个str对象,产生一个新的字符串。如前所述,我们也可以使用*运算符对字符串做乘法。此外,需要注意的是这些操作不会添加任何额外的内容,例如在字符串之间插入空格。
(6)接下来,我们来了解一下字符串中的字符索引。添加下列几行代码:
str = 'Python NLTK' print(str[1]) print(str[-3])
首先,我们声明一个新的 string 对象。然后可以直接访问字符串中的第二个字符(y)。这里还有个小技巧:Python允许你在访问任何列表对象时使用负索引,比如说-1意味着最后一个成员,-2是倒数第二个成员,依此类推。例如,在前面代码的str对象中,索引7和-4是相同的字符N:
Output: <class 'str'> : Tuffy;Ali;Nysha;Tim <class 'list'> : ['My', 'dog', 'sleeps', 'on', 'sofa'] Text Additions : ganehsaganeshaganesha Text Multiplication : ganeshaganesha y L
3. 工作原理
我们使用split()函数将一个字符串变成了一个字符串列表,并使用join()函数将一个字符串列表变成了一个字符串。接下来我们了解了有关字符串的一些算术运算符的用法。
需要注意的是,我们不能在字符串中使用“-”(负号)和“/”(除法)运算符。最后,我们了解了如何在任一字符串中访问单个字符,特别值得一提的是,我们可以在访问字符串时使用负索引。
本段实例非常简单和直观,主要是介绍Python允许的一些常见和不常见的字符串操作。接下来,我们将在以上操作基础上继续学习一些字符串操作。
接下来,我们将了解子字符串、字符串替换以及如何访问一个字符串的所有字符。
1. 如何实现
(1)创建一个新的Python文件,命名为StringOps2.py并定义以下string对象:
str = 'NLTK Dolly Python'
(2)访问str对象中以第四个字符作为结束的子串。
print('Substring ends at:',str[:4])
我们知道索引从零开始,因此将返回由第0个到第3个字符组成的子串。运行代码,输出如下:
Substring ends at: NLTK
(3)访问str对象中从某个点开始直到末尾的子串:
print('Substring starts from:',str[11:] )
以上代码指示解释器返回str对象中从索引11到结束的一个子串。运行代码,得到以下输出:
Substring starts from: Python
(4)从str对象中访问包含Dolly的子串。添加以下行:
print('Substring :',str[5:10])
以上代码返回从索引5到10的字符,不包括第10个字符。输出是:
Substring : Dolly
(5)我们在前一段中已经了解了负索引在字符串操作中的应用。现在我们试试看它在获取子串中的作用:
print('Substring fancy:', str[-12:-7]) Run and check the output, it will be – Substring fancy: Dolly
这里得到的输出与上一步完全相同!为了理解这个结果,我们做一些计算:-1表示最后一个字符,-2是倒数第二个字符,依此类推。你将会发现[5:10]和[-12:-7]在这个例子中得出的子串是相同的。
(6)了解in操作符在if语句中的用法:
if 'NLTK' in str: print('found NLTK')
运行以上代码,程序的输出如下所示:
found NLTK
如上所示,in操作符会检查左边的字符串是否属于右边字符串的子串。
(7)了解str对象中replace函数的使用:
replaced = str.replace('Dolly', 'Dorothy') print('Replaced String:', replaced)
replace函数只需要两个参数。第一个是需要被替换的子字符串,第二个是用来替换前面子字符串的新子字符串。replace函数返回一个新的string对象,并且它不会修改调用它的字符串,运行代码,有如下输出:
Replaced String: NLTK Dorothy Python
(8)最后,迭代上面得到的replaced对象并访问它的每一个字符:
print('Accessing each character:') for s in replaced: print(s)
以上操作每次在新的一行输出replaced对象的每个字符,最终输出如下:
Output: Substring ends at: NLTK Substring starts from: Python Substring : Dolly Substring fancy: Dolly found NLTK Replaced String: NLTK Dorothy Python Accessing each character: N L T K D o r o t h y P y t h o n
2. 工作原理
字符串对象只是一个字符列表。正如第一步所示,我们可以像访问一个列表那样用for语句来访问字符串中的每个字符。任何列表的方括号内的字符“:”表示我们想要的一个子列表。
方括号内,如果字符“:”之后是一个数字n,表示我们希望获得一个从列表索引0开始到索引n-1结束的子列表。同样地,一个数字m后跟着字符“:”,则表示我们想要一个从列表索引m开始到列表末尾的子列表。
这个实例是从Python中访问PDF文件。首先,你需要安装PyPDF2库。
1. 准备工作
假设你已经安装了pip。然后,在Python2或Python3版本上用pip安装PyPDF2库,你只需要在命令行中运行以下命令:
pip install pypdf2
如果你成功安装了PyPDF2库,就完成了准备工作。与此同时,你需要通过以下链接下载一些我们将在本段用到的测试文档:
https://www.dropbox.com/sh/bk18dizhsu1p534/AABEuJw4TArUbzJf4Aa8gp5Wa?dl=0
2. 如何实现
(1)创建一个新的Python文件,命名为pdf.py并添加以下代码:
from PyPDF2 import PdfFileReader
这行代码会导入PyPDF2库中的PdfFileReader类。
(2)在上面创建的文件中添加如下Python函数,它的功能是读取一个PDF文件并返回其全文:
def getTextPDF(pdfFileName, password = '')
该函数需要两个参数,一个是你要读取的PDF文件路径,一个是这个PDF文件的密码(如果有的话)。可见,password 参数是可选的。
(3)现在我们来定义这个函数。在该函数下添加如下代码:
pdf_file = open(pdfFileName, 'rb') read_pdf = PdfFileReader(pdf_file)
第一行代码会以读取和反向查找模式打开文件。第一行本质是一个Python文件打开命令/函数,仅能打开非文本的二进制文件。第二行将打开的文件传递给PdfFileReader类,用于处理PDF文档。
(4)如果文件设置了密码保护,接下来是解密被密码保护的PDF文件:
if password != '': read_pdf.decrypt(password)
如果在函数调用时设置了密码,那么我们在解密这个文件时也同样需要密码。
(5)从PDF文件中读取文本:
text = [] for i in range(0,read_pdf.getNumPages()-1): text.append(read_pdf.getPage(i).extractText())
创建一个字符串列表,并将每一页的文本都添加到这个列表中。
(6)返回最终的输出结果:
return '\n'.join(text)
将列表中所有的字符串都连接起来,并且在每个字符串之间都加一个换行符,返回连接后的单一字符串。
(7)在pdf.py目录下创建另一个名为TestPDFs.py 的文件,添加以下导入语句:
import pdf
(8)现在我们打印输出两个文档中的文本,其中一个是受密码保护的,一个是未加密的:
pdfFile = 'sample-one-line.pdf' pdfFileEncrypted = 'sample-one-line.protected.pdf' print('PDF 1: \n',pdf.getTextPDF(pdfFile)) print('PDF 2: \n',pdf.getTextPDF(pdfFileEncrypted,'tuffy'))
输出:本实例的前六步只是创建了一个Python函数,并不向控制台输出内容,第七和第八步会输出以下内容:
This is a sample PDF document I am using to demonstrate in the tutorial. This is a sample PDF document password protected.
3. 工作原理
PyPDF2是用于提取PDF文件内容的一个纯Python库。该库有很多功能,可用于裁剪页面、叠加图像数字签名、创建新的PDF文件等。但是,对NLP工程师需要实现的文本分析任务来说,该库只用来读取内容。
在第二步中,以反向查找模式打开文件很重要,因为当加载文件内容时,PyPDF2模块试图从尾部开始读取文件内容。此外,如果PDF文件是受密码保护的,而你没有在访问文件前解密文件,Python解释器将抛出一个PdfReadError错误。
这里,我们将学习如何加载和读取Word/DOCX文档。用于读取Word/DOCX文件的相关库会更加全面,在这些库中我们还可以处理段落边界、文本样式以及对所谓的run对象的操作。我们将会了解以上提到的所有内容,因为这些内容在文本分析任务中是至关重要的。
Tip: 如果你没有安装Microsoft Word软件,你可以使用Liber Office和Open Office软件的开源版本来创建和编辑“.docx”文件。
1. 准备工作
假设你已经在你的机器上安装了pip,我们将使用pip来安装python-docx库。不要将它与另一个名为docx的库混淆,这是两个完全不同的库。我们将从python docx库中导入docx对象。在命令行中执行下面的命令将安装这个库:
pip install python-docx
成功安装了该库后,继续下一步,我们将在这个实例中使用一个测试文档,如果你已经通过本文第一段提供的链接下载了所有文档,你应该已具备相关文档。如果没有,请从以下链接下载sample-one-line.docx文档。
https://www.dropbox.com/sh/bk18dizhsu1p534/AABEuJw4TArUbzJf4Aa8gp5Wa?dl=0
现在,准备工作就全部完成了。
2. 如何实现
(1)创建一个新的Python文件,命名为word.py并添加以下导入代码:
import docx
这里只需导入python-docx模块的docx对象。
(2)定义getTextWord函数:
def getTextWord(wordFileName):
该函数需要一个字符串参数wordFileName,包含你要读取的Word文件的绝对路径。
(3)初始化doc 对象:
doc = docx.Document(wordFileName)
此时doc对象加载了你要读取的Word文件。
(4)接下来我们要从已经加载文档的doc对象中读取文本,添加以下代码来实现:
fullText = [] for para in doc.paragraphs: fullText.append(para.text)
首先初始化一个字符串列表fullText,然后采用for循环逐段从文档中读取文本,并把每段都放到fullText列表中去。
(5)然后,我们将所有的片段/段落连接为一个字符串对象,并将其作为函数的输出结果返回:
return '\n'.join(fullText)
通过以上操作,我们将fullText数组的所有元素用“\ n”分隔符连接起来,并返回连接后的对象。最后保存该Python文件并退出。
(6)创建另一个Python文件,命名为TestDocX.py,并添加以下导入声明:
import docx import word
这里只需导入docx库以及我们在前五步中实现的word.py文件。
(7)现在我们将要读取一个DOCX文件并使用我们在word.py中实现的API打印输出它的全部内容。添加以下两行代码:
docName = 'sample-one-line.docx' print('Document in full :\n',word.getTextWord(docName))
首先在第一行代码中初始化文档的路径,然后使用API打印输出文档的全部内容。当你运行这部分代码时,得到以下输出:
Document in full :
这是一个带有一些粗体文本、一些斜体文本和一些下划线文本的PDF示例文档。我们还嵌入了一个标题,如下所示:
This is my TITLE. This is my third paragraph.
(8)正如前面提到的,Word / DOCX文档是一个更加丰富的信息来源,除了提供文本内容外,还能提供很多信息。现在我们来看有关段落的信息。添加以下四行代码:
doc = docx.Document(docName) print('Number of paragraphs :',len(doc.paragraphs)) print('Paragraph 2:',doc.paragraphs[1].text) print('Paragraph 2 style:',doc.paragraphs[1].style)
以上代码的第二行打印出了给定文档中段落的数量。第三行打印出了文档中第二段的内容。而第四行将会打印出第二段的样式,比如在这个例子中的样式就是Title类型。当你运行以上代码后,输出将如下所示:
Number of paragraphs : 3 Paragraph 2: This is my TITLE. Paragraph 2 style: _ParagraphStyle('Title') id: 4374023248
(9)接下来,我们将了解什么是run对象。添加以下代码:
print('Paragraph 1:',doc.paragraphs[0].text) print('Number of runs in paragraph 1:',len(doc.paragraphs[0].runs)) for idx, run in enumerate(doc.paragraphs[0].runs): print('Run %s : %s' %(idx,run.text))
首先,我们获得文档第一段的全部内容。然后,我们获得第一段中run对象的数目。最后,我们把每个run对象打印输出。
(10)为了明确每个run对象的格式,添加以下代码:
print('is Run 0 underlined:',doc.paragraphs[0].runs[5].underline) print('is Run 2 bold:',doc.paragraphs[0].runs[1].bold) print('is Run 7 italic:',doc.paragraphs[0].runs[3].italic)
这段代码的各行分别在检查相应run对象的下划线样式、粗体样式以及斜体样式。最终输出如下:
Output: Document in full : This is a sample PDF document with some text in BOLD, some in ITALIC and some underlined. We are also embedding a Title down below. This is my TITLE. This is my third paragraph. Number of paragraphs : 3 Paragraph 2: This is my TITLE. Paragraph 2 style: _ParagraphStyle('Title') id: 4374023248 Paragraph 1: This is a sample PDF document with some text in BOLD, some in ITALIC and some underlined. We're also embedding a Title down below. Number of runs in paragraph 1: 8 Run 0 : This is a sample PDF document with Run 1 : some text in BOLD Run 2 : , Run 3 : some in ITALIC Run 4 : and Run 5 : some underlined. Run 6 : We are also embedding a Title down below Run 7 : . is Run 0 underlined: True is Run 2 bold: True is Run 7 italic: True
3. 工作原理
首先,我们在word.py文件中写了一个函数,它将读取给定的DOCX文件并返回一个包含文件全部内容的字符串对象。前面的输出内容大都是不需要解释的,我特别阐述了关于Paragraph和Run的输出内容。DOCX文件的结构可以用python-docx库的三个数据类型来表示,其中最高一级是Document对象。
每个文档都包含多个段落。文档中出现新的一行或一个回车,就表示开始一个新的段落。每个段落用多个Run对象表示段落内格式的变化,这里的格式包含有字体、尺寸、颜色和其他样式元素(如粗体、斜体、下划线等等)。这些元素每次发生变化时,都会创建一个新的Run对象。
现在我们要创建自己的语料库,而不是使用从互联网上得到的语料库。
1. 准备工作
在准备方面,我们将使用本文第一个实例中提到的Dropbox文件夹中的几个文件。如果你已经从那个文件夹中下载了全部的文件,那么你已经完成了准备工作。否则,请从
https://www.dropbox.com/sh/bk18dizhsu1p534/AABEuJw4TArUbzJf4Aa8gp5Wa?dl=0
下载如下文件:
如果你没有按照本文的顺序来完成实例,那么你需要先回头看看本文的前两个实例。我们将用到本文前两个实例中完成的两个模块 word.py和pdf.py。本段实例更多是关于本文前两个实例所做工作的应用以及语料库概念的应用。下面我们来看实际的代码。
2. 如何实现
(1)创建一个新的Python文件,命名为createCorpus.py并添加以下代码:
import os import word, pdf from nltk.corpus.reader.plaintext import PlaintextCorpusReader
我们导入os库用于与文件有关的操作,word库和pdf库是本文前两段完成的库,最后导入的PlaintextCorpusReader是为了完成语料库建立这一最终目标。
(2)编写一个简单的函数,用来打开并读取一个纯文本文件,并将其全部内容作为string对象返回。添加以下代码:
def getText(txtFileName): file = open(txtFileName, 'r') return file.read()
第一行代码定义了函数及其输入参数。第二行代码以只读方式打开文件(open函数的第二个参数r表示以只读方式打开)。第三行代码读取打开文件的内容并将其作为string对象返回。
(3)在磁盘或文件系统中创建一个新文件夹corpus。添加以下三行代码:
newCorpusDir = 'mycorpus/' if not os.path.isdir(newCorpusDir): os.mkdir(newCorpusDir)
第一行定义的string对象包含了新文件夹名,第二行检查该文件夹在磁盘或文件系统中是否存在,第三行则通过执行os.mkdir()函数在磁盘上创建一个给定名字的文件夹。以上代码执行后将在你的Python文件所在的工作目录下创建一个名为mycorpus的新文件夹。
(4)然后,逐个读取前面提到的三个文件。首先从纯文本文件开始,添加以下代码:
txt1 = getText('sample_feed.txt')
调用之前完成的getText函数,它将读取Sample_feed.txt文件并将输出结果存入名为txt1的字符串对象中。
(5)现在,添加以下代码来读取PDF文件:
txt2 = pdf.getTextPDF('sample-pdf.pdf')
这里使用了PDF.py模块的getTextPDF()函数,它将读取sample-pdf.pdf文件并将文件内容存入名为txt2的字符串对象中。
(6)最后,通过以下代码读取DOCX文件:
txt3 = word.getTextWord('sample-one-line.docx')
这里使用了word.py模块的getTexWord()函数,它将读取sample-one-line.docx文件并将文件内容存入名为txt3的字符串对象中。
(7)接下来,将上面读到的三个字符串对象写到磁盘文件中。添加以下代码:
files = [txt1,txt2,txt3] for idx, f in enumerate(files): with open(newCorpusDir+str(idx)+'.txt', 'w') as fout: fout.write(f)
(8)在mycorpus目录下,也就是我们之前存放文件的目录下新建一个PlainTextCorpus对象:
newCorpus = PlaintextCorpusReader(newCorpusDir, '.*')
以上一行代码看似简单,但是它在内部做了很多的文本处理,如识别段落、句子、单词等等。该函数的两个参数分别是语料库目录的路径以及要处理的文件名模式(这里我们已经设置corpus reader可以处理该目录下所有的文件)。通过以上步骤,我们创建了一个用户自定义的语料库。
(9)接下来,我们来看PlainTextCorpusReader是否加载正常。添加以下代码来进行测试:
print(newCorpus.words()) print(newCorpus.sents(newCorpus.fileids()[1])) print(newCorpus.paras(newCorpus.fileids()[0]))
第一行代码将打印输出语料库包含的所有单词数组(部分)。第二行代码将打印输出文件1.txt中的句子。第三行代码将打印输出文件0.txt中的段落:
Output: ['Five', 'months', '.', 'That', "'", 's', 'how', ...] [['A', 'generic', 'NLP'], ['(', 'Natural', 'Language', 'Processing', ')', 'toolset'], ...] [[['Five', 'months', '.']], [['That', "'", 's', 'how', 'long', 'it', "'", 's', 'been', 'since', 'Mass', 'Effect', ':', 'Andromeda', 'launched', ',', 'and', 'that', "'", 's', 'how', 'long', 'it', 'took', 'BioWare', 'Montreal', 'to', 'admit', 'that', 'nothing', 'more', 'can', 'be', 'done', 'with', 'the', 'ailing', 'game', "'", 's', 'story', 'mode', '.'], ['Technically', ',', 'it', 'wasn', "'", 't', 'even', 'a', 'full', 'five', 'months', ',', 'as', 'Andromeda', 'launched', 'on', 'March', '21', '.']], ...]
3. 工作原理
该实例最后一步的输出很简单直接,展示了各个对象不同的特征。输出内容的第一行是新语料库的单词列表,它与句子、段落、文件等更高级的结构没有关系。
第二行是1.txt文件中所有句子组成的列表,其中每个句子都是由该句子中单词组成的列表。
第三行是0.txt文件中所有段落组成的列表,其中每个段落对象又是由该段落中的句子组成的列表。从中可以发现,这些段落和句子保留了很多原有的结构。
丰富网站摘要(Rich Site Summary,RSS)信息源(feed)是一种计算机可读格式,用于传送互联网上定期更新的内容。大多数提供通知信息的网站以这种格式提供更新,例如新闻文章、在线出版物等。订阅者可以通过规范化格式定期访问其更新信息。
1. 准备工作
本段实例的目标是读取一个RSS信息源并访问其中的一条内容。为此,我们将使用全球之声(Mashable)提供的RSS信息源。全球之声是一个数字媒体网站。简而言之,它是一个科技和社交媒体的博客列表。该网站的RSS信息源网址(URL)是:
http://feeds.mashable.com/Mashable
另外,我们需要用feedparser库来读取RSS信息源。打开终端并运行以下命令即可在你的计算机上安装这个库:
pip install feedparser
安装好feedparser库后,我们就可以开始实现第一个读取RSS信息源的Python程序。
2. 如何实现
(1)创建一个新的Python文件,命名为rssReader.py,并添加以下代码:
import feedparser
(2)将全球之声信息源(Mashable feed)载入内存中,添加以下代码:
myFeed = feedparser.parse("http://feeds.mashable.com/Mashable")
myFeed对象包含全球之声信息源的第一页,通过feedparser自动下载和解析该信息源并填充到合适的位置。myFeed对象的条目列表将包含每个帖子(post)。
(3)检查当前信息源的标题并计算帖子数目:
print('Feed Title :', myFeed['feed']['title']) print('Number of posts :', len(myFeed.entries))
在第一行代码中,我们通过myFeed对象获取到了信息源的标题。在第二行代码中,我们计算了myFeed对象中entries对象的长度。如前所述,entries对象是一个包含解析后信息源中所有帖子的列表。运行代码,输出如下所示:
Feed Title: Mashable Number of posts : 30
标题是Mashable,当前,Mashable每次最多存放30个帖子到信息源。
(4)从entries列表中获取第一个post,并打印输出其标题:
post = myFeed.entries[0] print('Post Title :',post.title)
在第一行代码中,我们获取了entries列表中的第一个元素并将其加载到post对象中。在第二行代码中,我们打印输出了post对象的标题。运行代码,输出应该与以下内容相似:
Post Title: The moon literally blocked the sun on Twitter
这里提到输出内容应该与其相似而不是完全一样,是因为信息源在不断自我更新。
(5)访问post的原始HTML内容,并将其打印输出:
content = post.content[0].value print('Raw content :\n',content)
首先,我们访问post的内容对象并获取其具体值,打印输出如下:
Output: Feed Title: Mashable Number of posts : 30 Post Title: The moon literally blocked the sun on Twitter Raw content : <img alt="" src="http://www.hmttv.cn/uploadfile/2024/0806/20240806104718722.jpg" /><div style="float: right; width: 50px;"><a href="http://twitter.com/share?via=Mashable&text=The+moon+literally +blocked+the+sun+on+Twitter&url=http%3A%2F%2Fmashable.com%2F2017%2F 08%2F21%2Fmoon-blocks-sun-eclipse-2017- twitter%2F%3Futm_campaign%3DMash-Prod-RSS-Feedburner-All- Partial%26utm_cid%3DMash-Prod-RSS-Feedburner-All-Partial" style="margin: 10px;"> <p>The national space agency threw shade the best way it knows how: by blocking the sun. Yep, you read that right. </p> <div><div><blockquote> <p>HA HA HA I've blocked the Sun! Make way for the Moon<a href="https://twitter.com/hashtag/SolarEclipse2017?src=hash">#Solar Eclipse2017</a> <a href="https://t.co/nZCoqBlSTe">pic.twitter.com/nZCoqBlSTe</a></p> <p>— NASA Moon (@NASAMoon) <a href="https://twitter.com/NASAMoon/status/899681358737539073">Augus t 21, 2017</a></p> </blockquote></div></div>
3. 工作原理
互联网上大多数的RSS信息源都以时间顺序排列,将最新的帖子放到最上面。因此,在该实例中我们每次访问的都是信息源提供的最新内容。信息源本身是不断更新的。所以,每次运行程序时,输出的格式保持不变,但是输出的内容却可能发生改变,这取决于信息源更新的速度。
另外,我们在控制台直接输出原始的HTML文本而不是其文本内容。接下来,我们将解析HTML并从页面获取我们需要的信息。最后,本实例可以附加以下内容:读取你想要的任何信息源,将信息源中所有帖子的信息存储到磁盘,并利用它创建一个纯文本的语料库。当然,你可以从上一个和下一个实例中获得启发。
大多数情况下,你需要处理的网上数据都以HTML页面的形式存在。因此,我们认为有必要向你介绍Python的HTML解析方法。有很多Python模块可以用来解析HTML,在接下来的实例中,我们将使用BeautifulSoup4库来解析HTML。
1. 准备工作
BeautifulSoup4包适用于Python2和Python3。在使用这个包之前,我们需要提前下载并将它安装在解释器上。和之前一样,我们将使用pip来安装这个包。在命令行运行以下命令:
pip install beautifulsoup4
另外,你还需要本文Dropbox文件夹中的sample-html.html文件。如果你还没有下载该文件,请从以下链接下载:
https://www.dropbox.com/sh/bk18dizhsu1p534/AABEuJw4TArUbzJf4Aa8gp5Wa?dl=0
2. 如何实现
(1)完成所有准备工作后,从导入以下声明开始:
from bs4 import BeautifulSoup
从bs4模块中导入BeautifulSoup类,它将用于解析HTML。
(2)将一个HTML文件加载到BeautifulSoup对象中:
html_doc = open('sample-html.html', 'r').read() soup = BeautifulSoup(html_doc, 'html.parser')
在第一行代码中,我们将sample-html.html文件的内容加载到str对象html_doc中。然后,创建了一个BeautifulSoup对象,需要解析的HTML文件作为第一个参数,html.parser作为第二个参数。通过以上操作,BeautifulSoup对象使用html解析器来解析文档。它将文档内容加载到soup对象中进行解析以备使用。
(3)soup对象最主要、最简单且最有用的功能就是去除所有的HTML标签并获取文本内容。添加以下代码:
print('\n\nFull text HTML Stripped:') print(soup.get_text())
在soup对象上调用的get_text()方法将返回HTML标签去除后的文件内容。运行以上代码,将得到以下输出:
Full text HTML Stripped: Sample Web Page Main heading This is a very simple HTML document Improve your image by including an image. Add a link to your favorite Web site. This is a new sentence without a paragraph break, in bold italics. This is purely the contents of our sample HTML document without any of the HTML tags.
(4)有时不仅需要去除HTML标签,可能还需要获取特定标签的内容。访问其中的一个标签:
print('Accessing the <title> tag :', end=' ') print(soup.title)
soup.title将返回文件中的第一个标题(title)标签。以上代码的输出如下所示:
Accessing the <title> tag : <title>Sample Web Page</title>
(5)现在,我们需要某个HTML标签的文本内容。通过以下代码获取<h1>标签的内容:
print('Accessing the text of <H1> tag :', end=' ') print(soup.h1.string)
soup.h1.string命令将返回以<h1>标签开头的文本。以上代码的输出如下所示:
Accessing the text of <H1> tag : Main heading
(6)访问标签的属性。这里,我们将访问img标签的alt属性。添加以下代码行:
print('Accessing property of <img> tag :', end=' ') print(soup.img['alt'])
通过仔细观察,你会发现访问标签属性的语法和访问标签文本的语法是不同的。运行以上代码,得到以下输出:
Accessing property of <img> tag : A Great HTML Resource
(7)最后,一个HTML文件中同一类型的标签可能多次出现。使用“.”语法仅能获取文件中第一次出现的标签。为了获取所有的标签,我们将使用find_all()函数,如下所示:
print('\nAccessing all occurences of the <p> tag :') for p in soup.find_all('p'): print(p.string)
在BeautifulSoup对象上调用find_all()函数,参数是标签名,它将搜索整个HTML树并返回符合条件的标签列表。我们使用for循环来遍历该列表,并将BeautifulSoup对象中所有<p>标签的内容/文本打印并输出:
Output: Full text HTML Stripped: Sample Web Page Main heading This is a very simple HTML document Improve your image by including an image. Add a link to your favorite Web site. This is a new sentence without a paragraph break, in bold italics. Accessing the <title> tag : <title>Sample Web Page</title> Accessing the text of <H1> tag : Main heading Accessing property of <img> tag : A Great HTML Resource Accessing all occurences of the <p> tag : This is a very simple HTML document Improve your image by including an image. None
3. 工作原理
BeautifulSoup4是一个很方便的库,可以用于解析任何HTML和XML内容。它支持Python内置的HTML解析器,但是你也可以使用其他第三方的解析器,例如,lxml解析器和纯Python的html5lib解析器。
这里,我们使用Python内置的HTML解析器。如果你了解了HTML并会编写简单的HTML代码的话,输出结果是非常容易理解的。
关于作者:克里希纳·巴夫萨(KrishnaBhavsar)花了大约10年时间在各行业领域如酒店业、银行业、医疗行业等进行自然语言处理、社交媒体分析和文本挖掘方面的研究。他致力于用不同的NLP语料库如StanfordCoreNLP、IBM的 SystemText和BigInsights、GATE和NLTK来解决与文本分析有关的行业问题。纳雷什·库马尔(NareshKumar)曾为财富500强企业设计、实施和运行超大型因特网应用程序,在这方面他拥有超过十年的专业经验。他是一位全栈架构师,在电子商务、网络托管、医疗、大数据及分析、数据流、广告和数据库等领域拥有丰富的实践经验。
本文摘编自《自然语言处理Python进阶》,经出版方授权发布。
延伸阅读《自然语言处理Python进阶》
推荐语:本书包含的实例可以让你学会使用NLTK(处理NLP任务的主要Python平台)完成自然语言处理的各种任务,涵盖了自然语言理解、自然语言处理和句法分析等。
*请认真填写需求信息,我们会在24小时内与您取得联系。