【问题标题】:Unable to append new result *first* in an existing csv file having old data无法在具有旧数据的现有 csv 文件中附加新结果 *first*
【发布时间】:2020-02-18 00:10:14
【问题描述】:

我用 python 编写了一个脚本,它能够从网页中获取不同帖子的标题并将它们写入 csv 文件。由于该站点非常频繁地更新其内容,我喜欢首先将新结果附加到该 csv 文件中,其中已经有可用的旧标题列表。

我试过了:

import csv
import time
import requests
from bs4 import BeautifulSoup

url = "https://stackoverflow.com/questions/tagged/python"

def get_information(url):
    response = requests.get(url)
    soup = BeautifulSoup(response.content, 'lxml')
    for title in soup.select(".summary .question-hyperlink"):
        yield title.text

if __name__ == '__main__':
    while True:
        with open("output.csv","a",newline="") as f:
            writer = csv.writer(f)
            writer.writerow(['posts'])
            for items in get_information(url):
                writer.writerow([items])
                print(items)

        time.sleep(300)

上述脚本在运行两次时可以在旧结果之后追加新结果。

旧数据如下:

A
F
G
T

新数据为W,Q,U

当我重新运行脚本时,csv 文件应该如下所示:

W
Q
U
A
F
G
T

如何将新结果先附加到包含旧数据的现有 csv 文件中?

【问题讨论】:

  • 从您对我的回答的评论来看,您似乎对您的问题有一个更新。您使用什么代码进行插入,如何在定期运行时遇到问题?
  • 如果我让脚本运行 5 分钟睡眠 @Prune,将会有很多新的 csv 文件。
  • 如何拥有大量新文件?一次最多只能有两个。
  • 看答案:最后一步是将新文件移回旧文件名。不再有任何“第二个 csv 文件”。
  • 正如建议的那样,如果数据太大,您将不得不将旧数据存储在内存中,或者使用临时的第二个文件。另一种方法是在文件末尾正常写入数据,然后在读取文件时查找最后一个条目开始的位置。但这在这种情况下并不容易或可靠,因为每个条目都有任意大小,因此您必须猜测它的大小,在文件末尾查找它,然后读取并查找,直到找到一个标记。我知道这不是您想要的,但您必须按照答案中的建议进行操作。

标签: python python-3.x csv web-scraping


【解决方案1】:

将数据插入文件中除末尾之外的任何位置都需要重写整个内容。为此,无需先将其全部内容读入内存,您可以创建一个包含新数据的临时 csv 文件,将现有文件中的数据附加到该文件,删除旧文件并重命名新文件。

这是我的意思的示例(使用虚拟 get_information() 函数来简化测试)。

import csv
import os
from tempfile import NamedTemporaryFile

url = 'https://stackoverflow.com/questions/tagged/python'
csv_filepath = 'updated.csv'

# For testing, create a existing file.
if not os.path.exists(csv_filepath):
    with open(csv_filepath, 'w', newline='') as f:
        writer = csv.writer(f)
        writer.writerows([item] for item in 'AFGT')

# Dummy for testing.
def get_information(url):
    for item in 'WQU':
        yield item


if __name__ == '__main__':
    folder = os.path.abspath(os.path.dirname(csv_filepath))  # Get dir of existing file.

    with NamedTemporaryFile(mode='w', newline='', suffix='.csv',
                            dir=folder, delete=False) as newf:
        temp_filename = newf.name  # Save filename.
        # Put new data into the temporary file.
        writer = csv.writer(newf)
        for item in get_information(url):
            writer.writerow([item])
            print([item])

        # Append contents of existing file to new one.
        with open(csv_filepath, 'r', newline='') as oldf:
            reader = csv.reader(oldf)
            for row in reader:
                writer.writerow(row)
                print(row)

    os.remove(csv_filepath)  # Delete old file.
    os.rename(temp_filename, csv_filepath)  # Rename temporary file.

【讨论】:

    【解决方案2】:

    由于您打算更改表格中每个元素的位置,因此您需要将表格读入内存并重写整个文件,从新元素开始。

    您可能会发现 (1) 将新元素写入新文件,(2) 打开旧文件并将其内容附加到新文件,以及 (3) 将新文件移动到原始文件(旧) 文件名。

    【讨论】:

    • 除了重命名之外,您的建议似乎可行。查看脚本在用旧脚本重命名新脚本时引发的错误。 Traceback (most recent call last): File "C:\Users\WCS\Desktop\demo file\demo_script.py", line 36, in <module> os.rename("new_output.csv","output.csv") FileExistsError: [WinError 183] Cannot create a file when that file already exists: 'new_output.csv' -> 'output.csv'
    • 您未能发布失败的代码。您如何尝试用新文件替换旧文件?你需要用你的操作系统来解决这个问题。 看起来您尝试通过 Python os 命令执行此操作,只需 renameing 而无需先删除原始文件。
    • 是的——查看rename 的文档。查看martieau 答案的最后两行。另外,请注意,作为 Stack Overflow 问题的一部分,可以接受站外链接。
    猜你喜欢
    • 2020-12-14
    • 2021-10-11
    • 1970-01-01
    • 1970-01-01
    • 2021-09-20
    • 1970-01-01
    • 2014-05-03
    • 2020-12-26
    • 2018-08-03
    相关资源
    最近更新 更多