2017-09-27 3 views
0

J'utilise BS4 sur Python 2.7.13 pour analyser les messages du forum d'un site Web que je vais mettre dans un fichier CSV. Mon problème est que seul le premier message dans le fil a des données sur le titre du fil, mais je veux que le titre du message apparaisse dans chaque ligne du fichier CSV que je crée des messages du forum. Chaque ligne doit avoir le titre du poste, l'auteur du message, la date et l'heure du message, ainsi que le contenu du message. Lorsque je recherche un auteur, une date/heure et un contenu, je reçois autant de résultats qu'il y a dans la page, donc 19 dans ce cas. Il devrait donc y avoir 19 lignes dans le fichier CSV. Cependant, je ne reçois qu'une seule ligne de sortie dans le CSV, et je suppose que BS4 ne peut trouver qu'une seule occurrence d'une balise "h4" avec l'attribut "post-name" alors que les trois autres données sont trouvées plusieurs fois. Puis-je écrire du code où la première occurrence du titre est répétée pour tous les articles de la page et placée dans le document CSV? J'ai essayé d'utiliser la syntaxe if/else, mais je n'ai pas trouvé un moyen de dire à BS4 que s'il ne trouve pas le titre pour un post suivant, il devrait juste inclure le soup.title initial.Répétez l'élément trouvé une fois dans la page plusieurs fois dans le fichier CSV (analyse de post de forum)

J'apprécie vraiment votre aide car je ne pouvais pas trouver une solution pour cela n'importe où. Peut-être que je cherche la mauvaise chose. Voici le code que je utilise:

from bs4 import BeautifulSoup 
import csv 
import urllib2 
page = urllib2.urlopen("http://en.community.dell.com/support-forums/desktop/f/3513/t/20015349?pi21953=1") 
soup = BeautifulSoup(page, "lxml") 

one = soup.findAll("h4", attrs={"post-name"}) 
two = soup.findAll("a", attrs={"internal-link view-user-profile"}) 
three = soup.findAll("a", attrs={"internal-link view-post"}) 
four = soup.findAll("div", attrs={"post-content user-defined-markup"}) 

posttitle = [] 
poster = [] 
postdateandtime = [] 
postcontent = [] 

for post in one: 
    text = BeautifulSoup(str(post).strip()).get_text().encode("utf-8").replace("\n", " ") 
    posttitle.append(text.strip()) 

for post in two: 
    text2 = BeautifulSoup(str(post).strip()).get_text().encode("utf-8").replace("\n", " ") 
    poster.append(text2.strip()) 

for post in three: 
    text3 = BeautifulSoup(str(post).strip()).get_text().encode("utf-8").replace("\n", " ") 
    postdateandtime.append(text3.strip()) 

for post in four: 
    text4 = BeautifulSoup(str(post).strip()).get_text().encode("utf-8").replace("\n", " ") 
    postcontent.append(text4.strip()) 

csvfile = open('test.csv', 'wb') 

writer = csv.writer(csvfile) 

writer.writerow(["Post Title", "Poster", "Post Date and Time", "Post Content"]) 

for posttitle, poster, postdateandtime, postcontent in zip(posttitle, poster, postdateandtime, postcontent): 
writer.writerow([posttitle, poster, postdateandtime, postcontent]) 

csvfile.close() 

Répondre

0

Vous pouvez zip_longest pour remplir les valeurs manquantes par l'argument fillvalue. Donnez juste le dernier élément du post-titre pour que le dernier titre soit utilisé pour tous les disparus:

from itertools import izip_longest 
for posttitle, poster, postdateandtime, postcontent in izip_longest(posttitle, poster, postdateandtime, postcontent, fillvalue=posttitle[-1): 
    writer.writerow([posttitle, poster, postdateandtime, postcontent]) 
+0

Je ne peux pas vous dire à quel point je suis reconnaissant de votre aide, tayfun! J'ai cherché une solution pendant des jours et cela devenait très stressant pour moi. Merci beaucoup pour une solution claire et concise, mon ami. J'apprécie vraiment votre temps! – Vlakoulis

+0

Heureux d'être utile @Vlakoulis :) – tayfun