import requests
from bs4 import BeautifulSoup
r=requests.get("http://docs.oasis-open.org/cmis/CMIS/v1.1/os/CMIS-v1.1-os.html") # get page using requests
soup=BeautifulSoup(r.content)
s = soup.find_all(text=re.compile('\.pdf'))# find all .pdf's
print s
[u'http://docs.oasis-open.org/cmis/CMIS/v1.1/os/CMIS-v1.1-os.pdf', u'http://docs.oasis-open.org/cmis/CMIS/v1.1/csprd01/CMIS-v1.1-csprd01.pdf', u'http://docs.oasis-open.org/cmis/CMIS/v1.1/CMIS-v1.1.pdf']
使用requests和{a2}
编辑1:你可以跳到第3步,看看我是如何处理解析HTML的。在
我先假设您以前没有使用过HTML解析器。请原谅我,如果下面的话是傲慢的或冗长的;我只是试图彻底。在
在我们开始之前,我应该告诉您,我们在这里处理的是格式错误的HTML(例如,没有看到一个
</p>
),所以我们不能采取直接的方法。我们还要处理一个大文件,所以执行过程可能有点慢,而且容易出错。在如果您选择在您的项目中使用Python,那么有一个名为BeautifulSoup的流行模块可以帮助您处理糟糕的HTML。如果我们想用它从你的页面的某个部分(比如说,简介)捕获文本,我们将遵循以下步骤:
第1步
首先,您需要查看页面的HTML。在浏览器中,将页面向上拉后,右键单击该页面并单击“查看页面源代码”。在弹出的窗口中,您应该看到一个文本墙(超过38000行)。将文本保存到名为“CMIS-v1.1”的文件中-操作系统.html,并将该文件放在C驱动器的根文件夹中(为方便起见;如果不使用Windows,请将其放在其他位置)。我们会仔细检查一下,找出解析器需要什么。在
第2步
让我们试着弄清楚导言的内容。当我搜索第一行文本(“内容管理互操作性服务…”)时,我被带到第129行。这是摘要,所以我转到下一个实例:第617行。这就是我要找的文本,所以现在我需要找出它在HTML中是如何标记的。在
在浏览器中回顾页面(呈现的页面,而不是墙)。本节以短语“1简介”(第615行)开头。在墙上,它被标记为“h2”(也就是说,它在}之间。现在,'h2'标签在墙上很常见,但是这个标签有'chapterHead'类,这不是很常见。除此之外,头和文本看起来像是在一个带有'noindent'类的'p'标记内。(注意:我边打字边写;这些信息中的一些可能对我们提出的任何代码都没有帮助,但它应该有助于你的想法)。在
<h2>
和{我们知道如何查找章节(搜索“chapterHead”类)。我们现在找一个章节。在呈现的页面上,我看到了“1.4示例”。在墙上搜索第一行(“一组请求和响应…”)将我带到第878行。在第876行中,我在带有“sectionHead”类的“h3”标记中看到了该节的标题。此策略还将用于查找标记子节和子节的标记。在
理想情况下,每个章节节都包含在表示章节的标签中,小节将包含在表示章节的标签中,等等。这种理想的结构可以这样表示:
不幸的是,本文档中不存在这种结构。我们拥有的是:
我们必须按顺序检查这些标记,在遇到这些标记时对它们作出反应。在
根据我们所见,我们的战略如下:
<p>
,留意“h3”、“h4”和“h5”标记第3步
如果您没有安装Python,我会去here并下载Python3.x。完成后,打开一个命令控制台并执行以下操作:
现在,运行
python
在控制台中。我们接下来要做的任何事情都可以在控制台中逐行键入,或者存储在.py文件中并在以后运行。在要设置:
^{pr2}$前两行导入我们需要的模块。最后两行只是将HTML文件的内容读入
BeautifulSoup
类。soup
有很多方法可以使标记和类的搜索变得容易。执行这些行可能需要一段时间,因为文件太大。在
^{4}$first_chapter
包含第一个“h2”标记及其内容。由于此标记与其他章节、章节和小节处于同一级别,因此我们将使用它作为起点。在siblings
是一个生成器,它将把文档的内容逐段传递给我们。如果您在控制台中键入print(element)
,您应该会看到“h2”标记后面的文本(即,简介的第一段)。理想情况下,此文本将位于“p”标记中,但我们处理的不是格式良好的HTML。在每次运行
element = next(siblings)
,生成器都会传递文档树的同一级别上的元素(它不会传递任何嵌入的标记)。如果我们想知道标记的名称,我们可以使用element.name
获得它;如果元素是文本或注释标记,则它没有名称。在现在,为了构建XML,我们将使用
xml.etree.ElementTree
。在如果在控制台中输入
tostring(intro)
,应该会看到一些好看的XML。我们暂时删除sect1
。在最后,我们需要一种方法来跟踪遍历
siblings
时所处的文本级别。根据我在你的页面上看到的,小节在章节级别下上升到四个级别。让我们设置一些控制结构来检查标记的名称,以确定我们处于什么级别(这是为了激发灵感):我来解释一下逻辑:
depth
用于将header标记转换为深度级别(假设头与子节类型完全对应;如果这个假设是错误的,您可以尝试使用element.get('class')
检查元素的类)。在depth_tags
用于存储表示深度变化的标记(不包括'h2',因为我们只是做介绍)。在level
用于跟踪当前深度级别。在sects
用于跟踪当前的XML节点,我们可以向其中添加文本。在xml_tag
用于存储当前XML节点的标签。在last_sect
用于存储当前XML节点的父节点。在depth_tags
中的一个,我们将适当地更改XML节点:level
列表中添加一个“1”(因此,如果该列表之前是[1, 1]
,那么现在它将是[1, 1, 1]
)。在level
列表缩短为与级别对应的长度;我们还将增加更新列表的最后一个数字。(示例:最后一个标记是“h5”,当前标记是“h3”。如果level
列表以前是[1, 1, 3, 2]
,现在是[1, 2]
),我们还将缩短sects
列表,为新的XML节点腾出空间。在sects
列表添加一个新的XML节点。'.'.join(level)
将{我还没有测试过这个,但是即使它能完美地工作,我确信你需要小心处理'p'标记之外的文本(比如第一段我们找到)。在
结束语
我已经介绍了如何将(看起来很难看的)HTML转换为XML的基本原理。其他几点我没有提到:
element
中有很多“span”和“a”标记。使用element.text
将使它们消失,这对于只获取文本非常有用。如果您想保留它们,请尝试''.join(str(t) for t in element.contents)
。在相关问题 更多 >
编程相关推荐