【问题标题】:Issues with invoking "on click event" on the html page using beautiful soup in Python在 Python 中使用漂亮的汤在 html 页面上调用“点击事件”的问题
【发布时间】:2012-12-07 16:40:23
【问题描述】:

我正在尝试抓取网页上所有项目的名称,但默认情况下页面上只有 18 个可见,而我的代码仅抓取那些。您可以通过单击“全部显示”按钮查看所有项目,但该按钮是 Javascript 格式的。

经过一番研究,我发现 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" # This is the css selector you actually need
allButton   = r.frame.documentElement().findFirst(allSelector)
allButton.evaluateJavaScript(jsClick)




page = allButton
soup = BeautifulSoup(page)
soup.prettify()
with open('Smartphones_26decv1.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])

我在这方面面临的错误如下:

"Invalid Syntax" Error for evObj

有人可以帮我调用这个“onclick”事件,以便我能够抓取所有项目的数据。请原谅我的无知,因为我是编程新手。

【问题讨论】:

  • 你最好解释一下JS 做什么。它很可能只是通过 AJAX 加载数据,可能是 HTML 或 JSON。您可以使用开发者工具查看浏览器的功能;所有主流浏览器都带有此类工具,使用它们的网络选项卡查看完成了哪些额外请求。
  • @MartijnPieters 点击“显示所有设备”后,网络选项卡向我显示了之前使用方法“获取”隐藏的设备的额外条目
  • @MartijnPieters,您能否更具体地了解如何使用 javascript 抓取网页中的数据?任何参考都可以。

标签: python python-2.7 onclick pyqt beautifulsoup


【解决方案1】:
from contextlib import closing
from selenium.webdriver import Firefox # pip install selenium
from selenium.webdriver.support.ui import WebDriverWait
from BeautifulSoup import BeautifulSoup
from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions as EC
# use firefox to get page with javascript generated content
with closing(Firefox()) as driver:
    driver.get("http://www.att.com/shop/wireless/devices/smartphones.html")
    button = driver.find_element_by_id('deviceShowAllLink')
    button.click()
    # wait for the page to load
    element = WebDriverWait(driver, 10).until(
    EC.invisibility_of_element_located((By.ID, "deviceShowAllLink"))
    )
    # store it to string variable
    page_source = driver.page_source

soup = BeautifulSoup(page_source)
items = soup.findAll('div', {"class": "list-item"})
print "items count:",len(items)

这会有帮助吗..?

【讨论】:

    【解决方案2】:

    要单击按钮,您必须在对象上调用evaluateJavascript

    jsClick = """var evObj = document.createEvent('MouseEvents');
                 evObj.initEvent('click', true, true );
                 this.dispatchEvent(evObj);
                 """
    
    allSelector = "a#deviceShowAllLink" # This is the css selector you actually need
    allButton   = r.frame.documentElement().findFirst(allSelector)
    allButton.evaluateJavaScript(jsClick)
    

    【讨论】:

    • 我需要导入一些东西来运行这段代码吗?运行此“selectorAll”后未定义错误即将到来
    • @user1915050 修复了代码中未定义的变量,对此感到抱歉,看看现在是否有效
    • 圣诞快乐,我根据您的代码进行了更改,并遇到了上述错误 - evObj 的“无效语法”错误。请浏览我上面帖子中的更新代码
    • 另外你为什么提到在cmets中声明jsClick?
    • @user1915050 那是因为你在那里运行的是一段 javascript 代码,我三重引用它以允许字符串生成多行而不必用 \n\ 终止每一行,我可以把它放在单引号和一行中,但是我选择了这种提高可读性的方法,看看如果你再次运行那段代码会发生什么,就像我的例子一样
    猜你喜欢
    • 1970-01-01
    • 2012-08-01
    • 1970-01-01
    • 2012-12-08
    • 1970-01-01
    • 2017-08-15
    • 1970-01-01
    • 1970-01-01
    • 2018-11-03
    相关资源
    最近更新 更多