【问题标题】:Run Python Script on Subdirectories在子目录上运行 Python 脚本
【发布时间】:2020-03-06 10:57:16
【问题描述】:

我有一个包含子目录的父目录,每个子目录都包含一个 .html 文件,我想在该文件上运行我的代码。这需要一个 html 文件,并将导出一个包含表数据的相应 csv 文件。

我尝试了两种主要方法,但都无法正常工作,因为它无法相应地找到 .html 文件(不存在)。 注意: 子目录中每个文件的名称总是 index.html

Linux 命令行(基于使用 code1)

for file in */; do for file in *.html; do python html_csv2.py "$file"; done; done

代码1:

name = 'index.html'
html = utils.getFileContent(name)
#Get data from file
doc = SimplifiedDoc(html)
soup = bs(html, 'lxml')

title = (soup.select_one('title').text)
title = title.split(' -')
strain = title[0]
rows = []
tables = doc.selects('table.region-table')
tables = tables[:-1]
#print (type(tables))
for table in tables:
    trs = table.tbody.trs
    for tr in trs:
        rows.append([td.text for td in tr.tds])
#print(rows)
#print(type(rows))
#print("PANDAS DATAFRAME")
df_rows = pd.DataFrame(rows)
df_rows.columns = ['Region', 'Class', 'From', 'To', 'Associated Product', 'Class', 'Similarity']
df_rows['Strain'] = strain
df_rows = df_rows[['Strain','Region', 'Class', 'From', 'To', 'Associated Product', 'Class', 'Similarity']] 
#print(df_rows)
df_rows.to_csv (r'antismash_html.csv', index = False, header=True)
print('CSV CREATED')

在第二个 sn-p 中,我尝试使用 os 库相应地进入每个子目录。

代码 2:

import csv
from simplified_scrapy import SimplifiedDoc,req,utils
import sys
import pandas as pd
import lxml.html
from bs4 import BeautifulSoup as bs
import os

name = 'index.html'
html = utils.getFileContent(name)
# Get data from file
doc = SimplifiedDoc(html)
soup = bs(html, 'lxml')

cwd = os.getcwd()
print(cwd)
directory_to_check = cwd # Which directory do you want to start with?

def directory_function(directory):
      print("Listing: " + directory)
      print("\t-" + "\n\t-".join(os.listdir("."))) # List current working directory

# Get all the subdirectories of directory_to_check recursively and store them in a list:
directories = [os.path.abspath(x[0]) for x in os.walk(directory_to_check)]
directories.remove(os.path.abspath(directory_to_check)) #Dont' want it done in my main directory

def csv_create(name):
    title = (soup.select_one('title').text)
    title = title.split(' -')
    strain = title[0]
    rows = []
    tables = doc.selects('table.region-table')
    tables = tables[:-1]
    #print (type(tables))
    for table in tables:
        trs = table.tbody.trs
        for tr in trs:
            rows.append([td.text for td in tr.tds])
    #print(rows)
    #print(type(rows))
    #print("PANDAS DATAFRAME")
    df_rows = pd.DataFrame(rows)
    df_rows.columns = ['Region', 'Class', 'From', 'To', 'Associated Product', 'Class', 'Similarity']
    df_rows['Strain'] = strain
    df_rows = df_rows[['Strain','Region', 'Class', 'From', 'To', 'Associated Product', 'Class', 'Similarity']] 
    #print(df_rows)
    df_rows.to_csv (r'antismash_html.csv', index = False, header=True)
    print('CSV CREATED')
    #with open(name +'.csv','w',encoding='utf-8') as f:
    #    csv_writer = csv.writer(f)
    #    csv_writer.writerows(rows)

for i in directories:
      os.chdir(i)         # Change working Directory
      csv_create(name)      # Run your function


directory_function
#csv_create(name)

我尝试使用此处的示例:Python: run script in all subdirectories,但无法相应地执行。

【问题讨论】:

    标签: python linux command-line subdirectory


    【解决方案1】:

    或者,您可以考虑使用glob.glob()。但请注意通过在 glob 表达式中指定路径来从您打算搜索的文件夹中搜索 - 或 cd'ing 进入文件夹。

    glob 会给你一个相对路径的平面列表。

    >>> import glob
    >>> 
    >>> files = glob.glob('**/*.py', recursive=True)
    >>> len(files)
    3177
    >>> files[0]
    '_wxWidgets-3.0.2/build/bakefiles/wxwin.py'
    >>> 
    

    这里有一些 glob 表达式示例的文档:https://docs.python.org/3.5/library/glob.html

    如果您从一个包含大量嵌套子文件夹的文件夹开始在驱动器上进行递归搜索,它将使解释器陷入困境,直到它完成 - 或者您终止会话。

    【讨论】:

    • 感谢您的跟进,是否可以只为 .html 文件指定,或者因为我的文件名称有一个固定名称输入 (name = 'index.html'),我可以合并这个 glob命令?
    • 是的..如果我理解正确的话。如果您想要某个文件夹下所有 html 文件的相对路径,'**/*.html' 将是一个基本的 glob 模式。或/users/me/projects/web/**/*.html
    • 它将返回我的子目录列表以及相应的文件['index3/index.html', 'index1/index.html', 'index2/index.html']。它无法将对象 name 识别为文件本身,从而给出错误 TypeError: expected str, bytes or os.PathLike object, not list
    • @Biohacker 该错误表明您没有将字符串与另一个类似对象进行比较。检查您的代码以确保您正在将字符串与字符串进行比较。
    【解决方案2】:

    试试这个。

    import os
    from simplified_scrapy import utils
    def getSubDir(name,end=None):
      filelist = os.listdir(name)
      if end:
        filelist = [os.path.join(name,l) for l in filelist if l.endsWith(end)]
      return filelist
    subDir = getSubDir('./') # The directory which you want to start with
    for dir in subDir:
      # files = getSubDir(dir,end='index.html')
      fileName = dir+'/index.html'
      if not os.path.isfile(fileName): continue
      html = utils.getFileContent(fileName)
    

    【讨论】:

    • 非常感谢您之前在 html_extraction 方面为我提供的帮助。当我使用这行代码时,它只针对一个特定文件。我尝试将 csv-create 函数放入和退出 for 循环。但是,它只为子目录列表中的最后一个目录创建 csv 文件,而不是为每个相应的子目录创建 csv 文件。 ['html_csv.py', 'index3', 'html_csv2.py', 'antismash_html.csv', 'html2csv.py', 'index1', 'index2']
    • @Biohacker 我更新了答案。看看是不是你想要的
    • 我想我没有正确澄清,我只想保留最初提到的一个主 csv 文件,其中包含原始 html 文件中的所有表格。换句话说,我只想在每个子目录中拥有新的 csv 文件(所有表都在同一个 csv 中)及其各自的 html。基本上每个子目录都会有一个html和一个csv文件
    • @Biohacker 这有什么问题吗?粘贴你的目录结构,我帮你改代码。
    • 由于某种原因,它给了我错误,因为我的子目录中有子目录,所以它继续在子目录中搜索 index.html,尽管它已经被找到了,我只想让它去我的第一个子目录,然后回到父目录,然后继续执行此操作。这是我的代码 pastebin.com/M44iMGbL
    猜你喜欢
    • 2014-09-06
    • 2023-01-30
    • 2013-06-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-03-15
    • 1970-01-01
    相关资源
    最近更新 更多