如何使用python(bs4)阅读特定的html行

时间:2019-02-06 10:40:10

标签: javascript python html web-scraping beautifulsoup

首先,我是python和beautifulsoup的新手。

我无权访问html代码中链接的css,js文件。我也无法修改html页面。
如果那很重要,我在linux上并且正在使用python3。

我有以下页面:https://pastebin.com/VqRRe02P
托管的实际html代码未格式化,我通过在线html代码格式化程序运行了该代码。因此,我将在下面声明的行不会100%正确。

这是我当前正在使用的代码(并非实现所有功能):

import requests
import csv
from bs4 import BeautifulSoup, element
from operator import itemgetter

# ermöglicht schnelles Wechseln des Hosts (IP über die, das Interface lokal erreichbar ist)
a = 'http://192.168.68.128' # IP der Wärmepumpe
b = 'http://localhost' # für Entwicklungszwecke

# beziehe Daten vom Host
data = requests.get(b)

# lade Daten in BeautifulSoup
soup = BeautifulSoup(data.text, 'html.parser')

# Liste 'data' wird erstellt
data = []
var_name = []

# Alle Tabellen werden gesucht und in die Variable 'row' gespeichert
    for tr in soup.table.find_all('tr'):
        row = [td.text for td in tr.find_all('td')]
        var_name.append(row[0])
        if not row[1].startswith('\n') and row[2] in ['°C', 'bar']: # hier werden Filter angewendet, um nur relevante Daten zu speichern
        data.append(itemgetter(1)(row)) # die gefilterten Daten werden in die Liste 'data' gespeichert

print(var_name[2])


# die Strings von 'data' werden in den Datentyp float umgewandelt
data = list(map(float, data))

# hier werden die Unter- und Obergrenze festgelegt
 min_value = 0
max_value = 100

# Funktion überprüft, ob ein Wert die Untergrenze überschreitet
def check1():
    if data[1] < min_value:
        return(1)
    else:
        return(0)

    # Funktion überprüft, ob ein Wert die Obergrenze überschreitet
    def check2():
    if data[1] > max_value:
        return(1)
    else:
        return(0)

# Funktion überprüft, ob ein Fehler vorliegt
def check():
    if check1() + check2() is 2:
        return('Fehlercode: 2')
    if check1() + check2() is 1:
        return('Fehlercode: 1')
    else:
        return('OK')

if check() in 'Fehlercode: 2':
print('Email mit Fehlercode 2 senden')  # Platzhalter für Email Skript ausführen
if check() in 'Fehlercode: 1':
    print('Email mit Fehlercode 1 senden') # Platzhalter für Email Skript ausführen

 # Daten werden in eine CSV Datei namens 'auslesen.csv' gespeichert
with open('auslesen.csv', 'w') as auslesen:
    writer = csv.writer(auslesen)
    writer.writerow(data)
    auslesen.close()

/ * 我需要从以下几行的td元素中读取数据,并将其保存到变量中,然后将其输出到文本文件中,例如“ var1,var2,var3,..”。 线是158、204、264、339、557、579、920、937、954、1023、1042、1114、1168。 * /

我现在可以检查列表数据中的某个元素是否超过了最小值或最大值。
问题不是所有值都以度(°C)为单位,有些不是压力(bar),因此我还需要获得bar的最小值或最大值。我该怎么办?
而且我还想找出哪个值恰好超过了最小值或最大值,并包括其名称和度数或bar(名称在列表var_name中找到,但是索引不一样,因为列表行/数据中的某些数据得到了还试图删除document.write();仅使用.text.strip()获得实际名称无效。 不过需要过滤,因为否则我无法将字符串转换为浮点数。
例如,如果我们说“ Aussentemperatur”(html代码行158)为200.0,而不是1.4,则输出到csv文件中的期望输出为:
奥森温度,200,°C
如果有更多的值超过,请保持输出。
由于我不知道盐水热泵的行为,因此在构建html页面时,我希望它写一些字符串。在这种情况下,我还想输出给定的字符串:
奥氏体温度,未知数,°C

编辑:我将代码编辑为当前状态并添加了新段落

1 个答案:

答案 0 :(得分:0)

您可以根据是包含°C还是bar条目的格式正确的条目来决定要包括哪些行。可以使用正则表达式从脚本文本中提取传感器类型。

from collections import defaultdict
from bs4 import BeautifulSoup
import csv
import re

with open('index.html') as f_html:
    html = f_html.read()

soup = BeautifulSoup(html, "html.parser")
readings = defaultdict(list)    # Hold per sensor readings in a dictionary

with open('output.csv', 'w', newline='') as f_output:
    csv_output = csv.writer(f_output)
    csv_output.writerow(['Sensor', 'Value', 'Unit'])

    for tr in soup.table.find_all('tr'):
        row = [td.text for td in tr.find_all('td')]

        if not row[1].startswith('\n') and row[2] in ['°C', 'bar']:
            sensor = re.search(r'\((.*?)\)', row[0]).group(1)   # Extract sensor name from script text
            value = float(row[1])
            unit = row[2]

            readings[sensor].append(value)
            csv_output.writerow([sensor, value, unit])

for sensor in sorted(readings):
    data = readings[sensor]
    print(f'{sensor}:\n  Min {min(data)}, Max {max(data)}, {data}')

Python CSV library可用于轻松地将正确格式化为文件的数据行写入。

这将为您提供一个CSV文件,摘要如下:

Sensor,Value,Unit
Aussentemperatur,1.4,°C
Vorlauftemperatur,28.0,°C
Vorlauftemperatur,28.0,°C
Vorlauftemperatur,27.1,°C
Vorlauftemperatur,28.0,°C
Vorlauftemperatur,0.0,°C
Ruecklauftemperatur,27.1,°C
Ruecklauftemperatur,27.1,°C
Ruecklauftemperatur,28.0,°C
Ruecklauftemperatur,27.1,°C
Ruecklaufsolltemperatur,18.0,°C
Temperatur,0.0,°C
Kollektortemperatur,28.3,°C
MiniTempGKZwei,0.0,°C
Temperatur,16.3,°C
Temperatur,-999.9,°C
Solltemperatur,25.8,°C
MiniTempGKDrei,0.0,°C
Temperatur,35.1,°C
Temperatur,28.3,°C
Temperatur,0.0,°C
Solltemperatur,25.8,°C
Abtauendefuehler,17.6,°C
TempSpeicherReg,35.1,°C
TempSpeicherReg,28.3,°C
TempSpeicherReg,0.0,°C
RLTempKp,0.0,°C
VlTempKp,0.0,°C
Heissgastemperatur,0.0,°C
Raumtemperatur,35.1,°C
Raumtemperatur,28.3,°C
Raumtemperatur,0.0,°C
Raumtemperatur,0.0,°C
Raumtemperatur,0.0,°C
Temperatur,41.6,°C
Warmwasser,45.0,°C
Temperatur,0.0,°C
Wuelleneintritt,16.3,°C
Wuellenaustritt,17.6,°C
Niederdrucksensor,9.6,bar
Vorlauftemperatur,0.0,°C

defaultdict(list)可用于创建每个传感器的所有传感器读数的列表。然后,可以使用它显示之后的所有值,并显示每个传感器的最小值和最大值。例如,输出为:

Abtauendefuehler:
  Min 17.6, Max 17.6, [17.6]
Aussentemperatur:
  Min 1.4, Max 1.4, [1.4]
Heissgastemperatur:
  Min 0.0, Max 0.0, [0.0]
Kollektortemperatur:
  Min 28.3, Max 28.3, [28.3]
MiniTempGKDrei:
  Min 0.0, Max 0.0, [0.0]
MiniTempGKZwei:
  Min 0.0, Max 0.0, [0.0]
Niederdrucksensor:
  Min 9.6, Max 9.6, [9.6]
RLTempKp:
  Min 0.0, Max 0.0, [0.0]
Raumtemperatur:
  Min 0.0, Max 35.1, [35.1, 28.3, 0.0, 0.0, 0.0]
Ruecklaufsolltemperatur:
  Min 18.0, Max 18.0, [18.0]
Ruecklauftemperatur:
  Min 27.1, Max 28.0, [27.1, 27.1, 28.0, 27.1]
Solltemperatur:
  Min 25.8, Max 25.8, [25.8, 25.8]
TempSpeicherReg:
  Min 0.0, Max 35.1, [35.1, 28.3, 0.0]
Temperatur:
  Min -999.9, Max 41.6, [0.0, 16.3, -999.9, 35.1, 28.3, 0.0, 41.6, 0.0]
VlTempKp:
  Min 0.0, Max 0.0, [0.0]
Vorlauftemperatur:
  Min 0.0, Max 28.0, [28.0, 28.0, 27.1, 28.0, 0.0, 0.0]
Warmwasser:
  Min 45.0, Max 45.0, [45.0]
Wuellenaustritt:
  Min 17.6, Max 17.6, [17.6]
Wuelleneintritt:
  Min 16.3, Max 16.3, [16.3]

查看此输出,可能意味着您可能需要根据每个传感器的值过滤最小值和最大值。

如果您不想处理0-100范围之外的值,请更改为使用以下行:

        if 0 <= value <= 100:
            readings[sensor].append(value)
            csv_output.writerow([sensor, value, unit])