【问题标题】:Any way to tell selenium don't execute js at some point?有什么方法可以告诉 selenium 在某些时候不要执行 js?
【发布时间】:2016-03-22 01:26:23
【问题描述】:

我想抓取一个有一些由 js 生成的内容的网站。 该站点每 5 秒运行一次 js 更新内容(请求新的加密 js 文件,无法解析)。

我的代码:

from selenium import webdriver

driver = webdriver.PhantomJS()
driver.set_window_size(1120, 550)

driver.get(url)

trs = driver.find_elements_by_css_selector('.table tbody tr')

print len(trs)

for tr in trs:
    try:
        items.append(tr.text)
    except:
        # because the js update content, so this tr is missing
        pass

print len(items)

len(items)len(trs) 不匹配。 我运行trs = driver.find_elements_by_css_selector('.table tbody tr')后如何告诉selenium停止执行js或停止工作?

我需要稍后使用trs,所以不能driver.quit()

异常详情

---------------------------------------------------------------------------
StaleElementReferenceException            Traceback (most recent call last)
<ipython-input-84-b80e3579efca> in <module>()
     11 items = []
     12 for tr in trs:
---> 13     items.append(tr.text)
     14     #items.append(map_label(hidemyass_label, tr.find_elements_by_tag_name('td')))
     15 

C:\Python27\lib\site-packages\selenium\webdriver\remote\webelement.pyc in text(self)
     69     def text(self):
     70         """The text of the element."""
---> 71         return self._execute(Command.GET_ELEMENT_TEXT)['value']
     72 
     73     def click(self):

C:\Python27\lib\site-packages\selenium\webdriver\remote\webelement.pyc in _execute(self, command, params)
    452             params = {}
    453         params['id'] = self._id
--> 454         return self._parent.execute(command, params)
    455 
    456     def find_element(self, by=By.ID, value=None):

C:\Python27\lib\site-packages\selenium\webdriver\remote\webdriver.pyc in execute(self, driver_command, params)
    199         response = self.command_executor.execute(driver_command, params)
    200         if response:
--> 201             self.error_handler.check_response(response)
    202             response['value'] = self._unwrap_value(
    203                 response.get('value', None))

C:\Python27\lib\site-packages\selenium\webdriver\remote\errorhandler.pyc in check_response(self, response)
    179         elif exception_class == UnexpectedAlertPresentException and 'alert' in value:
    180             raise exception_class(message, screen, stacktrace, value['alert'].get('text'))
--> 181         raise exception_class(message, screen, stacktrace)
    182 
    183     def _value_or_default(self, obj, key, default):

StaleElementReferenceException: Message: {"errorMessage":"Element is no longer attached to the DOM","request":{"headers":{"Accept":"application/json","Accept-Encoding":"identity","Connection":"close","Content-Type":"application/json;charset=UTF-8","Host":"127.0.0.1:63305","User-Agent":"Python-urllib/2.7"},"httpVersion":"1.1","method":"GET","url":"/text","urlParsed":{"anchor":"","query":"","file":"text","directory":"/","path":"/text","relative":"/text","port":"","host":"","password":"","user":"","userInfo":"","authority":"","protocol":"","source":"/text","queryKey":{},"chunks":["text"]},"urlOriginal":"/session/4bb16340-a3b6-11e5-8ce5-9d0be40203a6/element/%3Awdc%3A1450243990539/text"}}
Screenshot: available via screen

显然 tr 丢失了。

PS:我需要使用 selenium 来选择元素。其他库如lxmlpyquery 不知道哪个元素是display:none.text() 经常在&lt;script&gt; 中得到评论或其他内容,等等错误。可惜python没有完美的jquery克隆。

【问题讨论】:

  • 您能否删除try/except - 如果有的话,您会遇到什么错误?
  • @alecxe 我已经粘贴了异常。
  • @Mithril 也许您可以尝试像.find_elements_by_css_selector('.table tbody tr').text 一样一次获取表格的整个文本,然后通过字符串操作存储tex。
  • @Mesut Güneş 例如我只是写代码,我需要在 tr 下操作一些 td,for 循环可能会花费几秒钟,然后 tr 丢失.....

标签: python selenium web-crawler


【解决方案1】:

使用scrapy。确定页面已加载后,使用以下命令抓取正文:

response = TextResponse(url=self.driver.current_url, body=self.driver.page_source, encoding='utf-8')

您现在拥有该页面的静态副本,以便您可以使用 scrapy 的 response.xpath 来提取您需要的任何数据。这个answer 更详细。

【讨论】:

  • scrapy 只是一个爬虫框架,为scrapy添加硒或飞溅支持对我的问题没有帮助。您的代码就像使用lxml解析driver.page_source,但lxml(我认为scrapy 也在使用lxml)不知道哪个元素是display:none(以及许多其他错误)。我需要使用硒来选择元素。所以我问标题。
  • @Mithril 一旦有了静态副本,就不会每 5 秒更新一次 JS。你有一个快照,所以即使你的 for 循环需要几秒钟,也没有任何变化。您甚至可以保存 response.body 并在第二天处理它。
  • 您不能将静态 html 传递给 selenium。我需要使用 selenium 来选择。
  • @Mithril,我们可能有不同的目的。我会使用Selenium 来抓取包含所有 JS 渲染内容的页面。如上所述复制该 HTML,然后使用 scrapy 从静态 HTML 中提取我需要的信息。你是说由于某种原因不能使用scrapy
  • 不,我已经提到没有一个 python 包可以处理 html 和 jquery。 Antispider 站点有很多随机的垃圾 dom 元素来干扰提取真实内容。只有 jquery(node.js) 和 selenium 可以轻松提取真实内容。我不想浪费时间打破防蜘蛛规则。
猜你喜欢
  • 2022-01-01
  • 2021-11-26
  • 2010-10-25
  • 1970-01-01
  • 2014-08-23
  • 2019-06-16
  • 2011-05-12
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多