Skip to content

Commit

Permalink
Rectifie bug TP webscraping (#281)
Browse files Browse the repository at this point in the history
* affiche image

* Automated changes

* Automated changes

* dcompose

* Update find_element functions (#267)

Update find_elements as the function changed with a recent Selenium update

* reformat

* eval false

* eval false

* Automated changes

* Automated changes

Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
Co-authored-by: Antoine Palazzolo <97433407+antoine-palazz@users.noreply.github.com>
  • Loading branch information
3 people committed Sep 26, 2022
1 parent d068cb6 commit 25046de
Showing 1 changed file with 110 additions and 49 deletions.
159 changes: 110 additions & 49 deletions content/course/manipulation/04a_webscraping_TP/index.qmd
Expand Up @@ -766,11 +766,17 @@ celui qui suit

{{% box status="exercise" title="Exercice" icon="fas fa-pencil-alt" %}}

Pour cet exercice, nous vous demandons d'obtenir différentes informations sur les pokémons à partir du site internet [pokemondb.net](http://pokemondb.net/pokedex/national).
Pour cet exercice,
nous vous demandons d'obtenir différentes informations sur les pokémons
à partir du site internet [pokemondb.net](http://pokemondb.net/pokedex/national).

## Etape 1

Nous souhaitons tout d'abord obtenir les informations personnelles des ``893`` pokemons sur [pokemondb.net](http://pokemondb.net/pokedex/national). Les informations que nous aimerions obtenir au final pour les pokemons sont celles contenues dans 4 tableaux :
Nous souhaitons tout d'abord obtenir les
informations personnelles de tous
les pokemons sur [pokemondb.net](http://pokemondb.net/pokedex/national).

Les informations que nous aimerions obtenir au final pour les pokemons sont celles contenues dans 4 tableaux :

- Pokédex data
- Training
Expand Down Expand Up @@ -919,7 +925,7 @@ Nous aimerions que vous récupériez également les images des 5 premiers pokém

Idée : Utilisez les modules `request` et [`shutil`](https://docs.python.org/3/library/shutil.html)

_pour cette question, il faut que vous cherchiez de vous même certains éléments, tout n'est pas présent dans le TD_.
:warning: _Pour cette question, il faut que vous cherchiez de vous même certains éléments, tout n'est pas présent dans le TD_.

```{python}
#| include: false
Expand Down Expand Up @@ -950,7 +956,12 @@ for indice_pokemon in range(0,nb_pokemons) :
```{python}
#| echo: false
#plt.savefig('pokemon.png', bbox_inches='tight')
plt.show()
ax[0].get_figure()
```

```{python}
#| include: false
shutil.copyfile("bulbasaur.jpg", "featured.jpg")
```

{{% /box %}}
Expand All @@ -972,43 +983,80 @@ sur <a href="https://github.com/linogaliana/python-datascientist" class="github"
# `Selenium` : mimer le comportement d'un utilisateur internet


Jusqu'à présent, nous avons raisonné comme si nous connaissions toujours l'url qui nous intéresse. De plus, les pages que nous visitons sont "statiques", elles ne dépendent pas d'une action ou d'une recherche de l'internaute.
Jusqu'à présent,
nous avons raisonné comme si nous connaissions toujours l'url qui nous intéresse.
De plus, les pages que nous visitons sont "statiques",
elles ne dépendent pas d'une action ou d'une recherche de l'internaute.

Nous allons voir à présent comment nous en sortir pour remplir
des champs sur un site web et récupérer ce qui nous intéresse.
La réaction d'un site _web_ à l'action d'un utilisateur passe régulièrement par
l'usage de `JavaScript` dans le monde du développement _web_.
Le package [Selenium](https://pypi.python.org/pypi/selenium) permet
de reproduire, depuis un code automatisé, le comportement
manuel d'un utilisateur. Il permet ainsi
d'obtenir des informations du site qui ne sont pas dans le
code `HTML` mais qui apparaissent uniquement à la suite de
l'exécution de script `JavaScript` en arrière plan.

Nous allons voir à présent comment nous en sortir pour remplir des champs sur un site web et récupérer ce qui nous intéresse.
`Selenium` se comporte comme un utilisateur lambda sur internet :
il clique sur des liens, il remplit des formulaires, etc.

L'avantage du package [Selenium](https://pypi.python.org/pypi/selenium) est d'obtenir des informations du site qui ne sont pas dans le code html mais qui apparaissent uniquement à la suite de l'exécution de script javascript en arrière plan.
## Premier exemple en scrapant un moteur de recherche

Selenium se comporte comme un utilisateur lambda sur internet : il clique sur des liens, il remplit des formulaires etc. Dans cet exemple, nous allons essayer de aller sur le site de [Bing Actualités](https://www.bing.com/news) et entrer dans la barre de recherche un sujet donné (Trump).
Dans cet exemple, nous allons essayer de aller sur le
site de [Bing Actualités](https://www.bing.com/news) et entrer dans la barre de recherche un sujet donné (__"Trump"__).

L'installation de `selenium` nécessite d'avoir chromium qui est un
L'installation de `Selenium` nécessite d'avoir `Chromium` qui est un
navigateur Google Chrome minimaliste.
La version de [chromedriver](https://sites.google.com/a/chromium.org/chromedriver/) doit être ``>= 2.36`` et dépend de la version de Chrome que vous avez sur votre poste.
La version de [chromedriver](https://sites.google.com/a/chromium.org/chromedriver/)
doit être `>= 2.36` et dépend de la version de `Chrome` que vous avez sur votre environnement
de travail. Pour installer cette version minimaliste de `Chrome` sur un environnement
`Linux`, vous pouvez
vous référer à l'encadré dédié

~~~python
!pip install selenium
{{% box status="note" title="Note" icon="fa fa-comment" %}}

# Sur votre poste
# télécharger le chrome driver https://chromedriver.storage.googleapis.com/index.html?path=85.0.4183.83/
L'installation nécessite de passer par le terminal.
D'abord, il convient d'installer les dépendances.
Sur `Colab`, vous pouvez utiliser les commandes suivantes:

# Sur google colab
# https://stackoverflow.com/questions/51046454/how-can-we-use-selenium-webdriver-in-colab-research-google-com
!apt-get update # to update ubuntu to correctly run apt install
!apt install chromium-chromedriver
```{python}
#| eval: false
!sudo apt get update
!sudo apt install -y unzip xvfb libxi6 libgconf-2-4 -y
!sudo apt install chromium-chromedriver -y
!cp /usr/lib/chromium-browser/chromedriver /usr/bin
```

Si vous êtes dans un `Jupyter Notebook`, vous pouvez
exécuter les commandes ci-dessous en les faisant
précéder de `!`

Vous pouvez ensuite installer `Selenium`. Par
exemple, depuis une
cellule de `Notebook`:

```{python}
#| eval: false
!pip install selenium
```
{{% /box %}}

```{python}
#| eval: false
import sys
sys.path.insert(0,'/usr/lib/chromium-browser/chromedriver')
~~~

~~~python
import selenium
path_to_web_driver = "chromedriver"
~~~

On va sur le site de Bing Actualités, et on lui indique le mot clé que nous souhaitons chercher.
```

Dans cet exemple, on va voir que l'ordinateur va ouvrir une nouvelle fenêtre.
En premier lieu, il convient d'initialiser le comportement
de Selenium en répliquant les paramètres
du navigateur:

~~~python
```{python}
#| eval: false
import time
from selenium import webdriver
Expand All @@ -1022,45 +1070,53 @@ chrome_options.add_argument('--no-sandbox')
browser = webdriver.Chrome(executable_path=path_to_web_driver,
options=chrome_options)
```

On va sur le site de `Bing Actualités`, et on lui indique le mot clé que nous souhaitons chercher.

```{python}
#| eval: false
browser.get('https://www.bing.com/news')
# on cherche l'endroit où on peut remplir un formulaire
# en utilisant les outils du navigateur > inspecter les éléments de la page
# on voit que la barre de recherche est un élement du code appelé 'q' comme query
# on lui demande de chercher cet élément
search = browser.find_element_by_name('q')
search = browser.find_element("name", "q")
print(search)
print([search.text, search.tag_name, search.id])
# on envoie à cet endroit le mot qu'on aurait tapé dans la barre de recherche
search.send_keys("Trump")
search_button = browser.find_element_by_xpath("//input[@id='sb_form_go']")
search_button = browser.find_element("xpath", "//input[@id='sb_form_go']")
#search_button = browser.find_element_by_id('search_button_homepage')
#search_button = browser.find_element("id", 'search_button_homepage')
search_button.click()
# on appuie sur le bouton "Entrée" Return en anglais
#search.send_keys(Keys.RETURN)
~~~
```

~~~python
```{python}
#| eval: false
png = browser.get_screenshot_as_png()
~~~
```

~~~python
```{python}
#| eval: false
from IPython.display import Image
Image(png, width='500')
~~~
```

On extrait les résultats.

~~~python
```{python}
#| eval: false
from selenium.common.exceptions import StaleElementReferenceException
links = browser.find_elements_by_xpath("//div/a[@class='title'][@href]")
links = browser.find_elements("xpath", "//div/a[@class='title'][@href]")
results = []
for link in links:
Expand All @@ -1072,25 +1128,30 @@ for link in links:
results.append(url)
len(results)
~~~
```

~~~python
```{python}
#| eval: false
# on a une pause de 10 secondes pour aller voir ce qui se passe sur la page internet
# on demande de quitter le navigateur quand tout est fini
browser.quit()
~~~
```

~~~python
```{python}
#| eval: false
print(results)
~~~
```

## Utiliser selenium pour jouer à 2048

Dans cet exemple, on utilise le module pour que python appuie lui même sur les touches du clavier afin de jouer à 2048.
Dans cet exemple, on utilise le module pour que `Python`
appuie lui même sur les touches du clavier afin de jouer à 2048.

Note : ce bout de code ne donne pas une solution à 2048, il permet juste de voir ce qu'on peut faire avec selenium
Note : ce bout de code ne donne pas une solution à 2048,
il permet juste de voir ce qu'on peut faire avec `Selenium`

~~~python
```{python}
#| eval: false
from selenium import webdriver
from selenium.webdriver.common.keys import Keys
Expand All @@ -1103,17 +1164,17 @@ browser.get('https://play2048.co//')
# Ce qu'on va faire : une boucle qui répète inlassablement la même chose : haut / droite / bas / gauche
# on commence par cliquer sur la page pour que les touches sachent
browser.find_element_by_class_name('grid-container').click()
grid = browser.find_element_by_tag_name('body')
browser.find_element("class name", 'grid-container').click()
grid = browser.find_element("tag name", 'body')
# pour savoir quels coups faire à quel moment, on crée un dictionnaire
direction = {0: Keys.UP, 1: Keys.RIGHT, 2: Keys.DOWN, 3: Keys.LEFT}
count = 0
while True:
try: # on vérifie que le bouton "Try again" n'est pas là - sinon ça veut dire que le jeu est fini
retryButton = browser.find_element_by_link_text('Try again')
scoreElem = browser.find_element_by_class_name('score-container')
retryButton = browser.find_element("link text",'Try again')
scoreElem = browser.find_element("class name", 'score-container')
break
except:
#Do nothing. Game is not over yet
Expand All @@ -1125,4 +1186,4 @@ while True:
print('Score final : {} en {} coups'.format(scoreElem.text, count))
browser.quit()
~~~
```

0 comments on commit 25046de

Please sign in to comment.