J'essaie de gratter le répertoire des juges de première instance de l'État de New York. Le site vérifie si javascript est activé et affiche la page avec un bref avertissement sur la nécessité de python. J'ai donc essayé Selenium.

Cependant, lorsque j'exécute la ligne suivante ligne par ligne en ipython ou python, il est capable d'accéder à la page correctement. Ensuite, si je l'exécute à partir de la ligne de commande (python scraper.py), le site s'affiche avec l'avertissement javascript - mais uniquement la première fois que j'accède au site. Ça arrive:

  • quel que soit le navigateur que j'utilise,
  • que je l'exécute comme un navigateur sans tête ou non,
  • quels que soient les cookies que j'essaie de définir

Mon code:

import string
import csv
from selenium import webdriver

# Start the browser
browser = webdriver.Firefox()
browser.get(
    "https://iapps.courts.state.ny.us/judicialdirectory/JudicialDirectory")
print(browser.title)

# You can run the above 4 lines directly in ipython,
# but if running from the command line, the previous try will not work
browser.get(
    "https://iapps.courts.state.ny.us/judicialdirectory/JudicialDirectory")
print(browser.title)

Dans le cas où c'est important: je l'exécute sur Windows 10.

Quelqu'un at-il des suggestions sur la façon de déboguer cela?

2
RCA 13 avril 2018 à 21:55

3 réponses

Meilleure réponse

La différence ici est que, lorsqu'il est exécuté en tant que script, browser.title est accessible avant que le JS n'ait réellement une chance de s'exécuter. Vous pouvez éviter cela en mettant une attente après avoir obtenu la page. Utiliser time.sleep est simple

browser.get(...)
time.sleep(1.5)

Cependant, cela peut vous faire attendre plus longtemps que nécessaire. Il serait donc préférable d'utiliser le prise en charge des conditions attendues de selenium. De cette façon, vous n'attendrez que le temps nécessaire.

from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC

condition = EC.presence_of_element_located((By.ID, "some_element_id_present_after_JS_load"))
driver.get(url)
WebDriverWait(driver, 10).until(condition)
print(driver.title)
# ... 
2
sytech 13 avril 2018 à 19:27

Pendant que vous invoquez l'url https://iapps.courts.state.ny.us/judicialdirectory/JudicialDirectory, le WebClient c'est-à-dire FirefoxBrowser atteint document.readyState égal à complete à un certain stade, mais cela ne signifie pas que tous les Javascript et appels Ajax associés sont terminés.

Maintenant, si vous regardez la balise <head> dans le HTML contenant le Titre de la page qui est rendu après qu'un certain Javascript se termine comme suit :

<script type="text/javascript" id="ucs-jd-internet-page-BioPage-0">
/*<![CDATA[*/

    function clearDefaultandCSS(el) {
      if (el.defaultValue == el.value)
    el.value = "";
    }

/*]]>*/
</script>
<title>Judicial Directory</title>

Ainsi, tant que le Javascript correspondant n'aura pas terminé le rendu, le titre de page n'est pas rendu. Par conséquent, vous ne pouvez pas récupérer le titre de page réel.

Dans ces cas, la meilleure approche serait d'induire WebDriverWait en conjonction avec expect_conditions définie comme title_contains comme suit:

browser.get("https://iapps.courts.state.ny.us/judicialdirectory/JudicialDirectory")
element = WebDriverWait(browser, 10).until(EC.title_contains(("Judicial Directory")))
print(browser.title)
browser.quit()
0
DebanjanB 13 avril 2018 à 19:49

J'ai utilisé la fonction WebDriverWait de Selenium, qui a résolu le problème.

browser.get(
    "https://iapps.courts.state.ny.us/judicialdirectory/JudicialDirectory")
element = WebDriverWait(browser, 10).until(
             EC.presence_of_element_located((By.ID, "column1_A630"))) # a random element
print([i.text for i in element.find_elements_by_xpath("//a[contains(@href, 'JUDGE_ID')]")])
browser.quit()
0
RCA 13 avril 2018 à 19:20