Autor Thema: Produktbewertungen: Auswertung und Übersicht  (Gelesen 160914 mal)

Jeong Jeong

  • Korsaren
  • Hero Member
  • *
  • Beiträge: 3.782
  • Autorin und Cosplayerin
    • Profil anzeigen
Re: Produktbewertungen: Auswertung und Übersicht
« Antwort #105 am: 08 Jan 2018, 19:49:45 »
Quick and dirty, aber trotzdem ganz ansehnlich:

Inoffizielle Publikationen

 :D

JohnLackland

  • Beta-Tester
  • Hero Member
  • ***
  • Beiträge: 3.003
  • Nicht Beißen!
    • Profil anzeigen
    • Oh Kultes
Re: Produktbewertungen: Auswertung und Übersicht
« Antwort #106 am: 08 Jan 2018, 20:20:34 »
That's cool ;-)
Spielst du schon oder diskutierst du noch über die Regeln?

Thallion

  • Moderator
  • Sr. Member
  • *****
  • Beiträge: 250
    • Profil anzeigen
Re: Produktbewertungen: Auswertung und Übersicht
« Antwort #107 am: 14 Jan 2018, 11:37:26 »
@4-USB-HUB: Meinst du du kannst das Script so ändern, dass eine Ausgabe nach Excel möglich ist?
Dann könnte ich nämlich noch ganz andere Auswertungen, zB nach Heldengrad, nach Ort etc. machen.
So, wie ich das auch für's DSA-Forum mache:
Beispiel Auswertung nach Region

4 Port USB Hub

  • Hero Member
  • *****
  • Beiträge: 1.047
  • Jetzt mit USB 3.0 Ports
    • Profil anzeigen
Re: Produktbewertungen: Auswertung und Übersicht
« Antwort #108 am: 13 Feb 2018, 12:07:03 »
(C*m + sum(B)) / (C + S)
Wie gesagt, ich werde es vermutlich umändern in "durchschnittliche Anzahl Stimmen * durchschnittliche mögliche Bewertung" und das jeweils für die Kategorie (also die Spielhelfen werden da eine andere Stimmzahl bekommen als die Abenteuer etc.).
Wobei ich auch da ein Maximum reinsetzen werde (bei den Abenteuern vermutlich so um die 30, bei den Spielhilfen 50 etc.).
Hier das Ergebnis vom Parser nach o.a. methode:

Hier die Sammlung aller Produktbewertungsthreads, inklusive Durchschnittsbewertung und Ranking.
Das script ist verfügbar unter https://github.com/zaboron/Splittermond/blob/master/parsebewertungen.py

Spielhilfen
Platz   Bewertung   Stimmen   Produkt   
11.5370Jenseits der Grenzen
21.6163Selenia - Kaiserreich unter den Monden
31.6286Bestien & Ungeheuer
41.6446Splittermond Einsteigerbox
51.6531Esmoda: Die Zitadelle der Unsterblichkeit
61.66172Splittermond: Die Regeln
71.7128Zhoujiang: Der Phönix im Schatten des Drachen
81.72169Splittermond: Die Welt
91.759Farukan: Unter dem Pfauenthron
101.7936Diener der Götter
111.89Die Flammensenke: Land der tausend Gefahren
121.826Die Surmakar - Unter Gleißender Sonne
131.8432Dakardsmyr
141.87108Mondstahlklingen
151.8925Das Unreich
161.9179Die Arwinger Mark
171.9946Bestienmeister
182.0765Splittermond: Die Götter

Zubehör
Platz   Bewertung   Stimmen   Produkt   
11.8366NSC-Heft mit SL-Schirm
22.1915Splittermond Tickleisten-Set Deluxe
32.2134Splittermond CD
42.2643Splittermond Tickleisten-Set
52.2721Splittermond Würfelset
62.3341Splittermond Zustandskarten

Kaufabenteuer
Platz   Bewertung   Stimmen   Produkt   
11.9527Die Seidene Stadt
21.9780Der Fluch der Hexenkönigin
32.0220Bis zum Hals (Dakardsmyr)
42.0224Ein Funke Mut (Unter Wölfen)
52.0226Das Geschenk der Seealben (Kristallsee-Anthologie)
62.0428Mord im Schwimmende Zirkus (An den Küsten der Kristallsee)
72.0626Pashtarische Päckchen (An den Küsten der Kristallsee)
82.0759Das Geheimnis des Krähenwassers
92.0937Kettenrasseln (Einsteigerbox)
102.113Das Heulen des Windes (Unter Wölfen)
112.124Im Auge des Sturms (Die Surmakar)
122.133Zügelloser Zorn (Die Surmakar)
132.1413Feuer und Flamme
142.1414Sommersonnenwende
152.1676Zwist der Geschwister (Arwinger Mark)
162.1811Die Totengräber von Dakardsmyr (Dakardsmyr)
172.184Tempel der tausend Tore (Verwunschene Mauern)
182.192Der Vulkan des Todes (Die Flammensenke)
192.192Das schwarze Labyrinth (Die Flammensenke)
202.192Wenn die Wasser verstummen (Verwunschene Mauern)
212.193Palast der tausend Zimmer (Verwunschene Mauern)
222.1914Zorn der Natur
232.26Das Wandernde Warenhaus (Mephisto #66)
242.26Letzter Wille (Esmoda)
252.27Drachenpakt
262.2124Des Seekönigs Zorn (An den Küsten der Kristallsee)
272.2220Das Mädchen mit den grünen Augen (Das Unreich)
282.244Der Schatten von Palitan (Zwischen den Welten)
292.2426Gejagt! (Unter Wölfen)
302.257Jagdfieber
312.269Wolfsjagd (Zwischen den Welten)
322.265Der Quell des Lebens (Alter Friede, neuer Streit)
332.274In Feindschaft verbunden (Mephisto Nr. 61)
342.286Der Abgrund (Alter Friede, neuer Streit)
352.2915Der Schimmerturm
362.313In Luft aufgelöst (Zwischen den Welten)
372.3123Der Pfad durchs Seelenmoor (Einsteigerbox)
382.3145Türme im Eis
392.3211Die lange Wacht (Das Unreich)
402.3452Seelenqualen (Arwinger Mark)
412.3722Im Zeichen der Schlange
422.438Auf Abwegen (Alter Friede, neuer Streit)

Kostenlos verfügbare Abenteuer
Platz   Bewertung   Stimmen   Produkt   
12.0451Die Nacht der Toten
22.2176Zwist der Geschwister (Arwinger Mark)
32.3845Türme im Eis
42.3816Ein Licht in dunkler Nacht
52.4152Seelenqualen (Arwinger Mark)
62.4247Die Bestie von Krahorst
72.5210Die Federn des Feiglings (Schnellstarter GRT 2016)
82.6930Nacht über Tannhag

Anthologien
Platz   Bewertung   Stimmen   Produkt   
12.04104An den Küsten der Kristallsee
22.163Unter Wölfen
32.29Verwunschene Mauern
42.3316Zwischen den Welten
52.4119Alter Friede, neuer Streit
Für Fetzenstein! Nieder mit Knax!

4 Port USB Hub

  • Hero Member
  • *****
  • Beiträge: 1.047
  • Jetzt mit USB 3.0 Ports
    • Profil anzeigen
Re: Produktbewertungen: Auswertung und Übersicht
« Antwort #109 am: 13 Feb 2018, 12:11:05 »
@4-USB-HUB: Meinst du du kannst das Script so ändern, dass eine Ausgabe nach Excel möglich ist?
Dann könnte ich nämlich noch ganz andere Auswertungen, zB nach Heldengrad, nach Ort etc. machen.
So, wie ich das auch für's DSA-Forum mache:
Beispiel Auswertung nach Region
hab das projekt mal aktualisiert.
Nun unter https://github.com/cvaliente/bewertungsparser
unter helper.options kannst du auf xlsx umschalten, dann kriegst du eine excel datei im projekt verzeichnis als output.
die thread ids finden sich nun unter helper.constants
Für Fetzenstein! Nieder mit Knax!

Thallion

  • Moderator
  • Sr. Member
  • *****
  • Beiträge: 250
    • Profil anzeigen
Re: Produktbewertungen: Auswertung und Übersicht
« Antwort #110 am: 23 Feb 2018, 09:53:07 »
Vielen Dank an 4 Port USB Hub für die Möglichkeit nun die Auswertung in Excel zu machen.

Ich die Auswertung mal nach DSAnews hochgeladen, inklusive Zusatzinfos wie Genre, Heldengrad, Ort, Zeit etc.

Hoffe es gefällt euch:

https://dsanews.de/abenteuerbewertungen-splittermond/

Kreggen

  • Beta-Tester
  • Hero Member
  • ***
  • Beiträge: 765
  • ... hat mal was geschrieben
    • Profil anzeigen
    • Elfenwolf.de
Re: Produktbewertungen: Auswertung und Übersicht
« Antwort #111 am: 23 Feb 2018, 10:27:50 »
Vielen Dank an 4 Port USB Hub für die Möglichkeit nun die Auswertung in Excel zu machen.

Ich die Auswertung mal nach DSAnews hochgeladen, inklusive Zusatzinfos wie Genre, Heldengrad, Ort, Zeit etc.

Hoffe es gefällt euch:

https://dsanews.de/abenteuerbewertungen-splittermond/

Hm. Beim "Schimmerturm" wird Kai Hirschfelder als Autor genannt ...  8) und es ist auch nicht 26. January 2017 erschienen ...  8)

Oh ... "Das Schwarze Labyrinth" aus dem Flammensenke-Band wird auf den 20. July 2015 datiert ...

Kann es sein, dass da in einigen Feldern was mit den Konvertierungen der Einträge schief läuft?
« Letzte Änderung: 23 Feb 2018, 10:41:56 von Kreggen »
Ich mag die blaue Farbe. Ehrlich!

Thallion

  • Moderator
  • Sr. Member
  • *****
  • Beiträge: 250
    • Profil anzeigen
Re: Produktbewertungen: Auswertung und Übersicht
« Antwort #112 am: 23 Feb 2018, 12:24:11 »
Danke für den Hinweis, da hat der Sverweis 2 Abenteuer miteinander vertauscht. Ist korrigiert.

Thallion

  • Moderator
  • Sr. Member
  • *****
  • Beiträge: 250
    • Profil anzeigen
Re: Produktbewertungen: Auswertung und Übersicht
« Antwort #113 am: 23 Feb 2018, 12:51:31 »
Und hier geht's zu den Spielhilfen:

https://dsanews.de/spielhilfenbewertungen-splittermond/


Die neue Durchschnitts-Methode werde ich noch als eigene Spalte ergänzen.

Olibino

  • Hero Member
  • *****
  • Beiträge: 1.114
    • Profil anzeigen
Re: Produktbewertungen: Auswertung und Übersicht
« Antwort #114 am: 23 Feb 2018, 13:37:18 »
Ich habe mir die Auswertung und das Excel mal angeschaut und habe noch 3 Anregungen, falls ihr da noch Arbeit investieren möchtet.

1) Einsteigerregeln oder Standardregeln. Dürfte für diejenigen die nach den Einsteigerregeln spielen eine wichtige Information sein. Gerade jetzt wo es endlich auch vermehrt Abenteuer für die Einsteigerregeln gibt
2) Wenn schon das Erscheinungsdatum, dann sollte man auch danach sortieren können (funktioniert nicht). Man möchte ja evtl. schon wissen, was aktuell ist und was schon recht alt.
3) Heldengrad bitte als Zahl. Überall in den Diskussionen hier werden Helden- oder Monstergrade als Zahl angegeben. Das ist unmittelbar klarer als "Suchender" und ähnliches

Thallion

  • Moderator
  • Sr. Member
  • *****
  • Beiträge: 250
    • Profil anzeigen
Re: Produktbewertungen: Auswertung und Übersicht
« Antwort #115 am: 23 Feb 2018, 14:02:12 »
Alle 3 Punkte sinnvoll. Mach ich bei Gelegenheit.

Thallion

  • Moderator
  • Sr. Member
  • *****
  • Beiträge: 250
    • Profil anzeigen
Re: Produktbewertungen: Auswertung und Übersicht
« Antwort #116 am: 25 Feb 2018, 12:08:32 »
@4 Port USB Hub: Hilfe, was mach ich falsch? Will die Excel-Ausgabe für die Tanelorn-Auswertungen implementieren.

#!/usr/bin/python
# coding=utf-8

import urllib.request
import xlsxwriter
from statistics import StatisticsError, mean
from bs4 import BeautifulSoup
from collections import namedtuple, OrderedDict
from operator import attrgetter
from multiprocessing.dummy import Pool as ThreadPool

# Collection of Thread IDs in several categories
Produktthreads = OrderedDict([
    ('Spielhilfen', [
100244 ,
99039 ,
98315 ,
103886

]),
    ('Abenteuer', [
97188 ,
98757 ,
100657 ,
103971
])
])

# maintain anthologies separately
Anthologien = OrderedDict([
                           ('Cthulhu - Ars Mathematica',[
                                            102159, 102160, 102158]),
                           ('Cthulhu - Dreissig',[
                                            101501, 101503, 101504, 101502]),
                           ('Cthulhu - The Final Revelation',[
                                            97284, 97285, 97286, 97287]),
                           ('Cthulhu - Die Goldenen Hände Suc´naaths',[
                                            98758, 98757, 98759]),
                           ('Shadowrun - Licht aus der Asche',[
                                            96028, 96027, 96026])
                           ])

# Add anthologies to collection to avoid duplicates
for Anthologie in Anthologien:
    for threadid in Anthologien[Anthologie]:
        if threadid not in Produktthreads['Abenteuer']:
            Produktthreads['Abenteuer'].append(threadid)

# URL of a thread (%d will be thread_id)
baseurl = "https://www.tanelorn.net/index.php?topic=%d.0"

# Number of parallel threads (should be equal to number of CPU cores)
concurrent_parses = 4


def bbcode(tag, string, value=None):
    """Return a text(string) enclosed by the bbcode tags"""
    if value:
        return'[' + tag + '=' + value + ']' + string + '[/' + tag + ']'
    else:
        return'[' + tag + ']' + string + '[/' + tag + ']'


def bbcodeurl(urlstring, urlname):
    """Return an bbcode url format for given url and description"""
    return bbcode('url', urlname, urlstring)


def bbbold(text):
    """Return the text with a bbcode bold tag"""
    return bbcode(tag='b', string=text)


def bbtt(text):
    """Return the text with a bbcode tt tag"""
    return bbcode(tag='tt', string=text)

def generate_xlsx(bewertungs_threads):
        # Create a workbook and add a worksheet.
        workbook = xlsxwriter.Workbook('Bewertungen.xlsx')
        worksheet = workbook.add_worksheet()

        # Start from the first cell. Rows and columns are zero indexed.
        row = 0
        col = 0

        # Iterate over the data and write it out row by row.
        for index, element in bewertungsthreads:
            worksheet.write(row, col, index + 1)
            worksheet.write(row, col + 1, element.Durchschnitt)
            worksheet.write(row, col + 2, element.Stimmen)
            worksheet.write(row, col + 3, element.url)
            worksheet.write(row, col + 4, element.name)
            row += 1

        workbook.close()


class bbtable():

    """creates the frame of a bbcode table"""

    def __init__(self, rows):
        """needs the rows as input for this table"""
        self.elements = rows

    def tablify(self, rows):
        """adds start and end tags for tables"""
        return str('[table]\r\n' + rows + '[/table]')

    def __str__(self):
        """prints table in bbcode format"""
        return(self.tablify(''.join(str(row) for row in self.elements)))


class tablerow(bbtable):

    """creates a bbcode table row with correct tags"""

    def cellify(self, rowfield):
        """encloses cells with correct tags"""
        return str('[td]' + str(rowfield) + '[/td]')

    def rowify(self, cells):
        """encloses rows with the correct tags"""
        return str('[tr]' + str(cells) + '[/tr]\r\n')

    def __str__(self):
        """adds cell and row tags to elements"""
        return(self.rowify(''.join(self.cellify(field) for field in self.elements)))


class tableheaderrow(tablerow):

    """adds a header row"""

    def cellify(self, rowfield):
        return str('[td]' + bbbold(rowfield) + bbtt('   ') + '[/td]')


class ProduktParser():

       
    def __init__(self, Produktthreads, Produkt = namedtuple('Produkt', 'name id url Stimmen Durchschnitt'), Produkte = [], Anthologien = [], baseurl = baseurl):
        """set base properties: URLs, thread ids, format"""
        self.Produkt = Produkt
        self.Produkte = Produkte
        self.baseurl = baseurl
        self.Produktthreads = Produktthreads
        self.Anthologien = Anthologien
        self.bewertungen = set(
            [item for sublist in self.Produktthreads.values() for item in sublist])
        self.pool = ThreadPool(concurrent_parses)
        self.pool.map(self.getProdukt, self.bewertungen)
        self.getAnthologie()

    def getProdukt(self, threadid):
        """collect information for selected thread id"""
        url = self.baseurl % threadid
        page = urllib.request.urlopen(url)
        soup = BeautifulSoup(page.read(), "html.parser")
        Produktname = soup.find('title').string.split('/')[0].strip()
        polls = soup.find('dl', {'class': 'options'})
        options = polls.findAll('dt', {'class': 'middletext'})
        votes = polls.findAll('span', {'class': 'percentage'})       
        ergebnis = dict(zip([[int(s) for s in option.string.replace("(","").split() if s.isdigit()][0] for option in options], [int(vote.string.split(' ')[0]) for vote in votes]))
        einzelvotes = [
            item for sublist in [[k] * v for k, v in ergebnis.items()] for item in sublist]
        try:
            durchschnitt = str(round(mean(einzelvotes), 2))
            stimmen = len(einzelvotes)
        except (ZeroDivisionError, StatisticsError) as e:
            durchschnitt = '0 / No votes yet'
            stimmen = 0
        self.Produkte.append(
            self.Produkt(Produktname, threadid, url, stimmen, durchschnitt))
       
    def getAnthologie(self):
        for Anthologie in self.Anthologien:
            Anthologiedurchschnittagg = 0
            Anthologiestimmen = 0
            for Spielhilfe in self.Produkte:
                if Spielhilfe.id in self.Anthologien[Anthologie]:
                    if  Spielhilfe.Durchschnitt != '0 / No votes yet':
                        Anthologiestimmen += Spielhilfe.Stimmen 
                        Anthologiedurchschnittagg += Spielhilfe.Stimmen * float(Spielhilfe.Durchschnitt)
            if Anthologiestimmen == 0:
                Anthologiedurchschnitt = '0 / No votes yet'
            else:
                Anthologiedurchschnitt = str(round(Anthologiedurchschnittagg/Anthologiestimmen, 2))
                         
            self.Produkte.append(
                self.Produkt(Anthologie, 0, 0, Anthologiestimmen, Anthologiedurchschnitt))
                   
               

    def generateTable(self, bewertungsthreads):
        """"generate a table for the threads"""
        return bbtable([tableheaderrow(['Platz', 'Bewertung', 'Stimmen', 'Produkt'])]
                       + [tablerow([index + 1, element.Durchschnitt, element.Stimmen, bbcodeurl(element.url, element.name)])
                          for index, element in enumerate(sorted(bewertungsthreads, key=attrgetter('Durchschnitt'), reverse=True))])



    def printProdukte(self):
        """"print the table"""
        for key, value in self.Produktthreads.items():
            print('\r\n' + bbbold(key))
            print(self.generateTable(
                [Spielhilfe for Spielhilfe in self.Produkte if Spielhilfe.id in value]))
           
        print('\r\n' + bbbold("Anthologien"))
        print(self.generateTable(
            [Spielhilfe for Spielhilfe in self.Produkte if Spielhilfe.name in [Anthologie for Anthologie in Anthologien]]))


if __name__ == '__main__':
    TanelornParser = ProduktParser(Produktthreads=Produktthreads, Anthologien=Anthologien)
    generate_xlsx(TanelornParser.get_all())
Traceback (most recent call last):
  File "D:/RPG/tanelornbewertungen-xls.py", line 219, in <module>
    generate_xlsx(TanelornParser.get_all())
AttributeError: 'ProduktParser' object has no attribute 'get_all'


Yinan

  • Hero Member
  • *****
  • Beiträge: 5.291
  • U3BsaXR0ZXJtb25k
    • Profil anzeigen
Re: Produktbewertungen: Auswertung und Übersicht
« Antwort #117 am: 25 Feb 2018, 12:54:53 »
Der Fehler ist, dass der Produkt-Parser kein "get_all()" kennt, wie die Fehlermeldung schon sagt.
Zeile 141 bis 214 ist der ProduktParser definiert, aber da wird kein "get_all" definiert. Folglich läuft er in einen Fehler.

Wenn ich das mit dem Original-Skript vergleiche, dann sollte es auch nicht "TanelornParser.get_all()" sein sondern "TanelornParser.printProdukte()".

Andererseits erwartet "generate_xlsx" einen Parameter den es selbst "bewertungs_threads" nennt und dass liefert ProduktParser nicht...
Insofern fehlt da irgendwo eine Funktion im ProduktParser das dir Daten zurück gibt in einer Form, die "generate_xlsx" erwartet.

Btw. wird "generate_xlsx" ebenfalls in einen Fehler laufen, selbst wenn es "get_all()" geben würde und dir das zurückliefert, was du willst.
Weil "generate_xlsx" hat den Parameter "bewertungs_threads", der aber in der Funktion gar nicht benutzt wird. Statt dessen wird in Zeile 88 auf "bewertungsthreads" (ohne _) verwiesen, welches nirgends definiert ist. Da bekommst du dann also gleich den nächsten Fehler.
« Letzte Änderung: 25 Feb 2018, 12:58:07 von Yinan »
Wenn nicht anders gesagt, dann befassen sich meine Aussagen zu Regeln niemals mit Realismus oder Simulationismus, sondern nur mit Balancing.
----
Space is GOD DAMN TERRIFYING! Novas and Hypernovas are natures reminder that we can be wiped out instantly at any given time.

Thallion

  • Moderator
  • Sr. Member
  • *****
  • Beiträge: 250
    • Profil anzeigen
Re: Produktbewertungen: Auswertung und Übersicht
« Antwort #118 am: 25 Feb 2018, 15:19:18 »
Ich glaube ich nähere mich. Aber ohne Hilfe von 4-USB-HUB wird das wohl nichts.

#!/usr/bin/python
# coding=utf-8

import urllib.request
import xlsxwriter
from statistics import StatisticsError, mean
from bs4 import BeautifulSoup
from collections import namedtuple, OrderedDict
from operator import attrgetter
from multiprocessing.dummy import Pool as ThreadPool

# Collection of Thread IDs in several categories
Produktthreads = OrderedDict([
    ('Spielhilfen', [
100244 ,
99039 ,
98315 ,
103886

]),
    ('Abenteuer', [
97188 ,
98757 ,
100657 ,
103971
])
])

# maintain anthologies separately
Anthologien = OrderedDict([
                           ('Cthulhu - Ars Mathematica',[
                                            102159, 102160, 102158]),
                           ('Cthulhu - Dreissig',[
                                            101501, 101503, 101504, 101502]),
                           ('Cthulhu - The Final Revelation',[
                                            97284, 97285, 97286, 97287]),
                           ('Cthulhu - Die Goldenen Hände Suc´naaths',[
                                            98758, 98757, 98759]),
                           ('Shadowrun - Licht aus der Asche',[
                                            96028, 96027, 96026])
                           ])

# Add anthologies to collection to avoid duplicates
for Anthologie in Anthologien:
    for threadid in Anthologien[Anthologie]:
        if threadid not in Produktthreads['Abenteuer']:
            Produktthreads['Abenteuer'].append(threadid)

# URL of a thread (%d will be thread_id)
baseurl = "https://www.tanelorn.net/index.php?topic=%d.0"

# Number of parallel threads (should be equal to number of CPU cores)
concurrent_parses = 4


def bbcode(tag, string, value=None):
    """Return a text(string) enclosed by the bbcode tags"""
    if value:
        return'[' + tag + '=' + value + ']' + string + '[/' + tag + ']'
    else:
        return'[' + tag + ']' + string + '[/' + tag + ']'


def bbcodeurl(urlstring, urlname):
    """Return an bbcode url format for given url and description"""
    return bbcode('url', urlname, urlstring)


def bbbold(text):
    """Return the text with a bbcode bold tag"""
    return bbcode(tag='b', string=text)


def bbtt(text):
    """Return the text with a bbcode tt tag"""
    return bbcode(tag='tt', string=text)


class bbtable():

    """creates the frame of a bbcode table"""

    def __init__(self, rows):
        """needs the rows as input for this table"""
        self.elements = rows

    def tablify(self, rows):
        """adds start and end tags for tables"""
        return str('[table]\r\n' + rows + '[/table]')

    def __str__(self):
        """prints table in bbcode format"""
        return(self.tablify(''.join(str(row) for row in self.elements)))


class tablerow(bbtable):

    """creates a bbcode table row with correct tags"""

    def cellify(self, rowfield):
        """encloses cells with correct tags"""
        return str('[td]' + str(rowfield) + '[/td]')

    def rowify(self, cells):
        """encloses rows with the correct tags"""
        return str('[tr]' + str(cells) + '[/tr]\r\n')

    def __str__(self):
        """adds cell and row tags to elements"""
        return(self.rowify(''.join(self.cellify(field) for field in self.elements)))


class tableheaderrow(tablerow):

    """adds a header row"""

    def cellify(self, rowfield):
        return str('[td]' + bbbold(rowfield) + bbtt('   ') + '[/td]')


class ProduktParser():

    def __init__(self, Produktthreads, Produkt = namedtuple('Produkt', 'name id url Stimmen Durchschnitt'), Produkte = [], Anthologien = [], baseurl = baseurl):
        """set base properties: URLs, thread ids, format"""
        self.produkt_ergebnisse = []
        self.anthologie_ergebnisse = []
        self.Produkt = Produkt
        self.Produkte = Produkte
        self.baseurl = baseurl
        self.Produktthreads = Produktthreads
        self.Anthologien = Anthologien
        self.bewertungen = set(
            [item for sublist in self.Produktthreads.values() for item in sublist])
        self.pool = ThreadPool(concurrent_parses)
        self.pool.map(self.getProdukt, self.bewertungen)
        self.getAnthologie()
        self.calculate_average()

    def calculate_average(self):
        for produkt in self.produkt_ergebnisse:
            produkt.calculate_mean()
 

    def getProdukt(self, threadid):
        """collect information for selected thread id"""
        url = self.baseurl % threadid
        page = urllib.request.urlopen(url)
        soup = BeautifulSoup(page.read(), "html.parser")
        Produktname = soup.find('title').string.split('/')[0].strip()
        polls = soup.find('dl', {'class': 'options'})
        options = polls.findAll('dt', {'class': 'middletext'})
        votes = polls.findAll('span', {'class': 'percentage'})       
        ergebnis = dict(zip([[int(s) for s in option.string.replace("(","").split() if s.isdigit()][0] for option in options], [int(vote.string.split(' ')[0]) for vote in votes]))
        einzelvotes = [
            item for sublist in [[k] * v for k, v in ergebnis.items()] for item in sublist]
        try:
            durchschnitt = str(round(mean(einzelvotes), 2))
            stimmen = len(einzelvotes)
        except (ZeroDivisionError, StatisticsError) as e:
            durchschnitt = '0 / No votes yet'
            stimmen = 0
        self.Produkte.append(
            self.Produkt(Produktname, threadid, url, stimmen, durchschnitt))
       
    def getAnthologie(self):
        for Anthologie in self.Anthologien:
            Anthologiedurchschnittagg = 0
            Anthologiestimmen = 0
            for Spielhilfe in self.Produkte:
                if Spielhilfe.id in self.Anthologien[Anthologie]:
                    if  Spielhilfe.Durchschnitt != '0 / No votes yet':
                        Anthologiestimmen += Spielhilfe.Stimmen 
                        Anthologiedurchschnittagg += Spielhilfe.Stimmen * float(Spielhilfe.Durchschnitt)
            if Anthologiestimmen == 0:
                Anthologiedurchschnitt = '0 / No votes yet'
            else:
                Anthologiedurchschnitt = str(round(Anthologiedurchschnittagg/Anthologiestimmen, 2))
                         
            self.Produkte.append(
                self.Produkt(Anthologie, 0, 0, Anthologiestimmen, Anthologiedurchschnitt))

    def get_produkt_ergebnisse(self, produkt_typ):

        result = [produkt for produkt in self.produkt_ergebnisse
                                 if produkt.thread_id in self.Produktthreads[produkt_typ]]
        return enumerate(sorted(result))

    def get_anthologie_ergebnisse(self):
        return enumerate(sorted(self.anthologie_ergebnisse))

    def get_all(self):
        return enumerate(sorted(self.produkt_ergebnisse))
                   

    def generateTable(self, bewertungsthreads):
        """"generate a table for the threads"""
        return bbtable([tableheaderrow(['Platz', 'Bewertung', 'Stimmen', 'Produkt'])]
                       + [tablerow([index + 1, element.Durchschnitt, element.Stimmen, bbcodeurl(element.url, element.name)])
                          for index, element in enumerate(sorted(bewertungsthreads, key=attrgetter('Durchschnitt'), reverse=True))])

    def printProdukte(self):
        """"print the table"""
        for key, value in self.Produktthreads.items():
            print('\r\n' + bbbold(key))
            print(self.generateTable(
                [Spielhilfe for Spielhilfe in self.Produkte if Spielhilfe.id in value]))
           
        print('\r\n' + bbbold("Anthologien"))
        print(self.generateTable(
            [Spielhilfe for Spielhilfe in self.Produkte if Spielhilfe.name in [Anthologie for Anthologie in Anthologien]]))

def generate_xlsx(bewertungs_threads):
    # Create a workbook and add a worksheet.
    workbook = xlsxwriter.Workbook('Bewertungen.xlsx')
    worksheet = workbook.add_worksheet()

    # Start from the first cell. Rows and columns are zero indexed.
    row = 0
    col = 0

    # Iterate over the data and write it out row by row.
    for index, element in bewertungs_threads:
        worksheet.write(row, col, index + 1)
        worksheet.write(row, col + 1, element.Durchschnitt)
        worksheet.write(row, col + 2, element.Stimmen)
        worksheet.write(row, col + 3, element.url)
        worksheet.write(row, col + 4, element.name)
        row += 1

    workbook.close()

if __name__ == '__main__':
    TanelornParser = ProduktParser(Produktthreads=Produktthreads, Anthologien=Anthologien)
    output = 'xlsx'
    generate_xlsx(TanelornParser.get_all())


4 Port USB Hub

  • Hero Member
  • *****
  • Beiträge: 1.047
  • Jetzt mit USB 3.0 Ports
    • Profil anzeigen
Re: Produktbewertungen: Auswertung und Übersicht
« Antwort #119 am: 26 Feb 2018, 16:33:29 »
hab schon kuerzlich beim refactoring gemerkt wie schlimm ich python finde.  >:(

Ich glaube es kann sinnvoll sein wenn du einfach versuchst das Ganze in google spreadsheets zu bauen und da einfach die ratings per IMPORTHTML() importierst

so z.b.
https://docs.google.com/spreadsheets/d/1nrB35fYctB0_QT9TXjBd9Osk9Fy35_cG6ORIUoGMrxY/edit?usp=sharing
« Letzte Änderung: 26 Feb 2018, 16:56:07 von 4 Port USB Hub »
Für Fetzenstein! Nieder mit Knax!