2016-11-19 1 views
1

Je reçois les données sous forme de tableau HTML à partir de source externe -itérer sur le dictionnaire python pour récupérer uniquement les lignes nécessaires

from xml.etree import ElementTree as ET 

s = """<table> 
    <tr><th>Release</th><th>REFDB</th><th>URL</th></tr> 
    <tr><td>3.7.3</td><td>12345</td><td>http://google.com</td></tr> 
    <tr><td>3.7.4</td><td>456789</td><td>http://foo.com</td></tr> 
</table> 
""" 

Pour convertir html table au dictionnaire

table = ET.XML(s) 
rows = iter(table) 
headers = [col.text for col in next(rows)] 
for row in rows: 
    values = [col.text for col in row] 
    out = dict(zip(headers, values)) 

maintenant mon résultat attendu est comme ci-dessous étant donné que je vais passer la version Release de l'argument de la ligne de commande. python $ myscript.py 3.7.3 (j'ai un code pour cela) Je cherche une solution à boucle sur le dictionnaire quand il trouve la version particulière de sortie - dans mon cas, il est 3.7.3

Release Version - 3.7.3 
REFDB - 12345 
URL - http://google.com 
+0

'' 'out''' que contient la dernière ligne * *, – wwii

Répondre

1

Vous n'avez pas besoin d'un dictionnaire. Il suffit d'analyser le contenu de chaque ligne et voir si la version de sortie correspond à votre entrée:

#coding:utf-8 

import sys 
from lxml import html 

if len(sys.argv) != 2: 
    raise Exception("Please provide release version only") 

release_input = sys.argv[1].strip() 

data = """<table> 
    <tr><th>Release</th><th>REFDB</th><th>URL</th></tr> 
    <tr><td>3.7.3</td><td>12345</td><td>http://google.com</td></tr> 
    <tr><td>3.7.4</td><td>456789</td><td>http://foo.com</td></tr> 
</table> 
""" 

tree = html.fromstring(data) 
for row in tree.xpath('//tr')[1:]: 
    release, refbd, url = row.xpath('.//td/text()') 
    if release_input == release: 
     print("Release Version - {}".format(release)) 
     print("REFBD - {}".format(refbd)) 
     print("URL - {}".format(url)) 
     break 

print("{} release version wasn't found".format(release_input)) 
+0

Merci Andres, je recherchais exactement pour cela. – vpd

+0

@vpd Je suis content que ma réponse m'a aidé. S'il vous plaît n'oubliez pas d'accepter ma réponse (comme réponse à votre question) si cela vous a aidé à résoudre le problème :) –

1

En supposant qu'il n'y a qu'une seule ligne par version et que vous n'avez pas du tout besoin des autres versions, vous pouvez créer une fonction qui analyse le code HTML et renvoie la version dict dès qu'elle est trouvée. Si la version est introuvable, il pourrait revenir à la place None:

from xml.etree import ElementTree as ET 

s = """<table> 
    <tr><th>Release</th><th>REFDB</th><th>URL</th></tr> 
    <tr><td>3.7.3</td><td>12345</td><td>http://google.com</td></tr> 
    <tr><td>3.7.4</td><td>456789</td><td>http://foo.com</td></tr> 
</table> 
""" 

def find_version(ver): 
    table = ET.XML(s) 
    rows = iter(table) 
    headers = [col.text for col in next(rows)] 
    for row in rows: 
     values = [col.text for col in row] 
     out = dict(zip(headers, values)) 
     if out['Release'] == ver: 
      return out 

    return None 

res = find_version('3.7.3') 
if res: 
    for x in res.items(): 
     print(' - '.join(x)) 
else: 
    print 'Version not found' 

Sortie:

Release - 3.7.3 
URL - http://google.com 
REFDB - 12345 
0
from xml.etree import ElementTree as ET 

s = """<table> 
    <tr><th>Release</th><th>REFDB</th><th>URL</th></tr> 
    <tr><td>3.7.3</td><td>12345</td><td>http://google.com</td></tr> 
    <tr><td>3.7.4</td><td>456789</td><td>http://foo.com</td></tr> 
</table> 
""" 

table = ET.XML(s) 
rows = iter(table) 
headers = [col.text for col in next(rows)] 
master = {} 

for row in rows: 
    values = [col.text for col in row] 
    out = dict(zip(headers, values)) 
    if 'Release' in out: 
     master[out['Release']] = out 

# Use the release to get the right dict out of master 
print(master) 
if in_data in master: 
    for k, v in master[in_data]: 
     # print here 
     pass 
else: 
    print('Error') 
0
import lxml.html 
from collections import namedtuple 
s = """<table> 
    <tr><th>Release</th><th>REFDB</th><th>URL</th></tr> 
    <tr><td>3.7.3</td><td>12345</td><td>http://google.com</td></tr> 
    <tr><td>3.7.4</td><td>456789</td><td>http://foo.com</td></tr> 
    <tr><td>3.7.5</td><td>151515</td><td>http://foo.com</td></tr> 
</table> 
""" 
def info_gen(rows): 

    info = namedtuple('info', ['Release', 'REFDB', 'URL']) 
    for row in rows: 
     yield info(*row.xpath('.//text()')) 

html = lxml.html.fromstring(s) 
rows = html.xpath('//table//tr[td]') 

Release = input("Enter Release:") 
for info in info_gen(rows): 
    if Release in info: 
     print(info) 
     break 

sur:

Enter Release:3.7.5 
info(Release='3.7.5', REFDB='151515', URL='http://foo.com') 
0

Si vous accumulez les dictionnaires dans une liste:

result = [] 
for row in rows: 
    values = [col.text for col in row] 
    result.append(dict(zip(headers, values))) 

Vous pouvez filtrer la liste -

import operator 
value = '3.7.3' 
release = operator.itemgetter('Release') 
refdb = operator.itemgetter('REFDB') 
url = operator.itemgetter('URL') 
data = [d for d in result if release(d) == value] 

imprimer ensuite tous les dictionnaires qui ont obtenu passé le filtre -

f_string = 'Release Version - {}\nREFDB - {}\nURL - {}' 
for d in data: 
    print(f_string.format(release(d), refdb(d), url(d)))