[Python] Uitvoeren van string

Pagina: 1
Acties:

Vraag


Acties:
  • 0 Henk 'm!

  • mickjuh
  • Registratie: Mei 2004
  • Laatst online: 03-10 13:39

mickjuh

Good news everyone!

Topicstarter
Tweakers,

Ik weet niet of het mogelijk is of ik kan het misschien beter op een andere manier oplossen maar ik zit met het volgende probleem. Ik gebruik Beautifulsoup voor het scrapen van een website. Dat gaat op zich goed maar loop tegen het volgende aan;

Python:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
soup = BeautifulSoup(html,'lxml')
findall = soup.findAll('div', {'class': 'de-div-class'})

totalcount = len(findall)
count = 0

for item in findall:
    count = count + 1
    homebasis = soup.find('div', {'class': 'hometeam'})
    homenext = '.findNext(\'div\', {\'class\': \'hometeam\'})'

    awaybasis = soup.find('div', {'class': 'awayteam'})
    awaynext = '.findNext(\'div\', {\'class\': \'awayteam\'})'

    if count > 1:
        hometeam = homebasis + (homenext*count)
        hometeam = hometeam.getText()
    else:
        hometeam = homebasis
        hometeam = hometeam.getText()

    print hometeam


Wat ik eigenlijk wil doen is die .findNext achter die soup.find plaatsen in de hoeveelheid van de count.

Bij count 2 zou hij dit moeten uitvoeren:

Python:
1
soup.find('div', {'class': 'hometeam'}).findNext('div', {'class': 'hometeam'})


Bij count 3 dit:

Python:
1
soup.find('div', {'class': 'hometeam'}).findNext('div', {'class': 'hometeam'}).findNext('div', {'class': 'hometeam'})


Echter als ik de code run krijg ik de volgende foutmelding:

Python:
1
TypeError: unsupported operand type(s) for +: 'Tag' and 'str'


Is het mogelijk wat ik wil? Dus de te uit te voeren code aanpassen op basis van de count? :)

Beste antwoord (via mickjuh op 21-07-2018 07:43)


  • DroogKloot
  • Registratie: Februari 2001
  • Niet online

DroogKloot

depenisvanjezus

Python:
1
2
3
4
5
homebasis = "tag = soup.find('div', {'class': 'hometeam'})"
homenext = ".findNext(\'div\', {\'class\': \'hometeam\'})"

exec(homebasis + (homenext*count))
print(tag)

[ Voor 5% gewijzigd door DroogKloot op 20-07-2018 23:19 ]

Alle reacties


Acties:
  • Beste antwoord
  • +1 Henk 'm!

  • DroogKloot
  • Registratie: Februari 2001
  • Niet online

DroogKloot

depenisvanjezus

Python:
1
2
3
4
5
homebasis = "tag = soup.find('div', {'class': 'hometeam'})"
homenext = ".findNext(\'div\', {\'class\': \'hometeam\'})"

exec(homebasis + (homenext*count))
print(tag)

[ Voor 5% gewijzigd door DroogKloot op 20-07-2018 23:19 ]


Acties:
  • 0 Henk 'm!

  • mickjuh
  • Registratie: Mei 2004
  • Laatst online: 03-10 13:39

mickjuh

Good news everyone!

Topicstarter
Dank je wel. Dat is precies wat ik zocht. Heb het nog wel iets moeten aanpassen maar het werkt nu :D

Python:
1
2
3
4
5
6
7
homebasis = "hometeam = soup.find('div', {'class': 'hometeam'})"
homenext = ".findNext(\'div\', {\'class\': \'hometeam\'})"

exec (homebasis)
hometeam = hometeam.getText()

print hometeam

Acties:
  • +1 Henk 'm!

  • ValHallASW
  • Registratie: Februari 2003
  • Niet online
Geen exec() voor nodig:

Python:
1
2
3
4
5
6
7
8
9
10
for item in findall:
    count = count + 1

    hometeam = soup.find('div', {'class': 'hometeam'})
    
    if count > 1:
        for _ in range(count):
            hometeam = hometeam.findNext('div', {'class': 'hometeam'})
    
    print hometeam


Vermoedelijk is dit met een andere manier van BS aanroepen nog wat netter op te lossen, maar dat is zonder de oorspronkelijke HTML lastig te bepalen.

Acties:
  • +1 Henk 'm!

  • Raynman
  • Registratie: Augustus 2004
  • Laatst online: 13:23
Ter illustratie: met een beetje functioneel programmeren kun je de structuur van de stringmanipulatiecode ook zonder exec behouden.
Python:
1
2
3
4
5
6
from functools import reduce
from operator import methodcaller

homebasis = soup.find('div', {'class': 'hometeam'})
homenext = methodcaller('findNext', 'div', {'class': 'hometeam'})
hometeam = reduce(lambda x, f: f(x), [homenext] * count, homebasis)


Maar inderdaad: gewoon een loopje gebruiken. Trouwens, als dit klopt:
mickjuh schreef op vrijdag 20 juli 2018 @ 21:38:
Bij count 2 zou hij dit moeten uitvoeren:

[code=python]
Python:
1
soup.find('div', {'class': 'hometeam'}).findNext('div', {'class': 'hometeam'})


Bij count 3 dit:

Python:
1
soup.find('div', {'class': 'hometeam'}).findNext('div', {'class': 'hometeam'}).findNext('div', {'class': 'hometeam'})
Dan zit je nog met een off-by-one error en moet je gewoon zonder if kunnen:
Python:
1
2
3
4
5
6
7
8
for item in findall:
    hometeam = soup.find('div', {'class': 'hometeam'})
    
    for _ in range(count):
        hometeam = hometeam.findNext('div', {'class': 'hometeam'})
    
    print hometeam
    count += 1

Acties:
  • 0 Henk 'm!

  • mickjuh
  • Registratie: Mei 2004
  • Laatst online: 03-10 13:39

mickjuh

Good news everyone!

Topicstarter
Raynman schreef op zaterdag 21 juli 2018 @ 10:57:
Ter illustratie: met een beetje functioneel programmeren kun je de structuur van de stringmanipulatiecode ook zonder exec behouden.
Python:
1
2
3
4
5
6
from functools import reduce
from operator import methodcaller

homebasis = soup.find('div', {'class': 'hometeam'})
homenext = methodcaller('findNext', 'div', {'class': 'hometeam'})
hometeam = reduce(lambda x, f: f(x), [homenext] * count, homebasis)


Maar inderdaad: gewoon een loopje gebruiken. Trouwens, als dit klopt:
Bedankt voor het meedenken! De exec methode zoals hierboven werkt niet in Python 3.7, werkte wel in 2.7 dus ik heb jouw methode ook geprobeerd. Hij voert de eerste find uit maar daarna niet meer.

Wil dezelfde stringmanipulatie ook met een makkelijker voorbeeld gebruiken;

HTML:
1
2
3
4
5
6
7
8
<html>
<head></head>
<body>
    <p>Lorum</p>
    <p>Ipsum</p>
    <p>Einde</p>
</body>
</html>


Python:
1
2
3
4
5
6
7
8
9
10
11
12
13
from functools import reduce
from operator import methodcaller

soup = BeautifulSoup(response.data, 'lxml')
count = 0

while count <= totaalp:
    firstp = soup.find("p")
    nextp = methodcaller('.findNext("p")')
    p = reduce(lambda x, f: f(x), [nextp] * count, firstp)
    count += 1

    print(p)


Die totaalp reken ik ervoor al uit. Als ik bovenstaande code uitvoer krijg ik het volgende:

Python:
1
2
3
4
5
6
7
8
9
<p>Lorum</p>
Traceback (most recent call last):
  File "test.py", line 63, in get_p
    p = reduce(lambda x, f: f(x), [nextp] * count, firstp)
  File "test.py", line 63, in <lambda>
    p = reduce(lambda x, f: f(x), [nextp] * count, firstp)
TypeError: 'NoneType' object is not callable

Process finished with exit code 1


Zoals je ziet voert hij de eerste find uit. Als de count 1 is zou hij het volgende moeten uitvoeren;

Python:
1
2
3
4
articlesoup.find("p").findNext("p")

# bij count = 2 wordt het dan;
articlesoup.find("p").findNext("p").findNext("p")
ValHallASW schreef op zaterdag 21 juli 2018 @ 10:31:
Python:
1
2
3
4
5
6
7
8
for item in findall:
    count = count + 1

    hometeam = soup.find('div', {'class': 'hometeam'})
    
    if count > 1:
        for _ in range(count):
            hometeam = hometeam.findNext('div', {'class': 'hometeam'})
Heb ik ook geprobeerd maar hij moet de "find" eenmalig vooraan uitvoeren en de ".findNext" in een loop meenemen en vermenigvuldigen met de count.

Denk dat ik er met jullie hulp heel dicht bij zit maar krijg het helaas nog niet voor elkaar :)

Acties:
  • +1 Henk 'm!

  • ValHallASW
  • Registratie: Februari 2003
  • Niet online
Gegeven je voorbeeld
HTML:
1
2
3
4
5
6
7
8
<html>
<head></head>
<body>
    <p>Lorum</p>
    <p>Ipsum</p>
    <p>Einde</p>
</body>
</html>


is het waarschijnlijk handiger om findAll te gebruiken:

code:
1
2
3
4
5
item = soup.find('body')
hometeam_divs = item.findAll('p')

for hometeam_div in hometeam_divs:
    print(hometeam_div.getText())


wat resulteert in
Lorum
Ipsum
Einde

Acties:
  • 0 Henk 'm!

  • mickjuh
  • Registratie: Mei 2004
  • Laatst online: 03-10 13:39

mickjuh

Good news everyone!

Topicstarter
ValHallASW schreef op donderdag 2 augustus 2018 @ 09:00:
Gegeven je voorbeeld
is het waarschijnlijk handiger om findAll te gebruiken:
Dank je! Ik gebruikte de findAll voornamelijk voor het tellen van het aantal elementen. Echter kon ik deze ook gebruiken op de manier die jij aangaf. |:(

Thanks! :-)

Acties:
  • 0 Henk 'm!

Verwijderd

hier geraak ik niet uit, kan er mij iemand helpen met wat info/toelichting? Ik weet dat ik ergens function call bin moet implementeren in die code maar weet nie hoe en waar.
Daarbij is er ook niet uitgelegd geweest hoe die code juist geschreven moet worden enz. Volgorde is belangrijk. Het is python op coursera. Ik zit nu in mijn derde week, het ging goed maar nu opeens krijg ik chinees voorgeschoteld. Kan er mij iemand anders vertellen waar ik het best met die vraag/topic naar toe kan?

Write a program that prompts the user to enter an integer and displays that integer. The program should then prompt the user to enter the integer again and display its binary representation.

For example, here are some sample program runs:

Enter an integer >45
45
Enter it again >45
0b101101

You can use the built-in functions named: input, int, bin and print to help you solve this problem. Look at the documentation for the builtin-in functions at python.org.

tip:

Recall that you can apply a function to the result of a function as many times as you like, for example, to print the rounded value of a floating point number that is input as a string, you can use this expression:

print(round(float(input('Enter a decimal number >'))))
input returns a string

float returns a floating point number for the string

round returns the integer obtained by rounding the floating point number

print displays the integer

You should enter a program that contains this one example line and experiment with it before you write the program for this quiz. Experiment by removing one or more of the function calls to see how these functions work (or generate semantic errors), depending on the types of their argument objects.

When you enter your program and run it, the input for one test case will be entered automatically.

When your program is tested, we will always enter valid integers.

Acties:
  • 0 Henk 'm!

  • Barreljan
  • Registratie: December 2001
  • Laatst online: 30-09 13:10

Barreljan

...Zoom-Zoom...

Ehhh... misschien moet je even een eigen topic starten in plaats van een bestaande 'te kapen' ?

Kleine hulp in de richting. Start de python shell even op:

>>> bla = input("enter some: ")
enter some: 45
>>> print int(bla)
45
>>> bla2 = input("enter again: ")
enter again: 45
>>> print bin(int(bla2))
0b101101

en dit is altijd handig:
>>> help(input)
of
>>> help(bin)

of gewoon google.... ;)

Time Attacker met de Mazda 323F 2.5 V6 J-spec | PV output

Pagina: 1