【问题标题】:How do I read all html-files in a directory recursively?如何递归读取目录中的所有 html 文件?
【发布时间】:2018-07-02 06:18:33
【问题描述】:

我正在尝试将所有 html 文件 Doctype 打印到 txt 文件中。我没有使用 Python 的经验,所以请多多包涵。 :)

最终脚本应该根据 html 文件中设置的 Doctype 中给出的 html 版本从 html 文件中删除元素。我也尝试在 PHP 中列出文件,并且它在某种程度上有效。我认为 Python 是完成这项任务的更好选择。

下面的脚本是我现在得到的,但我不知道如何编写一个“for each”来递归地获取 arkivet 文件夹中每个 html 文件的 Doctype。我目前只打印文件名和扩展名,我不知道如何获取它的路径,也不知道如何利用 BeautifulSoup 从文件中编辑和获取信息。

import fnmatch
from urllib.request import urlopen as uReq
import os
from bs4 import BeautifulSoup as soup
from bs4 import Doctype

files = ['*.html']
matches = []

for root, dirnames, filenames in os.walk("arkivet"):
    for extensions in files:
        for filename in fnmatch.filter(filenames, extensions):
            matches.append(os.path.join(root, filename))
            print(filename)

matches 是一个数组,但我不确定如何在 Python 中正确处理它。我想将文件夹名、带扩展名的文件名和它的文档类型打印到根目录下的文本文件中。

脚本在带有 Python 3.5(也存在 Python 2.x)的本地 Vagrant Debian 服务器上的 CLI 中运行。所有文件和文件夹都存在于服务器公共根目录下名为 arkivet(存档)的文件夹中。

任何帮助表示赞赏!我被困在这里:)

【问题讨论】:

  • 从字面上看,没有理由标记“PHP”,因为它与 PHP 完全无关。
  • 你能追溯你的全部错误吗?
  • @VikasDamodar 这个脚本没有错误。正如我在文本中描述的那样,它只吐出文件名和扩展名。 :) 只有我不知道怎么做剩下的。
  • 所以基本上你想读取一个目录下的所有html文件?
  • 当然它只“打印”文件名,这是您打印的唯一内容。文件路径在您的 matches 列表中(注意:它是 list 而不是 array - 这些是 Python 中的不同类型)。 wrt/ 你必须解析文件的 html 版本(使用真正的 html 解析器——beautifulsoup 可能是你最好的选择——基于正则表达式的方法并不可靠,或者需要大量调试,所以不要重新发明众所周知的方轮)。

标签: python arrays python-3.x


【解决方案1】:

如果你想读取特定目录中的所有 html 文件,你可以试试这个:

import os
from bs4 import BeautifulSoup

directory ='/Users/xxxxx/Documents/sample/'
for filename in os.listdir(directory):
     if filename.endswith('.html'):
         fname = os.path.join(directory,filename)
         with open(fname, 'r') as f:
             soup = BeautifulSoup(f.read(),'html.parser')
             # parse the html as you wish

【讨论】:

  • 是的,BeautifulSoup 很有用。然而,我试图利用 Doctype 模块来识别每个 html 文件的 doctype。不幸的是,BeautifulSoup 没有读取 doctype-element。我猜我汤将包含整个 html 文件,但 BS 无法识别持有 doctype 的特定元素。 :)
  • 当 OP 明确表示他必须进行递归搜索并且 alread_ 为此使用正确的函数 (os.walk) 时,为什么在您的示例中使用 os.listdir()
  • @brunodesthuilliers 那么,你会怎么做呢?我正在使用 os.walk(),但我还需要每个 html 文档的 doctype。
  • @ChristerJohansson 还有?为什么解析文件会有什么不同?只要你有完整的文件路径(你已经在matches列表中发布了代码),你过去的方式是无关紧要的。
  • @brunodesthuilliers 不同之处在于我不明白,所以如果你能给我看一个代码示例,我将非常感激。此外,BeautifulSoup 不会仅读取 html 的其他元素的 doctype。 :)
【解决方案2】:

Vikas 的答案可能正是您所要求的,但如果他对问题的解释有误,值得知道您在循环时可以访问所有这三个变量:root、dirnames 和 filenames .您当前只打印基本文件名:

print(filename)

也可以打印完整路径:

print(os.path.join(root, filename))

Vikas 通过使用不同的函数(os.listdir)解决了缺少目录名的问题,但我认为这将失去递归的能力。

您发布的 os.walk 的组合,以及 Vikas 发布的使用 open 读取文件的内部可能是您想要的?

【讨论】:

  • 正确,我只打印文件名。打印匹配项会在列表中显示一大堆文件名及其路径,而不是数组(如前面在 cmets 中所述)。但是,我也试图将 doctype 放入此列表。文本文件中的路径 + 文件名 + doctype 是我想要做的。稍后我想使用 doctype 来做一个 switch/case 来根据文件的 doctype 来编辑文件,但是这个特定的功能是为了以后的问题。
【解决方案3】:

由于您没有标记任何答案解决方案,我猜您从未完全得到答案。这是一段递归搜索文件、打印完整文件路径并在 html 文件中显示 Doctype 字符串(如果存在)的代码。

import os
from bs4 import BeautifulSoup, Doctype

directory = '/home/brian/Code/sof'
for root, dirnames, filenames in os.walk(directory):
    for filename in filenames:
        if filename.endswith('.html'):
            fname = os.path.join(root, filename)
            print('Filename: {}'.format(fname))
            with open(fname) as handle:
                soup = BeautifulSoup(handle.read(), 'html.parser')
                for item in soup.contents:
                    if isinstance(item, Doctype):
                        print('Doctype: {}'.format(item))
                        break

【讨论】:

  • 感谢您的贡献。这个sn-p只能在一定程度上起作用,似乎有一堆UnicodeDecodeError的。从无效的起始字节到无效的延续字节。我会把你的答案标记为正确的。也许 Python 毕竟不适合这个任务。
  • 用 Python 2.7 试过了,然后就可以正常工作了。但是它无法读取我所有的 html-files 文档类型,我必须手动查看这些文件并查看可能导致它的原因。也许 Python 2.7 只是跳过了 Python3 停止的文件。
猜你喜欢
  • 1970-01-01
  • 2018-03-05
  • 2017-05-18
  • 1970-01-01
  • 2020-03-13
  • 1970-01-01
  • 2011-04-26
  • 2011-09-27
  • 2013-05-17
相关资源
最近更新 更多