Je récupère les données de plusieurs tables d'URL. Mon code me permet d'obtenir un tel csv (en utilisant le point-virgule comme coma ... EUROPE)

a;1  -------- 1st URL
b;2
c;3
d;4
e;5
a;7 ---------- 2nd URL
b;3
c;5
d;8
e;9
a;9 ---------- 3rd URL
b;3
y;5

L'URL --- ne fait pas partie du CSV. C'est juste pour vous montrer où commencent les données pour URL1, et ainsi de suite.
Je ne sais jamais à l'avance combien de champs une URL va contenir et quels sont les champs qu'elle va contenir. Je veux arriver à un CSV bien organisé ressemblant à ceci (avec l'exemple):

Name ; 1stUrl ;2ndURl ;3rd Url
a;1;7;9
b;2;3;3
c;3;5;ø
d;4;8;ø
e;5;9;ø
y;ø;ø;5

Je ne me soucie pas beaucoup de l'ordre des a, b, c, d. Les champs peuvent être dans l'ordre qu'ils préfèrent le plus.

Le truc, c'est que j'ai deux problèmes: - quand le code rencontre un nouveau champ, il doit l'ajouter à la liste des champs (exemple du champ 'y'). - le code doit laisser un espace vide / vide; ø; lorsqu'il n'y a pas de clé dans l'URL de ce champ.

J'ai mal essayé quelque chose mais ce n'est clairement pas ça. Même conceptuellement, je ne suis pas là.

from collections import *
import csv

def parse_csv(content, delimiter = ';'):
  csv_data = []
  for line in content.split('\n'):
    csv_data.append( [x.strip() for x in line.split( delimiter )] ) # strips spaces also
  return csv_data


s =parse_csv(open('raw.csv','rU', encoding='utf8').read())
print(len(s))
dic = defaultdict(list)
for n in range(0,len(s)):
    if (len(s[n]) == 2):
        key = s[n][0]
        val = s[n][1]
        print(key)
        print(val)


writer = csv.writer(open('dict.csv', 'w',encoding='utf8'), delimiter=';')
for key, value in dico.items():
   writer.writerow([key, value])

Qu'en pensez-vous? Toute aide serait appréciée les gars :)!

0
BoobaGump 23 juil. 2015 à 01:37

2 réponses

Meilleure réponse
from bs4 import BeautifulSoup
import csv
import urllib.request
from collections import *


def parse_csv(content, delimiter = ';'):  ##We use here ";" to parse CSV because of the European way of dealing with excel-csv
  csv_data = []
  for line in content.split('\n'):
    csv_data.append( [x.strip() for x in line.split( delimiter )] ) # strips spaces also
  return csv_data

List_of_list_of_pairs=[]
List_of_pairs=[]

list_url=parse_csv(open('url.csv','rU').read())


for i in range(0,len(list_url)) :
    List_of_pairs = []

    url=str(list_url[i][0]) ## read URL from an array coming from an Url-CSV
    page=urllib.request.urlopen(url)
    soup_0 = BeautifulSoup(page.read(),"html.parser")
    restricted_webpage= soup_0.find( "div", {"id":"ingredients"} )
    readable_restricted=str(restricted_webpage)
    soup=BeautifulSoup(readable_restricted,"html.parser")


    trs = soup.find_all('tr')

    for tr in trs:
        tds = tr.find_all("td")

        try: #we are using "try" because the table is not well formatted. This allows the program to continue after encountering an error.
            Nutriments = str(tds[0].get_text().strip())
            print(Nutriments)
        # This structure $isolate the item by its column in the table and converts it into a string.
            Quantity = str(tds[1].get_text().strip())
            print(Quantity)
            Pair=[Nutriments,Quantity]
            List_of_pairs.append(Pair)

        except:
            print ("bad tr string")
            continue #This tells the computer to move on to the next item after it encounters an error
    List_of_list_of_pairs.append(List_of_pairs)

print(List_of_list_of_pairs)
dico = defaultdict(list)

for n,list_of_pairs in enumerate(List_of_list_of_pairs):
    for i,pairs in enumerate(list_of_pairs):
        if (len(pairs) == 2):
             cle = pairs[0]
             val = pairs[1]
             while (len(dico[cle]) < n):
                   dico[cle].append('ND')
             dico[cle].append(val)
for cle in dico:
    while (len(dico[cle]) < n):
            dico[cle].append('ND')


import csv
with open("dict2csv.csv", 'w',encoding='utf8') as outfile:
   csv_writer = csv.writer(outfile, delimiter=';', quotechar='|', quoting=csv.QUOTE_MINIMAL,)

   for k,v in dico.items():
       csv_writer.writerow([k] + v)
0
BoobaGump 23 juil. 2015 à 21:55

Vous pouvez avoir des objets list comme valeur pour votre dict. C'est donc aussi simple que:

content = """a;1
b;2
c;3
d;4
e;5
a;7
b;3
c;5
d;8
e;9
a;9
b;3
y;5"""

csv_data = []
for line in content.split('\n'):
    csv_data.append( [x.strip() for x in line.split(';')] )

s = csv_data
dic = {}
for n in range(0,len(s)):
    if (len(s[n]) == 2):
        key = s[n][0]
        val = s[n][1]
        if key not in dic:
            dic[key] = []
        dic[key].append(val)

Et maintenant dic c'est:

{'a': ['1', '7', '9'],
 'b': ['2', '3', '3'],
 'c': ['3', '5'],
 'd': ['4', '8'],
 'e': ['5', '9'],
 'y': ['5']}

C'est ce que tu voulais, je suppose.

En passant, je vous déconseille fortement d'utiliser from package_xx import * car cela peut encombrer votre environnement.

0
Challensois 22 juil. 2015 à 23:27