Python beginners vraag!

Pagina: 1
Acties:

Vraag


Acties:
  • 0 Henk 'm!

  • Aviv1
  • Registratie: Januari 2018
  • Laatst online: 04-02 22:08
Hallo,

Ik ben sinds gisteren voor het eerst begonnen met Python omdat ik een real-life case heb en daarvoor een script heb getikt. Het doel is al bereikt maar nu wil ik het script verbeteren. Dit is de eerste keer dat ik aan het 'programmeren' ben dus sorry als ik een domme vraag stel.

Wat is de bedoeling? Ik wil een HTML bestand crawlen en daar 3 dingen uit halen:
1. Woord in het Hebreeuws
2. Engelse vertaling
3. Hebreeuwse uitspraak .mp3

Vervolgens zet ik dit in een flash-card app d.m.v. CSV uplpad (en mp3 handmatig uploaden) om de woorden te oefenen.

Hoe zit dat script er tot nu toe uit??

Python:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
from urllib.request import urlopen, urlretrieve
import bs4

url = "https:/link_naar_HTML_bestand"

html_file = urlopen(url).read()

html_parse = bs4.BeautifulSoup(html_file, 'html.parser')

all_container = html_parse('div', 'wlv-item__word-box') ##Deze container bevat hebr+engl+mp3
title = html_parse.find('title').contents[0]
title = (title.replace('ongewenste string tekst',""))
print(title)

for every_container in all_container:
    hebr = every_container('span', "wlv-item__word js-wlv-word") ##Hier staat het Hebr woord in de paragraph
    engl = every_container('span', 'wlv-item__english js-wlv-english') ## En hier de Engl
    hebr = (hebr[0].contents[0]).replace('.','') ##eventuele ongewenste . wordt hier verwijderd
    engl = (engl[0].contents[0]).replace('.','') ##net als hier
    engl_hebr = engl+","+hebr ##ik raap beide bij elkaar, gooi er een , tussen voor CSV en sla dat op in engl_hebr
    print(engl_hebr) ## dat print ik dan in de IDE
    
    ## NU Nog de MP3 wegschrijven en klaar.
    mp3 = every_container('audio')[0]
    mp3_src = mp3.get('src ')  # , None)
    urlretrieve(mp3_src, 'mp3/'+engl_hebr+".mp3") ##file name 


En de output ziet er dan zo uit. Dit copy/paste ik dan uit de IDE console

code:
1
2
3
4
5
6
50 Most Commonly Used Verbs 
go,ללכת
eat,לאכול
drink,לשתות
come,לבוא
[...]


Nu het probleem. Hoe moeilijk kan het dan zijn om ditzelfde vervolgens ook weg te schrijven naar een .txt? Handig als backup. Het meest simpele lukt niet. Ik heb het volgende stukje code:

Python:
1
2
3
4
path = 'C:/hebrew_txt/output.txt' ## moet eigenlijk variable title.txt worden
f = open(path,'w')
f.write(engl_hebr)
f.close()


Iemand een idee waarom het niet werkt?

Groet!

// edit: had dus te maken met het het feit dat Hebreeuwse tekens niet zomaar konden worden weggeschreven.

props to @gertvdijk

[ Voor 4% gewijzigd door Aviv1 op 07-03-2019 00:26 ]

Let me share my screen...

Beste antwoord (via Aviv1 op 06-03-2019 23:24)


  • gertvdijk
  • Registratie: November 2003
  • Laatst online: 03-10 12:27
Probeer eens het schrijven op onderstaande manier te doen, met een encoding argument bij het openen van de file handle:

Python:
1
2
3
path = 'C:/hebrew_txt/output.txt' ## moet eigenlijk variable title.txt worden
with open(path, mode='w', encoding='utf-8') as f:
    f.write(engl_hebr)


Achtergrond: op Windows is de default file output text encoding cp-1252 (bah!), Mac/Linux gebruikers hebben daar geen last van. In CP-1252 passen je Hebreeuwse karakters helemaal niet die hij in UTF-8 in die variabelen heeft staan. Je moet daarom bij het uitvoeren nog even vertellen hoe Python die strings moet encoden (of eigenlijk onveranderd uitsturen nu, want ze zijn al UTF-8 gok ik).

Zelf meer testen:

Python:
1
2
3
4
5
6
7
8
9
10
11
12
import locale

# Will print UTF-8 on most OSs, but cp1252 on Windows.
print("Platform default encoding: ", locale.getpreferredencoding(False))

# example string with unicode
s = "זו שפה יפה!"

# Print (as binary, mostly hex encoded) how it should be written to disk when encoded with UTF-8.
print(s.encode('utf-8'))
# But as cp-1252, this can't be encoded and it will explode.
print(s.encode('cp1252'))

UnicodeEncodeError                        Traceback (most recent call last)
<ipython-input-11-adf442fb0850> in <module>()
----> 1 s.encode('cp1252')

/usr/lib/python3.6/encodings/cp1252.py in encode(self, input, errors)
     10 
     11     def encode(self,input,errors='strict'):
---> 12         return codecs.charmap_encode(input,errors,encoding_table)
     13 
     14     def decode(self,input,errors='strict'):

UnicodeEncodeError: 'charmap' codec can't encode characters in position 0-1: character maps to <undefined>


Meer info/referenties:

[ Voor 66% gewijzigd door gertvdijk op 06-03-2019 23:42 ]

Kia e-Niro 2021 64 kWh DynamicPlusLine. See my GitHub and my blog for articles on security and other stuff.

Alle reacties


Acties:
  • 0 Henk 'm!

  • Matis
  • Registratie: Januari 2007
  • Laatst online: 06-10 17:29

Matis

Rubber Rocket

Je kunt simpelweg twee dingen doen. In de loop telkens een regel wegschrijven in de file, of je slaat iedere engl_hebr op in een List en schrijft die uiteindelijk weg in een file.

Waarschijnlijk schrijf je nu alleen de laatste regel in de file weg, omdat die als laatste in de eerdergenoemde variabele worst opgeslagen/overschreven.

If money talks then I'm a mime
If time is money then I'm out of time


Acties:
  • 0 Henk 'm!

  • Aviv1
  • Registratie: Januari 2018
  • Laatst online: 04-02 22:08
Matis schreef op woensdag 6 maart 2019 @ 21:14:
Je kunt simpelweg twee dingen doen. In de loop telkens een regel wegschrijven in de file, of je slaat iedere engl_hebr op in een List en schrijft die uiteindelijk weg in een file.

Waarschijnlijk schrijf je nu alleen de laatste regel in de file weg, omdat die als laatste in de eerdergenoemde variabele worst opgeslagen/overschreven.
Het verwarrende is dat hij helemaal niets wegschrijft. Het textbestand blijft leeg en hij gooit een error waar ik niet veel van snap. Wel print hij de eerste hebr_eng variabele, maar dan stopt hij.

Python:
1
2
3
4
5
6
Traceback (most recent call last):
  File "C:/Users/xxx/PycharmProjects/hebrcrawler/text.py", line 25, in <module>
    f.write(hebr_engl)
  File "C:\Users\xxx\AppData\Local\Programs\Python\Python37-32\lib\encodings\cp1252.py", line 19, in encode
    return codecs.charmap_encode(input,self.errors,encoding_table)[0]
UnicodeEncodeError: 'charmap' codec can't encode characters in position 0-2: character maps to <undefined>


Echter... als ik f.write(title) doe, write hij netjes de titel van het HTML bestand in de .txt

Dus: waarom kan ik de ene variabele niet opslaan, en de andere wel?

Let me share my screen...


Acties:
  • +1 Henk 'm!

  • gertvdijk
  • Registratie: November 2003
  • Laatst online: 03-10 12:27
Kan je misschien even vermelden welke Python versie je gebruikt? Plus, de website die je probeert te crawlen is misschien ook wel handig om een exact goed antwoord te kunnen geven.

Het lijkt erop dat je encoding issues hebt. Je (unicode) variabele bevat een karakter (code point) die niet beschikbaar is in de standaard Windows CP-1252 encoding. Mijn gok is dat urllib de encoding van de site goed snapt, maar je output encoding zonder op te geven een default is die niet alle mogeljikheden van UTF-8 toestaat. Als je zelf UTF-8 voor de uitvoer opgeeft zal het dan wel lukken misschien. Als de ene variabele wel werkt en de andere niet, komt dat doordat de ene net die karakters niet heeft en de andere wel.

[ Voor 14% gewijzigd door gertvdijk op 06-03-2019 22:55 ]

Kia e-Niro 2021 64 kWh DynamicPlusLine. See my GitHub and my blog for articles on security and other stuff.


Acties:
  • 0 Henk 'm!

  • Aviv1
  • Registratie: Januari 2018
  • Laatst online: 04-02 22:08
gertvdijk schreef op woensdag 6 maart 2019 @ 22:53:
Kan je misschien even vermelden welke Python versie je gebruikt? Plus, de website die je probeert te crawlen is misschien ook wel handig om een exact goed antwoord te kunnen geven.

Het lijkt erop dat je encoding issues hebt. Je (unicode) variabele bevat een karakter (code point) die niet beschikbaar is in de standaard Windows CP-1252 encoding. Mijn gok is dat urllib de encoding van de site goed snapt, maar je output encoding zonder op te geven een default is die niet alle mogeljikheden van UTF-8 toestaat. Als je zelf UTF-8 voor de uitvoer opgeeft zal het dan wel lukken misschien. Als de ene variabele wel werkt en de andere niet, komt dat doordat de ene net die karakters niet heeft en de andere wel.
PM.

Ik gebruik Python 3.7 icm Pycharm

Dan komt dat misschien omdat het Hebreeuws is (rechts naar links)? De titel van het HTML bestand is namelijk Engels en die write hij wel naar het .txt bestand.

print(hebr_engl) ziet er dus zo uit:

code:
1
אתה יכול לעשות זאת! , You can do it! , ata yachol la'asot zot!


hebreeuws, engels, romanization

Echter kan ik dit gewoon handmatig in Notepad plakken en probleemloos opslaan.

/edit: ook onderstaand werkt niet.

Python:
1
2
 with open('out.txt','w') as f:
        print(hebr_engl, file=f)


Maar dit wel:


Python:
1
2
 with open('out.txt','w') as f:
        print(title, file=f)

[ Voor 11% gewijzigd door Aviv1 op 06-03-2019 23:18 ]

Let me share my screen...


Acties:
  • Beste antwoord
  • 0 Henk 'm!

  • gertvdijk
  • Registratie: November 2003
  • Laatst online: 03-10 12:27
Probeer eens het schrijven op onderstaande manier te doen, met een encoding argument bij het openen van de file handle:

Python:
1
2
3
path = 'C:/hebrew_txt/output.txt' ## moet eigenlijk variable title.txt worden
with open(path, mode='w', encoding='utf-8') as f:
    f.write(engl_hebr)


Achtergrond: op Windows is de default file output text encoding cp-1252 (bah!), Mac/Linux gebruikers hebben daar geen last van. In CP-1252 passen je Hebreeuwse karakters helemaal niet die hij in UTF-8 in die variabelen heeft staan. Je moet daarom bij het uitvoeren nog even vertellen hoe Python die strings moet encoden (of eigenlijk onveranderd uitsturen nu, want ze zijn al UTF-8 gok ik).

Zelf meer testen:

Python:
1
2
3
4
5
6
7
8
9
10
11
12
import locale

# Will print UTF-8 on most OSs, but cp1252 on Windows.
print("Platform default encoding: ", locale.getpreferredencoding(False))

# example string with unicode
s = "זו שפה יפה!"

# Print (as binary, mostly hex encoded) how it should be written to disk when encoded with UTF-8.
print(s.encode('utf-8'))
# But as cp-1252, this can't be encoded and it will explode.
print(s.encode('cp1252'))

UnicodeEncodeError                        Traceback (most recent call last)
<ipython-input-11-adf442fb0850> in <module>()
----> 1 s.encode('cp1252')

/usr/lib/python3.6/encodings/cp1252.py in encode(self, input, errors)
     10 
     11     def encode(self,input,errors='strict'):
---> 12         return codecs.charmap_encode(input,errors,encoding_table)
     13 
     14     def decode(self,input,errors='strict'):

UnicodeEncodeError: 'charmap' codec can't encode characters in position 0-1: character maps to <undefined>


Meer info/referenties:

[ Voor 66% gewijzigd door gertvdijk op 06-03-2019 23:42 ]

Kia e-Niro 2021 64 kWh DynamicPlusLine. See my GitHub and my blog for articles on security and other stuff.


Acties:
  • 0 Henk 'm!

  • Aviv1
  • Registratie: Januari 2018
  • Laatst online: 04-02 22:08
gertvdijk schreef op woensdag 6 maart 2019 @ 23:19:
Probeer eens het schrijven op onderstaande manier te doen, met een encoding argument bij het openen van de file handle:

Python:
1
2
3
path = 'C:/hebrew_txt/output.txt' ## moet eigenlijk variable title.txt worden
with open(path, mode='w+', encoding='utf-8') as f:
    f.write(engl_hebr)


Meer info: https://docs.python.org/3...-and-writing-unicode-data
Het werkt! Dank. _/-\o_

Het enige is dat hij nu inderdaad alleen het laatste resultaat wegschrijft terwijl de print() wel alles uitspuugt.

Maar daar kom ik denk wel uit (of moet ik echt een List maken?)

Let me share my screen...


Acties:
  • +1 Henk 'm!

  • gertvdijk
  • Registratie: November 2003
  • Laatst online: 03-10 12:27
Het enige is dat hij nu inderdaad alleen het laatste resultaat wegschrijft terwijl de print() wel alles uitspuugt.
Als ik het goed begrijp doe je nu binnen je for-loop een assignment van die engl_hebr variabele. Dus bij elke iteratie wordt die oude waarde weer weggegooid. Als je dan na het doorlopen van die loop pas schrijft, schrijf je alleen de waarde tijdens de laatste iteratie weg.

Als je alles wilt wegschrijven kan je kiezen:
  • Open de file handle buiten de scope van de for-loop (ervoor) en doe in de loop f.write(engl_hebr).
  • Declareer de string buiten/voor de for-loop en append ernaar. dus ervoor: engl_hebr_all = "" en erbinnen: engl_hebr_all += engl_hebr
Uitwerking eerste optie:

Python:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# ... snip, zelfde ...
print(title)

path = 'C:/hebrew_txt/output.txt' ## moet eigenlijk variable title.txt worden
with open(path, mode='w', encoding='utf-8') as f:
    for every_container in all_container:
        # ... snip, zelfde ...
        print(engl_hebr) ## dat print ik dan in de IDE
        f.write(engl_hebr) # dit schrijft (append, niet eroverheen) naar de file.
        
        # ... snip, zelfde ...

# f.close() hoeft niet meer, want je hebt een scoped context gemaakt met 'with', en daarbuiten
# wordt die scope gesloten, dat bij een open() feitelijk een automagische close() doet. Zo kan
# je niet meer vergeten .close() te doen als je eerder uit je loop zou springen bijvoorbeeld.

[ Voor 33% gewijzigd door gertvdijk op 06-03-2019 23:50 ]

Kia e-Niro 2021 64 kWh DynamicPlusLine. See my GitHub and my blog for articles on security and other stuff.


Acties:
  • 0 Henk 'm!

  • Aviv1
  • Registratie: Januari 2018
  • Laatst online: 04-02 22:08
gertvdijk schreef op woensdag 6 maart 2019 @ 23:38:
[...]


Als ik het goed begrijp doe je nu binnen je for-loop een assignment van die engl_hebr variabele. Dus bij elke iteratie wordt die oude waarde weer weggegooid. Als je dan na het doorlopen van die loop pas schrijft, schrijf je alleen de waarde tijdens de laatste iteratie weg.

Als je alles wilt wegschrijven kan je kiezen:
  • Open de file handle buiten de scope van de for-loop (ervoor) en doe in de loop f.write(engl_hebr).
  • Declareer de string buiten/voor de for-loop en append ernaar. dus ervoor: engl_hebr_all = "" en erbinnen: engl_hebr_all += engl_hebr
Uitwerking eerste optie:

Python:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# ... snip, zelfde ...
print(title)

path = 'C:/hebrew_txt/output.txt' ## moet eigenlijk variable title.txt worden
with open(path, mode='w', encoding='utf-8') as f:
    for every_container in all_container:
        # ... snip, zelfde ...
        print(engl_hebr) ## dat print ik dan in de IDE
        f.write(engl_hebr) # dit schrijft (append, niet eroverheen) naar de file.
        
        # ... snip, zelfde ...

# f.close() hoeft niet meer, want je hebt een scoped context gemaakt met 'with', en daarbuiten
# wordt die scope gesloten, dat bij een open() feitelijk een automagische close() doet. Zo kan
# je niet meer vergeten .close() te doen als je eerder uit je loop zou springen bijvoorbeeld.
Yes !! Eerste optie werkt. Ik zat inderdaad even te hannessen met de indents maar het werkt nu. Ik heb hem ook werkend zoner while, zoals ik eerst probeerde (scheelt indent).

Python:
1
2
3
4
path = 'C:/hebrew_txt/' + title + ".txt"
f = open(path, mode='w+', encoding='utf-8')

for every_container in all_container:


Vreemd genoeg moet f.close() in beide gevallen weglaten uit de for, anders krijg ik een I/O error.


Hartelijk dank _/-\o_

[ Voor 5% gewijzigd door Aviv1 op 07-03-2019 00:18 ]

Let me share my screen...


Acties:
  • +1 Henk 'm!

  • Gropah
  • Registratie: December 2007
  • Niet online

Gropah

Admin Softe Goederen

Oompa-Loompa 💩

Aviv1 schreef op donderdag 7 maart 2019 @ 00:05:
[...]


Yes !! Eerste optie werkt. Ik zat inderdaad even te hannessen met de indents maar het werkt nu. Ik heb hem ook werkend zoner while, zoals ik eerst probeerde (scheelt indent).

Python:
1
2
3
4
path = 'C:/hebrew_txt/' + title + ".txt"
f = open(path, mode='w+', encoding='utf-8')

for every_container in all_container:


Vreemd genoeg moet f.close() in beide gevallen weglaten uit de for, anders krijg ik een I/O error.

Nu alleen even uitzoeken waarom ik in de print() alles netjes onder elkaar krijg, en in de f.write alles op 1 regel.

Hartelijk dank _/-\o_
print gooit standaard een newline achter de ingevoerde string aan en file.write niet. Gewoon even + '\n' bij de output proppen zou voldoende moeten zijn

Acties:
  • +1 Henk 'm!

  • Aviv1
  • Registratie: Januari 2018
  • Laatst online: 04-02 22:08
Gropah schreef op donderdag 7 maart 2019 @ 00:18:
[...]


print gooit standaard een newline achter de ingevoerde string aan en file.write niet. Gewoon even + '\n' bij de output proppen zou voldoende moeten zijn
Ik kwam er net achter :D

Python:
1
2
f.write(hebr_engl)
f.write('\n')


**probeert het werkend te krijgen op 1 regel**

Python:
1
f.write(hebr_engl+'\n')

[ Voor 12% gewijzigd door Aviv1 op 07-03-2019 00:29 ]

Let me share my screen...


Acties:
  • 0 Henk 'm!

  • gertvdijk
  • Registratie: November 2003
  • Laatst online: 03-10 12:27
**probeert het werkend te krijgen op 1 regel**
Python:
1
2
import os
f.write(hebr_engl + os.linesep)


os.linesep is platform-afhankelijk de "juiste" newline. Ook weer Windows die liever \r\n or \n\r heeft, kan het nooit onthouden, dit wel.

Kia e-Niro 2021 64 kWh DynamicPlusLine. See my GitHub and my blog for articles on security and other stuff.


Acties:
  • 0 Henk 'm!

  • Aviv1
  • Registratie: Januari 2018
  • Laatst online: 04-02 22:08
gertvdijk schreef op donderdag 7 maart 2019 @ 00:29:
[...]

Python:
1
2
import os
f.write(hebr_engl + os.linesep)


os.linesep is platform-afhankelijk de "juiste" newline. Ook weer Windows die liever \r\n or \n\r heeft, kan het nooit onthouden, dit wel.
Dus dit is beter dan
Python:
1
f.write(hebr_engl+'\n')
?

Let me share my screen...

Pagina: 1