【问题标题】:Python: How to run multiple PhantomJS instance efficiently?Python:如何高效地运行多个 PhantomJS 实例?
【发布时间】:2017-03-20 07:49:08
【问题描述】:

我正在使用这个库from multiprocessing import Pool 来使用多处理。

虽然我使用的是requests,但我想使用 selenium,因为一些数据正在弹出窗口中加载。在不发生内存泄漏的情况下使用 Phantomjs 的最佳方法是什么?

【问题讨论】:

  • 设置一个硒网格,maxInstances 设置为每个节点可以处理的东西,这样你就可以根据需要添加节点?您要查找多少个实例?每分钟有多少请求?如果这不是一个选项,或许可以考虑重用 selenium 会话并在它们发出请求时轮换它们?
  • @jmunsch 不知道Selenium Grid。因为我愿意一次使用并行处理,所以 5 个实例。每个请求都会有 2-5 秒的延迟。
  • @jmunsch 其次,我需要一个基于服务器的解决方案,这个网格似乎安装了 Java
  • “基于服务器的解决方案”是什么意思?是为了单元测试吗?或者像爬行/刮擦之类的东西?如果是用于单元测试,则可以考虑将 xvfb 与 pyvirtualdisplay 一起使用,如果用于抓取,则继续执行您正在执行的操作,但出于内存原因考虑将其放入 docker 容器中,并在其前面添加一个休息接口,这样您可以通过“重新启动” docker 容器来处理内存泄漏。同样,您可以使用指向所有容器和休息接口的负载均衡器水平扩展它。
  • @jmunsch 你提出了一些强有力的建议。您能否指导我一些资源以进一步了解此类设置?

标签: python selenium phantomjs


【解决方案1】:

大致翻译的基本思想可能是这样的:

from __future__ import unicode_literals
import logging
from werkzeug.routing import Map
from werkzeug.exceptions import HTTPException
from werkzeug.wrappers import Request
class WebApp(object):

    def __init__(self, **kw):
        self.log = logging.getLogger(__name__)

    def __call__(self, environ, start_response):
        return self.wsgi_app(environ, start_response)

    def wsgi_app(self, environ, start_response):
        request = Request(environ)
        response = self.dispatch_request(request)
        return response(environ, start_response)

    def dispatch_request(self, request):
        adapter = self.url_map.bind_to_environ(request.environ)
        try:
            endpoint, values = adapter.match()
            method = getattr(self, 'endpoint_{}'.format(endpoint))
            return method(adapter, request, **values)
        except HTTPException, e:
            return e

    url_map = Map([])


from pyvirtualdisplay import Display
from selenium import webdriver
from selenium.webdriver.common.keys import Keys
from subprocess import Popen, PIPE
import multiprocessing
display = Display(visible=0, size=(800, 600))
display.start()

def get_proxy_obj():
    proxy = '123.456.789.012'

    proxyobj = Proxy({
        'proxyType': ProxyType.MANUAL,
        'httpProxy': proxy,
        'ftpProxy': proxy,
        'sslProxy': proxy,
        'noProxy': '' # set this value as desired
    })
    capabilities = DesiredCapabilities().FIREFOX
    capabilities['acceptSslCerts'] = True
    proxyobj.add_to_capabilities(capabilities)
    return capabilities





drivers = [
     Firefox(FirefoxProfile('/etc/firefox/u2vgyy61.Proxied_User/'),
             capabilities=get_capabilities()),
     Firefox(FirefoxProfile('/etc/firefox/u2vgyy61.Proxied_User/'),
             capabilities=get_capabilities()),
     Firefox(FirefoxProfile('/etc/firefox/u2vgyy61.Proxied_User/'),
             capabilities=get_capabilities())
 ]

class Routes(WebApp):
    def endpoint_get_response(self, adapter, request, **values):
        url = request.values.get("query_param_here","")
        if url:
            # something better here
            while True:
                try:
                    driver = driver.pop()
                    resposne_txt = driver.get(url)
                    # response_txt = Popen(['docker', "exec", "-it", "selenium_phantom", url]).communicate()[0]
                    drivers.append(driver)
                    return Response(response_text)
                except:
                    sleep(1)
                    continue

        else:
            return Response("Not", status=400)

    url_map = Map([
            Rule('/get_response', endpoint='get_response', methods=['GET']),
        ])

例如用法:

curl http://node1/get_response?query_param_here=http://stackoverflow.com
curl http://node2/get_response?query_param_here=http://stackoverflow.com
curl http://node3/get_response?query_param_here=http://stackoverflow.com
curl http://node4/get_response?query_param_here=http://stackoverflow.com
...
and so on

前面有一个负载均衡器,例如:

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-04-30
    • 1970-01-01
    • 2015-09-25
    • 1970-01-01
    • 1970-01-01
    • 2015-12-21
    • 2015-04-24
    • 2014-12-16
    相关资源
    最近更新 更多