我试图让用户轻松地从网页输入数字。我能想到的最简单的事情就是让他们提供一个url和一个与该数字相关的xpath。然后我的代码可以抓住数字。 xpath的概念并不为人所知(对于非编码器),但使用Chrome的Inspect和Developer工具找到xpath是微不足道的。这太好了。
问题是来自Chrome和Firefox的xpath并不总是能让你在html解析器中使用xpath,如下所述: Why does this xpath fail using lxml in python?
基本上,浏览器会将源更改为技术更正确的形式,然后他们会将此更改的表单显示给用户并将其xpath基于该表单。
如果您的代码有自动方式查看不是页面来源,而是Chrome的页面来源再现,则可以修复此问题。有没有一种有效的自动方式来做到这一点?
再一次,更简洁和准确:我如何为python提供Chrome生成的改变的HTML文档而不是原始的源文档来解析?
答案 0 :(得分:1)
我看到的唯一方法是实际运行Web引擎...
使用QtWebKit QWebFrame
,您可以使用setHtml
,toHtml
将返回由WebKit调整的源代码...
显然这是一个很大的依赖,但只需安装PySide就可以获得所需的一切。
所以事实证明这比我想象的要糟糕得多,至少需要将Qt与其他代码隔离开来。使用setHtml
似乎不允许您立即使用toHtml
;必须发生一些异步加载...
寻找一些更简单的WebKit绑定可能会更有意义。
因此,load_source
都会从URL下载数据,并在WebKit修改后返回HTML。它用它的异步事件包装Qt的事件循环,并且是一个阻塞函数。
setUrl
可以替换为setHtml
。
from PySide.QtCore import QObject, QUrl, Slot
from PySide.QtGui import QApplication
from PySide.QtWebKit import QWebPage, QWebSettings
qapp = QApplication([])
def load_source(url):
page = QWebPage()
page.settings().setAttribute(QWebSettings.AutoLoadImages, False)
page.mainFrame().setUrl(QUrl(url))
class State(QObject):
src = None
finished = False
@Slot()
def loaded(self, success=True):
self.finished = True
if self.src is None:
self.src = page.mainFrame().toHtml()
state = State()
# Optional; reacts to DOM ready, which happens before a full load
def js():
page.mainFrame().addToJavaScriptWindowObject('qstate$', state)
page.mainFrame().evaluateJavaScript('''
document.addEventListener('DOMContentLoaded', qstate$.loaded);
''')
page.mainFrame().javaScriptWindowObjectCleared.connect(js)
page.mainFrame().loadFinished.connect(state.loaded)
while not state.finished:
qapp.processEvents()
return state.src
使用链接问题中的示例进行演示。现在它确实有用......
from lxml import html
url = 'http://www.makospearguns.com/product-p/mcffgb.htm'
xpath = '//*[@id="v65-product-parent"]/tbody/tr[2]/td[2]/table[1]/tbody/tr/td/table/tbody/tr[2]/td[2]/table/tbody/tr[1]/td[1]/div/table/tbody/tr/td/font/div/b/span/text()'
src = load_source(url)
tree = html.fromstring(src)
text = tree.xpath(xpath)
答案 1 :(得分:1)
使用Selenium。 https://selenium-python.readthedocs.org
from selenium import webdriver
browser = webdriver.Chrome()
browser.get('http://example.com')
html_source = browser.page_source
您可以使用lxml解析html_source
(Chrome浏览器源代码)。