我正在尝试使用漂亮的汤从网站上抓取数据。默认情况下,此网页显示18个项目,点击javascript按钮“showAlldevices”后,所有41个项目都可见。美丽的汤仅为默认情况下可见的项目擦除数据,以获取我使用PyQt模块的所有项目的数据,并使用javascript代码调用click事件。以下是推荐代码:
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 = allButton.webFrame().toHtml()
将html提供给漂亮的汤。此代码运行时没有任何错误但我仍然没有获得输出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'
如果我在这里问任何根本问题,请原谅我的无知,因为我是编程新手并帮助我解决这个问题。
答案 0 :(得分:0)
我认为您的JavaScript代码存在问题。由于您要创建MouseEvent
对象,因此应使用initMouseEvent
方法进行初始化。您可以找到示例here。
<强> UPDATE2 强>
但我认为您可以尝试的最简单的方法是使用onclick
元素的JavaScript DOM方法a
,而不是使用您自己的JavaScript代码。像这样:
allButton.evaluateJavaScript("this.onclick()")
应该有效。我想你必须在点击之后重新加载页面,然后再将它传递给解析器。
更新3
您可以通过r.action(QWebPage.ReloadAndBypassCache)
或r.action(QWebpage.Reload)
重新加载页面,但似乎没有任何效果。我试图用QWebView
显示页面,点击链接,看看会发生什么。不幸的是我收到了很多Segmentation Fault错误,所以我发誓PyQt4 / Qt4中有一个bug。由于被废弃的页面使用了jquery,我还试图在QWebPage
中加载jquery之后显示它,但是再次没有运气(段错误不会消失)。我放弃了:(我希望SO的其他用户能为您提供帮助。无论如何,我建议您向the PyQt4 mailing list寻求帮助。他们为PyQt用户提供了极好的支持。
<强>更新强>
预计更改代码时会出现错误:请记住allButton
是QWebElement
对象。并且QWebElement.evaluateJavaScript
方法返回QVariant
对象(如the docs中所述),并且该类对象没有webFrame
属性,因为您可以检查{{3} }}