【问题标题】:Use Python to Parse a Website to CSV file使用 Python 将网站解析为 CSV 文件
【发布时间】:2021-06-11 00:45:22
【问题描述】:

我使用以下内容作为指导,并且对 python 是全新的,不知道如何为我的数据集实现它。

How to extract tables from websites in Python

我的问题是我想将下表转换为 CSV 格式,我认为上面的解决方案可以,但可惜,不行。

import requests
import pandas as pd

url = '
html = requests.get(url).content
df_list = pd.read_html(html)
df = df_list[-1]
print(df)
df.to_csv('my data.csv')

帕夫洛斯建议:

import csv, requests
from bs4 import BeautifulSoup


html = requests.get(url)
connection = html.text
soup = bs4.BeautifulSoup(connection, 'lxml')

list_header = []
for items in header: 
    try: 
        list_header.append(items.get_text()) 
    except: 
        continue  
        
HTML_data = soup.find_all("table")[0].find_all("tr")[1:] 
  
for element in HTML_data: 
    sub_data = [] 
    for sub_element in element: 
        try: 
            sub_data.append(sub_element.get_text()) 
        except: 
            continue
    data.append(sub_data) 

dataFrame = pd.DataFrame(data = data, columns = list_header) 

dataFrame.to_csv('Overflow.csv') 

【问题讨论】:

  • 由于您正在处理的是 XML,请使用 xmltodictrequests 查看此答案:stackoverflow.com/a/62004135/42346
  • 该页面上没有 HTML,只有通过 XSLT 重新设置样式以显示为 HTML 的 XML。但底层内容是 XML。

标签: python html xml csv


【解决方案1】:

先打开html:

import requests
import csv
from bs4 import BeautifulSoup

url = 'http://reports.ieso.ca/public/GenOutputbyFuelHourly/PUB_GenOutputbyFuelHourly.xml'
html = requests.get(url)
connection = html.text
soup = BeautifulSoup(connection, 'lxml')

然后我们需要提取表的表头。为此,让我们创建一个空列表,其中标题将保存在 for 循环中:

header = soup.find_all("table")[0].find("tr")
list_header = []
for items in header: 
    try: 
        list_header.append(items.get_text()) 
    except: 
        continue  

然后从表中获取数据。在第一个循环中我们迭代获取行,第二个循环我们迭代查找行中的单个元素:

HTML_data = soup.find_all("table")[0].find_all("tr")[1:] 
  
for element in HTML_data: 
    sub_data = [] 
    for sub_element in element: 
        try: 
            sub_data.append(sub_element.get_text()) 
        except: 
            continue
    data.append(sub_data) 

将其存储到 pandas DataFrame:

dataFrame = pd.DataFrame(data = data, columns = list_header) 

现在将 DataFrame 转换为 CSV:

dataFrame.to_csv('Overflow.csv') 

【讨论】:

  • 嘿 Pavlos,我收到错误消息:导入 csv,来自 bs4 的请求导入 BeautifulSoup
  • 对不起。我忘了提到 csv 需要与 BeautifulSoup 模块一样导入: import csv, from bs4 import BeautifulSoup 在文件开头应该可以解决问题(在两个单独的行中包含两个导入语句)
  • 谢谢帕夫洛斯,但我仍然遇到同样的错误。
  • 你用什么来运行你的代码?我正在使用 Anaconda,其中嵌入了 bs4。如果您仍然遇到相同的错误,您可能应该尝试安装该模块。以下链接包含有关如何执行此操作的详细说明:geeksforgeeks.org/beautifulsoup-installation-python。您可能需要为 csv 包做类似的事情
  • 嗨 Pavlos 我正在使用 Mu,但是我可以在其他脚本中使用 bs4。我很抱歉让你伤心。
【解决方案2】:

等一下! Pandas 1.3 将引入一个新功能来读写浅层 XML 文档:pandas.read_xml(甚至是DataFrame.to_xml)。目前,您的链接完全包含带有 XSLT 脚本的 XML 内容,以通过浏览器将其样式化为 HTML。查看源代码(Ctrl/Cmd + U)。

熊猫 1.3+

使用简化的非 HTML XSLT 脚本。 Online Demo

import pandas as pd

url = "http://reports.ieso.ca/public/GenOutputbyFuelHourly/PUB_GenOutputbyFuelHourly"

xsl = """\
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
                              xmlns:ieso="http://www.ieso.ca/schema">
   <xsl:output method="xml" omit-xml-declaration="no" indent="yes"/>
   <xsl:strip-space elements="*"/>

   <xsl:template match="/ieso:Document">
     <data>
       <xsl:apply-templates select="descendant::ieso:HourlyData"/>
     </data>
   </xsl:template>
    
   <xsl:template match="ieso:HourlyData">
     <row>
       <Day><xsl:value-of select="ancestor::ieso:DailyData/ieso:Day"/></Day>
       <Hour><xsl:value-of select="ieso:Hour"/></Hour>
       <NUCLEAR><xsl:value-of select="ieso:FuelTotal[ieso:Fuel = 'NUCLEAR']/ieso:EnergyValue/ieso:Output"/></NUCLEAR>
       <GAS><xsl:value-of select="ieso:FuelTotal[ieso:Fuel = 'GAS']/ieso:EnergyValue/ieso:Output"/></GAS>
       <HYDRO><xsl:value-of select="ieso:FuelTotal[ieso:Fuel = 'HYDRO']/ieso:EnergyValue/ieso:Output"/></HYDRO>
       <WIND><xsl:value-of select="ieso:FuelTotal[ieso:Fuel = 'WIND']/ieso:EnergyValue/ieso:Output"/></WIND>
       <SOLAR><xsl:value-of select="ieso:FuelTotal[ieso:Fuel = 'SOLAR']/ieso:EnergyValue/ieso:Output"/></SOLAR>
       <BIOFUEL><xsl:value-of select="ieso:FuelTotal[ieso:Fuel = 'BIOFUEL']/ieso:EnergyValue/ieso:Output"/></BIOFUEL>
       <Total_Output><xsl:value-of select="sum(.//ieso:EnergyValue/ieso:Output)"/></Total_Output>
     </row>
   </xsl:template>
   
</xsl:stylesheet>
"""

fuelhour_df = pd.read_xml(url, stylesheet=xsl)

fuelhour_df.to_csv("IESO_Fuel_Hour_Data.csv")

print(fuelhour_df)

#              Day  Hour  NUCLEAR  GAS  HYDRO  WIND  SOLAR  BIOFUEL  Total_Output
# 0     2021-01-01     1     9021  338   4781   161      0        0         14301
# 1     2021-01-01     2     9037  245   4363   141      0        0         13786
# 2     2021-01-01     3     9027  214   4028   238      0        0         13507
# 3     2021-01-01     4     9182  214   3681   428      0        0         13505
# 4     2021-01-01     5     9219  213   3172   277      0        0         12881
# ...          ...   ...      ...  ...    ...   ...    ...      ...           ...
# 1699  2021-03-12    20     8377  381   5441  3724      0       32         17955
# 1700  2021-03-12    21     8374  245   5118  3596      0       31         17364
# 1701  2021-03-12    22     8374  247   4579  3379      0       31         16610
# 1702  2021-03-12    23     8374  209   4457  3041      0       31         16112
# 1703  2021-03-12    24     8376  208   4219  2476      0       15         15294

熊猫

现在考虑使用第三方包lxmlread_xml 中的默认解析器)在本地运行 XSLT 转换,然后调用read_html

import lxml.etree as lx
import pandas as pd

url = "http://reports.ieso.ca/public/GenOutputbyFuelHourly/PUB_GenOutputbyFuelHourly"
xsl = "http://reports.ieso.ca/docrefs/stylesheet/GenOutputbyFuelHourly_HTML_t1-1.xsl"

doc = lx.parse(url)
style = lx.parse(xsl)

transformer = lx.XSLT(style)
html = transformer(doc)

fuelhour_df = pd.read_html(bytes(html), header=0)[2]

print(fuelhour_df)
#             Date  Hour  NUCLEAR  GAS  HYDRO  WIND  SOLAR  BIOFUEL  Total Output
# 0     2021-01-01     1     9021  338   4781   161      0        0         14301
# 1     2021-01-01     2     9037  245   4363   141      0        0         13786
# 2     2021-01-01     3     9027  214   4028   238      0        0         13507
# 3     2021-01-01     4     9182  214   3681   428      0        0         13505
# 4     2021-01-01     5     9219  213   3172   277      0        0         12881
# ...          ...   ...      ...  ...    ...   ...    ...      ...           ...
# 1699  2021-03-12    20     8377  381   5441  3724      0       32         17955
# 1700  2021-03-12    21     8374  245   5118  3596      0       31         17364
# 1701  2021-03-12    22     8374  247   4579  3379      0       31         16610
# 1702  2021-03-12    23     8374  209   4457  3041      0       31         16112
# 1703  2021-03-12    24     8376  208   4219  2476      0       15         15294

fuelhour_df.to_csv("IESO_Fuel_Hour_Data.csv")

【讨论】:

  • 我喜欢这个解决方案,非常干净和简单。你知道我如何添加附加功能吗?就像 xml 文件每天更新​​一样,它只是追加新数据而不是替换文件?
  • 为什么不每天重新运行这段代码以获取最新数据?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2017-04-03
  • 1970-01-01
  • 2018-10-01
  • 2021-07-04
  • 2018-03-08
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多