【问题标题】:Python csv.writerows() Writes to Many Columns on One Row and Not to Many Rows and One Column as Desired/ExpectedPython csv.writerows() 写入一行上的多列,而不是所需/预期的多行和一列
【发布时间】:2019-10-06 03:23:45
【问题描述】:

问题和问题是:为什么csv.writerows() 只输出到一行上的多列,而不是按照期望和预期输出到多行和一列?

以下是详细信息:

我需要从各个网站页面收集大量电子邮件,而我没有时间复制/粘贴每封电子邮件。

所以我使用 Python 中的一些标准库以及第三方库 Beautiful Soup 4 开发了一个 HTML 网页电子邮件抓取工具。

我开发的脚本连接到网页,或者在这种情况下:连接到我计算机上的本地文件。

该脚本可以很好地从 HTML 文件中抓取和收集所有 HTML 锚标记 (<a></a>),然后将它们编译成锚标记列表。

然后它使用正则表达式提取电子邮件地址,然后将每个电子邮件地址的两个实例(在锚标记中找到)全部小写,以便我可以将它们组合成一组唯一的 e - 邮件地址。

然后我将这组唯一的电子邮件地址转换为电子邮件地址列表,然后使用 Python 列表对象的sort() 方法将它们按字母顺序排列。

然后我将这个按字母顺序排列的电子邮件列表转换为按字母顺序排列的电子邮件元组。

然后,我将这个按字母顺序排列的电子邮件元组附加到一个仅包含一个项目的列表中(即,写入 CSV 文件时不会将每个电子邮件字符串分成测试中发现的多个列)。

然后我将这个包含元组的 List 写入 CSV 文件,但是 writerows() 方法将它们写入只有多列的一行。

我想将每个电子邮件地址字符串写入一列中的多行。

感谢您的帮助。

## IMPORT MODULES
## IMPORT MODULES
## IMPORT MODULES

import urllib
import bs4
import re
import pprint
import csv


## DECLARE VARIABLES
## DECLARE VARIABLES
## DECLARE VARIABLES

## EMPTY LIST FOR SCRAPED E-MAILS
ListOfEmails = []

# EMPTY SET FOR SCRAPED E-MAILS 
SetOfEmails = set()

## HEADERS FOR OUTPUT TO CSV FILE
##headers = ['emails'] 

## ROWS FOR E-MAILS FOR OUTPUT TO CSV FILE
ListWithOneTuple = []


## BEGIN MAIN PROGRAM
## BEGIN MAIN PROGRAM
## BEGIN MAIN PROGRAM

## OPEN LOCAL HTML FILE; READ THE HTML DOCUMENT
file = urllib.request.urlopen("file:///c://Python372/local_venv/index.html")
##print(file)
##print(type(file))
##print("\n")

## PARSE THE HTML; MAKE BEAUTIFUL SOUP
soup = bs4.BeautifulSoup(file, features="html.parser")
##print(soup)
##print(type(soup))
##print("\n")

## FIND ALL <a> ANCHOR TAGS; MAKE LIST OF ANCHOR TAGS
ListOfAnchors = soup.find_all("a")
##pprint.pprint(ListOfAnchors)
##print("\n")
##print("Number of Anchor Tags = ", len(ListOfAnchors))
##print("\n")

## FOR EACH ELEMENT IN LIST OF ANCHORS...
for each in ListOfAnchors:
    ##print(each)

    ## CONVERT EACH BEAUTIFUL SOUP OBJECT INTO STRING
    each = str(each)
    ##print(type(each))

    ## REGEX TO EXTRACT E-MAILS TO LIST
    ListOfMatches = re.findall("([a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+\.[a-zA-Z0-9-.]+)", each)     
    ##print("ListOfMatches = ", type(ListOfMatches))

    ## FOR EACH ELEMENT IN LIST, MAKE E-MAILS LOWERCASE
    for email in ListOfMatches:

        ## CONVERT E-MAILS TO LOWERCASE
        EmailLowercase = email.lower()
        ##print(EmailLowercase, type(EmailLowercase))
        ##print("\n")

        ## APPEND E-MAILS TO LIST OF E-MAILS
        ListOfEmails.append(EmailLowercase)

## TEST PRINT LIST OF E-MAILS
##print("\n")    
##print("ListOfEmails = ", ListOfEmails)
##print(type(ListOfEmails), len(ListOfEmails))

## CONVERT LIST OF E-MAILS TO SET OF E-MAILS
SetOfEmails = set(ListOfEmails)

## TEST PRINT SET OF E-MAILS
##print("\n") 
##print("SetOfEmails = ", SetOfEmails)
##print(type(SetOfEmails), len(SetOfEmails))

## CONVERT SET OF E-MAILS BACK TO LIST OF E-MAILS FOR NEXT STEP ALPHABETIC SORTING
ListOfEmailsAlphabetic = list(SetOfEmails)

## ALPHABETIZE LIST OF E-MAILS
ListOfEmailsAlphabetic.sort()

## TEST PRINT ALPHABETIC LIST OF E-MAILS
print("\n") 
print(ListOfEmailsAlphabetic, type(ListOfEmailsAlphabetic), len(ListOfEmailsAlphabetic))

## CONVERT ALPHABETIC LIST OF E-MAILS TO TUPLE OF ALPHABETIC E-MAILS    
TupleOfEmailsAlphabetic = tuple(ListOfEmailsAlphabetic)    
print(TupleOfEmailsAlphabetic, type(TupleOfEmailsAlphabetic), len(TupleOfEmailsAlphabetic))

## APPEND TUPLE OF ALPHABETIC E-MAILS TO LIST TO MAKE LIST OF ONE TUPLE ITEM
ListWithOneTuple.append(TupleOfEmailsAlphabetic)

## TEST PRINT ROWS FOR CSV OUTPUT
print("\n")
print(ListWithOneTuple, type(ListWithOneTuple), len(ListWithOneTuple)) 

## OPEN CSV FILE TO OUTPUT LIST OF E-MAILS
with open('CSVofEmails.csv','w', newline='') as CSVFile:
    FileCSV = csv.writer(CSVFile, delimiter=';')
    ##FileCSV.writerow(headers)
    FileCSV.writerows(ListWithOneTuple)



## END MAIN PROGRAM
## END MAIN PROGRAM
## END MAIN PROGRAM

## GAME OVER
## GAME OVER
## GAME OVER

【问题讨论】:

  • newline='' 已经为空。它不工作。我现在将其删除以测试您的建议,但这并不能解决问题。电子邮件列表仍然只打印到一行中的多列。

标签: python csv beautifulsoup


【解决方案1】:

这应该可行。

你能像这样改变最后一段代码吗?

content = [[i] for i in ListWithOneTuple[0]]

# OPEN CSV FILE TO OUTPUT LIST OF E-MAILS
with open('CSVofEmails.csv', 'w', newline='') as CSVFile:
    FileCSV = csv.writer(CSVFile, delimiter=';')
    # FileCSV.writerow(headers)
    FileCSV.writerows(content)

这行得通。 CSV.writerows,实际上接受这样的列表 [[column, column], [column, column]],其中外部列表​​是行,内部是列。

【讨论】:

  • newline='' 已经为空。它不工作。我现在将其删除以测试您的建议,但这并不能解决问题。电子邮件列表仍然只打印到一行中的多列。
  • @JerusalemProgrammer 你可以试试 newline='\n' 吗?
  • 根据您的建议,我刚刚尝试了newline='\n',但这也会产生与打印到一行中多列的所有电子邮件相同的结果。
  • @JerusalemProgrammer 可以像FileCSV.writerows(ListOfEmailsAlphabetic)这样直接写列表吗?您正在将该列表转换为一个元组,然后再转换为具有该元组的一个列表。因为我没有 index.html,所以我无法运行和检查。
  • @JerusalemProgrammer 请尝试我的最后一次编辑。它对我有用。
猜你喜欢
  • 1970-01-01
  • 2019-10-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多