Python - 网页抓取HTML表格并打印到CSV文件

4

我对Python还非常陌生,但是我想构建一个网络爬虫工具,可以从在线的HTML表中提取数据,并将其以相同格式打印到CSV中。

这是HTML表格的示例(它非常庞大,因此我只提供几行)。

<div class="col-xs-12 tab-content">
        <div id="historical-data" class="tab-pane active">
          <div class="tab-header">
            <h2 class="pull-left bottom-margin-2x">Historical data for Bitcoin</h2>

            <div class="clear"></div>

            <div class="row">
              <div class="col-md-12">
                <div class="pull-left">
                  <small>Currency in USD</small>
                </div>
                <div id="reportrange" class="pull-right">
                    <i class="glyphicon glyphicon-calendar fa fa-calendar"></i>&nbsp;
                    <span>Aug 16, 2017 - Sep 15, 2017</span> <b class="caret"></b>
                </div>
              </div>
            </div>

            <table class="table">
              <thead>
              <tr>
                <th class="text-left">Date</th>
                <th class="text-right">Open</th>
                <th class="text-right">High</th>
                <th class="text-right">Low</th>
                <th class="text-right">Close</th>
                <th class="text-right">Volume</th>
                <th class="text-right">Market Cap</th>
              </tr>
              </thead>
              <tbody>

                <tr class="text-right">
                  <td class="text-left">Sep 14, 2017</td>
                  <td>3875.37</td>     
                  <td>3920.60</td>
                  <td>3153.86</td>
                  <td>3154.95</td>
                  <td>2,716,310,000</td>
                  <td>64,191,600,000</td>
                </tr>

                <tr class="text-right">
                  <td class="text-left">Sep 13, 2017</td>
                  <td>4131.98</td>     
                  <td>4131.98</td>
                  <td>3789.92</td>
                  <td>3882.59</td>
                  <td>2,219,410,000</td>
                  <td>68,432,200,000</td>
                </tr>

                <tr class="text-right">
                  <td class="text-left">Sep 12, 2017</td>
                  <td>4168.88</td>     
                  <td>4344.65</td>
                  <td>4085.22</td>
                  <td>4130.81</td>
                  <td>1,864,530,000</td>
                  <td>69,033,400,000</td>
                </tr>                
              </tbody>
            </table>
          </div>

        </div>
    </div>

我特别想重新创建一个表格,并使用提供的相同列标题:"日期","开盘价","最高价","最低价","收盘价","交易量","市值"。 目前,我已经能够编写一个简单的脚本,它将基本上转到URL,下载HTML,使用BeautifulSoup解析,然后使用'for'语句获取td元素。 下面是我的代码示例(URL被省略)和结果:

from bs4 import BeautifulSoup
import requests
import pandas as pd
import csv

url = "enterURLhere"
page = requests.get(url)
pagetext = page.text

pricetable = {
    "Date" : [],
    "Open" : [],
    "High" : [],
    "Low" : [],
    "Close" : [],
    "Volume" : [],
    "Market Cap" : []
}

soup = BeautifulSoup(pagetext, 'html.parser')

file = open("test.csv", 'w')

for row in soup.find_all('tr'):
    for col in row.find_all('td'):
        print(col.text)

样例输出

有没有人能够指点一下如何将数据拉取重新格式化成表格?谢谢。


请查看CSV模块:https://docs.python.org/2/library/csv.html - FelixEnescu
1个回答

9

运行代码,您将从该表中获得所需的数据。要尝试并从此元素提取数据,您只需要在上面粘贴整个html元素,并将其包装在html=''' '''中。

import csv
from bs4 import BeautifulSoup

outfile = open("table_data.csv","w",newline='')
writer = csv.writer(outfile)

tree = BeautifulSoup(html,"lxml")
table_tag = tree.select("table")[0]
tab_data = [[item.text for item in row_data.select("th,td")]
                for row_data in table_tag.select("tr")]

for data in tab_data:
    writer.writerow(data)
    print(' '.join(data))

我试图将代码分解成几个部分,以便您理解。上面的代码是一个嵌套的for循环。以下是它单独执行的步骤:

from bs4 import BeautifulSoup

soup = BeautifulSoup(html,"lxml")
table = soup.find('table')

list_of_rows = []
for row in table.findAll('tr'):
    list_of_cells = []
    for cell in row.findAll(["th","td"]):
        text = cell.text
        list_of_cells.append(text)
    list_of_rows.append(list_of_cells)

for item in list_of_rows:
    print(' '.join(item))

结果:

Date Open High Low Close Volume Market Cap
Sep 14, 2017 3875.37 3920.60 3153.86 3154.95 2,716,310,000 64,191,600,000
Sep 13, 2017 4131.98 3789.92 3882.59 2,219,410,000 68,432,200,000
Sep 12, 2017 4168.88 4344.65 4085.22 4130.81 1,864,530,000 69,033,400,000

我不得不进行一些调整,但这个完美地运作了。感谢您的分享和花费时间来帮助我。我可以问一下您如何描述这个逻辑吗?我的理解是:
  1. BeautifulSoup将HTML内容转换为可读格式
  2. table_tag被定义为在soup中找到的第一个表的选择
  3. tab_data首先获取所选列标题中的文本,而row_data则从table_tag中提取剩余部分,因为脚本在其中运行?
  4. 您能否解释一下写入for语句的原因?
了解逻辑将非常有帮助。
- user8508478
谢谢,Shahin - 这太棒了。我实际上发现了一个有趣的问题,现在正在尝试解决它。如果您注意到2017年9月13日的输出,您将看到缺少一列。那是因为该行中前两个<td>值具有相同的值。是否有任何方法可以防止Python仅获取唯一值? - user8508478

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接