我试图开发一个简单的网页刮板。我想提取没有HTML代码的文本。它适用于普通HTML,但不适用于JavaScript代码添加文本的某些页面。
例如,如果一些JavaScript代码添加了一些文本,我不能看到它,因为当我调用:
response = urllib2.urlopen(request)
我得到了原始文本而没有添加的文本(因为JavaScript是在客户端执行的)。
所以,我正在寻找一些解决这个问题的想法。
我试图开发一个简单的网页刮板。我想提取没有HTML代码的文本。它适用于普通HTML,但不适用于JavaScript代码添加文本的某些页面。
例如,如果一些JavaScript代码添加了一些文本,我不能看到它,因为当我调用:
response = urllib2.urlopen(request)
我得到了原始文本而没有添加的文本(因为JavaScript是在客户端执行的)。
所以,我正在寻找一些解决这个问题的想法。
当前回答
你也可以使用webdriver执行javascript。
from selenium import webdriver
driver = webdriver.Firefox()
driver.get(url)
driver.execute_script('document.title')
或者将值存储在变量中
result = driver.execute_script('var text = document.title ; return text')
其他回答
Pyppeteer
你可以考虑Pyppeteer,它是Chrome/Chromium驱动程序前端的Python移植版本。
下面是一个简单的例子,展示了如何使用pyppeterer动态地访问被注入到页面中的数据:
import asyncio
from pyppeteer import launch
async def main():
browser = await launch({"headless": True})
[page] = await browser.pages()
# normally, you go to a live site...
#await page.goto("http://www.example.com")
# but for this example, just set the HTML directly:
await page.setContent("""
<body>
<script>
// inject content dynamically with JS, not part of the static HTML!
document.body.innerHTML = `<p>hello world</p>`;
</script>
</body>
""")
print(await page.content()) # shows that the `<p>` was inserted
# evaluate a JS expression in browser context and scrape the data
expr = "document.querySelector('p').textContent"
print(await page.evaluate(expr, force_expr=True)) # => hello world
await browser.close()
asyncio.get_event_loop().run_until_complete(main())
请参阅pyppeterer的参考文档。
这似乎是一个很好的解决方案,从一个伟大的博客文章
import sys
from PyQt4.QtGui import *
from PyQt4.QtCore import *
from PyQt4.QtWebKit import *
from lxml import html
#Take this class for granted.Just use result of rendering.
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://pycoders.com/archive/'
r = Render(url)
result = r.frame.toHtml()
# This step is important.Converting QString to Ascii for lxml to process
# The following returns an lxml element tree
archive_links = html.fromstring(str(result.toAscii()))
print archive_links
# The following returns an array containing the URLs
raw_links = archive_links.xpath('//div[@class="campaign"]/a/@href')
print raw_links
Selenium是抓取JS和Ajax内容的最佳工具。
查看这篇文章,了解如何使用Python从web中提取数据
$ pip install selenium
然后下载Chrome webdriver。
from selenium import webdriver
browser = webdriver.Chrome()
browser.get("https://www.python.org/")
nav = browser.find_element_by_id("mainnav")
print(nav.text)
容易,对吧?
使用PyQt5
from PyQt5.QtWidgets import QApplication
from PyQt5.QtCore import QUrl
from PyQt5.QtWebEngineWidgets import QWebEnginePage
import sys
import bs4 as bs
import urllib.request
class Client(QWebEnginePage):
def __init__(self,url):
global app
self.app = QApplication(sys.argv)
QWebEnginePage.__init__(self)
self.html = ""
self.loadFinished.connect(self.on_load_finished)
self.load(QUrl(url))
self.app.exec_()
def on_load_finished(self):
self.html = self.toHtml(self.Callable)
print("Load Finished")
def Callable(self,data):
self.html = data
self.app.quit()
# url = ""
# client_response = Client(url)
# print(client_response.html)
听起来好像你真正要找的数据可以通过主页面上的一些javascript调用的辅助URL访问。
虽然您可以尝试在服务器上运行javascript来处理这个问题,但一种更简单的方法可能是使用Firefox加载页面,并使用Charles或Firebug之类的工具来准确识别辅助URL。然后,您可以直接查询该URL以获得您感兴趣的数据。