2016-12-15 6 views
1

私はAJAXでデータを読み込むサイトを削っています。私はリストに入れたたくさんのURLでこれをやりたい私はforループを使って繰り返します。私のコードは美しいスープ4の好奇心的なエラーループの繰り返し

import requests 
from bs4 import BeautifulSoup 
from selenium import webdriver 
import pandas as pd 
import pdb 

listUrls = ['https://www.flipkart.com/samsung-galaxy-nxt-gold-32-gb/p/itmemzd4gepexjya','https://www.flipkart.com/samsung-galaxy-on8-gold-16-gb/p/itmemvarkqg5dyay'] 
PHANTOMJS_PATH = './phantomjs' 
browser = webdriver.PhantomJS(PHANTOMJS_PATH) 

for url in listUrls: 
    browser.get(url) 
    soup = BeautifulSoup(browser.page_source, "html.parser") 
    labels = soup.findAll('li', {'class':"_1KuY3T row"}) 
    print labels 

このコードを実行すると、最初のURLの結果が得られますが、2番目のものは空白のリストが表示されます。私は両方のURLとそれが働いてスープを印刷しようとしました。このエラーは、ラベルを印刷している間だけ持続します。最初のURLのラベルは印刷されますが、2番目のリストは空です。

[<truncated>...Formats</div><ul class="_3dG3ix col col-9-12"><li class="sNqDog">MP3</li></ul></li>, <li class="_1KuY3T row"><div class="vmXPri col col-3-12">Battery Capacity</div><ul class="_3dG3ix col col-9-12"><li class="sNqDog">3300 mAh</li></ul></li>, <li class="_1KuY3T row"><div class="vmXPri col col-3-12">Battery Type</div><ul class="_3dG3ix col col-9-12"><li class="sNqDog">Li-Ion</li></ul></li>, <li class="_1KuY3T row"><div class="vmXPri col col-3-12">Width</div><ul class="_3dG3ix col col-9-12"><li class="sNqDog">75 mm</li></ul></li>, <li class="_1KuY3T row"><div class="vmXPri col col-3-12">Height</div><ul class="_3dG3ix col col-9-12"><li class="sNqDog">151.7 mm</li></ul></li>, <li class="_1KuY3T row"><div class="vmXPri col col-3-12">Depth</div><ul class="_3dG3ix col col-9-12"><li class="sNqDog">8 mm</li></ul></li>, <li class="_1KuY3T row"><div class="vmXPri col col-3-12">Warranty Summary</div><ul class="_3dG3ix col col-9-12"><li class="sNqDog">1 Year Manufacturer Warranty</li></ul></li>] 
[] 

Image:Result when I print labels in a loop

私はこれをさらにデバッグするインタラクティブなデバッグモジュールのPDBを使用し、好奇心旺盛なことが起こった - 私は、印刷ラベルの前にスタックトレースを追加し、ステップでループステップを実行したとき、それはラベルのリストを出力します2番目のURLの場合も同様です。

for url in listUrls: 
    browser.get(url) 
    soup = BeautifulSoup(browser.page_source, "html.parser") 
    labels = soup.findAll('li', {'class':"_1KuY3T row"}) 
    pdb.set_trace() 
    print labels 

...

[<truncated>..."vmXPri col col-3-12">Depth</div><ul class="_3dG3ix col col-9-12"><li class="sNqDog">8 mm</li></ul></li>, <li class="_1KuY3T row"><div class="vmXPri col col-3-12">Warranty Summary</div><ul class="_3dG3ix col col-9-12"><li class="sNqDog">1 Year Manufacturer Warranty</li></ul></li>] 
> /Users/aamnasimpl/Desktop/Scraper/web-scraper.py(12)<module>() 
-> for url in listUrls: 
(Pdb) n 
> /Users/aamnasimpl/Desktop/Scraper/web-scraper.py(13)<module>() 
-> browser.get(url) 
(Pdb) n 
> /Users/aamnasimpl/Desktop/Scraper/web-scraper.py(15)<module>() 
-> soup = BeautifulSoup(browser.page_source, "html.parser") #put all html in soup 
(Pdb) n 
> /Users/aamnasimpl/Desktop/Scraper/web-scraper.py(16)<module>() 
-> labels = soup.findAll('li', {'class':"_1KuY3T row"}) 
(Pdb) n 
> /Users/aamnasimpl/Desktop/Scraper/web-scraper.py(17)<module>() 
-> pdb.set_trace() 
(Pdb) 
> /Users/aamnasimpl/Desktop/Scraper/web-scraper.py(18)<module>() 
-> print labels 
(Pdb) n 
[<li class="_1KuY3T row"><div class="vmXPri col col-3-12">Sales Package</div><ul class="_3dG3ix col col-9-12"><li class="sNqDog">Handset, Adapter, Earphone, User Manual</li></ul></li>, <li class="_1KuY3T row"><div class="vmXPri col col-3-12">Model Number</div><ul class="_3dG3ix col col-9-12"><li class="sNqDog">J710FZDGINS</li></ul></li>, <li class="_1KuY3T row"><div class="vmXPri col col-3-12">Model Name</...<truncated>] 

Image: Result when I run the code with stack trace

私はまた、ループ内で個別に各URLをチェックしましたし、それが正常に動作します。私はプログラミングに慣れていないし、今は失われているし、なぜこれが起こっているのかについての洞察を本当に感謝するだろう。ありがとう!

+2

追加することができればそれが役立つだろう結果/スタックは、画像の代わりに質問のテキストとしてトレースされます。 –

+0

@テムリシコしました。 – dontpanic

答えて

0

デバッグ中に動作するという事実は、これがのタイミング問題であることを示唆しています。あなたはそれを段階的にデバッグするとき、基本的にはページを読み込む時間が長くなり、ラベルが正しく印刷されます。あなたがする必要がどのような

Explicit Waitを追加することで物事をより信頼性と予測することです - ページ上に存在することが、少なくとも一つのラベルを待つ:

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

# ... 

for url in listUrls: 
    browser.get(url) 

    # wait for labels to be present/rendered 
    wait = WebDriverWait(browser, 20) 
    wait.until(EC.presence_of_element_located((By.CSS_SELECTOR, "li._1KuY3T.row"))) 

    soup = BeautifulSoup(browser.page_source, "html.parser") 
    labels = soup.select("li._1KuY3T.row") 
    print(labels) 
+0

ありがとう@alecxe!これはうまくいった。私にはわかりませんが、ループが1番目のURLで動作する場合、2番目のURLで動作するよう明示的に追加する必要があるのはなぜですか? – dontpanic

+0

@dontpanicまあ、コードを実行すると、何百回も、私はあなたも最初のもので失敗するのを見るだろうと思う。ポイントは、待機がコードを信頼できるものにしていることです。特定のポイントでレンダリングされる要素について仮定しないで、明示的にそれを待つだけです。トピックを解決するための答えを受け入れることを検討してください、ありがとう。 – alecxe