1

美しいスープを使ってウェブサイトからデータをスクレイピングしようとしています。デフォルトでは、この Web ページには 18 項目が表示されます。JavaScript ボタン「showAlldevices」をクリックすると、41 項目すべてが表示されます。美しいスープは、デフォルトで表示されているアイテムのデータのみをスクレイピングし、すべてのアイテムのデータを取得するために、PyQt モジュールを使用し、javascript コードを使用してクリック イベントを呼び出しました。以下は参照されたコードです:

import csv
import urllib2
import sys
import time
from bs4 import BeautifulSoup
from PyQt4.QtGui import *  
from PyQt4.QtCore import *  
from PyQt4.QtWebKit import *  

class Render(QWebPage):  
  def __init__(self, url):  
    self.app = QApplication(sys.argv)  
    QWebPage.__init__(self)  
    self.loadFinished.connect(self._loadFinished)  
    self.mainFrame().load(QUrl(url))  
    self.app.exec_()  

  def _loadFinished(self, result):  
    self.frame = self.mainFrame()  
    self.app.quit()  

url = 'http://www.att.com/shop/wireless/devices/smartphones.html'  
r = Render(url)
jsClick = """var evObj = document.createEvent('MouseEvents');
             evObj.initEvent('click', true, true );
             this.dispatchEvent(evObj);
             """

allSelector = "a#deviceShowAllLink" 
allButton   = r.frame.documentElement().findFirst(allSelector)
allButton.evaluateJavaScript(jsClick) 
html = allButton.webFrame().toHtml()


page = html
soup = BeautifulSoup(page)
soup.prettify()
with open('Smartphones_26decv2.0.csv', 'wb') as csvfile:
    spamwriter = csv.writer(csvfile, delimiter=',')
    spamwriter.writerow(["Date","Day of Week","Device Name","Price"])
    items = soup.findAll('a', {"class": "clickStreamSingleItem"},text=True)
    prices = soup.findAll('div', {"class": "listGrid-price"})
    for item, price in zip(items, prices):
        textcontent = u' '.join(price.stripped_strings)
        if textcontent:            
            spamwriter.writerow([time.strftime("%Y-%m-%d"),time.strftime("%A") ,unicode(item.string).encode('utf8').strip(),textcontent])

このコード行を使用して、html を美しいスープにフィードしていますhtml = allButton.webFrame().toHtml()。このコードはエラーなしで実行されていますが、出力 csv の 41 項目すべてのデータを取得していません。

また、次のコード行を使用して、HTML を美しいスープにフィードしようとしました。

allButton   = r.frame.documentElement().findFirst(allSelector)
a = allButton.evaluateJavaScript(jsClick) 
html = a.webFrame.toHtml()


page = html
soup = BeautifulSoup(page)

しかし、私はこのエラーに遭遇しました:html = a.webFrame.toHtml() AttributeError: 'QVariant' object has no attribute 'webFrame'

私はプログラミングが初めてで、この問題の解決を手伝ってくれるので、ここで基本的なことを尋ねている場合は、私の無知を許してください。

4

1 に答える 1

0

JavaScriptコードに問題があると思います。MouseEventオブジェクトを作成しているのでinitMouseEvent、初期化にはメソッドを使用する必要があります。ここに例があります。

UPDATE2

しかし、あなたが試すことができる最も簡単な考えは、独自のJavaScriptコードを使用する代わりにonclick、要素のJavaScriptDOMメソッドを使用することだと思います。aこのようなもの:

allButton.evaluateJavaScript("this.onclick()")

動作するはずです。クリックした後、パーサーに渡す前に、ページをリロードする必要があると思います。

更新3

r.action(QWebPage.ReloadAndBypassCache)またはを介してページをリロードできますr.action(QWebpage.Reload)が、効果がないようです。でページを表示しようとしましたQWebView。リンクをクリックして、何が起こるかを確認してください。残念ながら、セグメンテーション違反のエラーがたくさん発生しているので、PyQt4/Qt4のどこかにバグがあることを誓います。スクラップされているページはjqueryを使用しているため、jqueryをロードした後に表示しようとしましたQWebPageが、運がありません(segfaultsは消えません)。私はあきらめています:(ここSOの他のユーザーがあなたを助けてくれることを願っています。とにかく私はあなたがPyQt4メーリングリストに助けを求めることをお勧めします。彼らはPyQtユーザーに優れたサポートを提供します。

アップデート

コードを変更するときに発生するエラーが予想されます。これallButtonQWebElementオブジェクトであることを忘れないでください。そして、QWebElement.evaluateJavaScriptメソッドはオブジェクトを返し(ドキュメントQVariantに記載されているように)、このページのレビューを確認できるように、その種類のオブジェクトには属性がありません。webFrame

于 2012-12-27T08:43:48.437 に答える