在Selenium中设置referer

时间:2013-12-22 18:11:47

标签: selenium http-referer

我正在使用selenium远程驱动程序来自动执行站点上的操作,我可以通过设计URL直接打开我需要的页面,因为站点url架构非常不变。这加快了脚本的速度,因为它不需要在它到达所需的页面之前完成多个页面。

为了使自动化看起来有机,有没有办法在Selenium中设置推荐页面?

4 个答案:

答案 0 :(得分:5)

如果您正在检查服务器上的推荐人,那么使用代理(如其他答案中所述)将是您的选择。

但是,如果您需要使用代理在Javascript中访问引荐来源将无法正常工作。要设置Javascript引用,我执行了以下操作:

  1. 转到推荐网站
  2. 通过Selenium API将此javascript注入页面:document.write('<script>window.location.href = "<my website>";</script>')"
  3. 我在selenium周围使用Python包装器,因此我无法提供您用语言注入代码所需的功能,但它应该很容易找到。

答案 1 :(得分:4)

这是Python中的一个解决方案:

https://github.com/j-bennet/selenium-referer

我在README中描述了用例和解决方案。我认为github repo不会去任何地方,但我会在这里引用相关部分以防万一。

该解决方案使用libmproxy实现仅执行一项操作的代理服务器:添加Referer标头。在运行代理时,标头被指定为命令行参数。代码:

# -*- coding: utf-8 -*-
"""
Proxy server to add a specified Referer: header to the request.
"""
from optparse import OptionParser
from libmproxy import controller, proxy
from libmproxy.proxy.server import ProxyServer


class RefererMaster(controller.Master):
    """
    Adds a specified referer header to the request.
    """

    def __init__(self, server, referer):
        """
        Init the proxy master.
        :param server: ProxyServer
        :param referer: string
        """
        controller.Master.__init__(self, server)
        self.referer = referer

    def run(self):
        """
        Basic run method.
        """
        try:
            print('Running...')
            return controller.Master.run(self)
        except KeyboardInterrupt:
            self.shutdown()

    def handle_request(self, flow):
        """
        Adds a Referer header.
        """
        flow.request.headers['referer'] = [self.referer]
        flow.reply()

    def handle_response(self, flow):
        """
        Does not do anything extra.
        """
        flow.reply()


def start_proxy_server(port, referer):
    """
    Start proxy server and return an instance.
    :param port: int
    :param referer: string
    :return: RefererMaster
    """
    config = proxy.ProxyConfig(port=port)
    server = ProxyServer(config)
    m = RefererMaster(server, referer)
    m.run()


if __name__ == '__main__':

    parser = OptionParser()

    parser.add_option("-r", "--referer", dest="referer",
                      help="Referer URL.")

    parser.add_option("-p", "--port", dest="port", type="int",
                      help="Port number (int) to run the server on.")

    popts, pargs = parser.parse_args()

    start_proxy_server(popts.port, popts.referer)

然后,在测试的 setUp()方法中,代理服务器作为外部进程启动,使用 pexpect ,并在 tearDown()中停止即可。名为 proxy()的方法返回代理设置以使用以下命令配置Firefox驱动程序:

# -*- coding: utf-8 -*-
import os
import sys
import pexpect
import unittest

from selenium.webdriver.common.proxy import Proxy, ProxyType

import utils


class ProxyBase(unittest.TestCase):
    """
    We have to use our own proxy server to set a Referer header, because Selenium does not
    allow to interfere with request headers.

    This is the base class. Change `proxy_referer` to set different referers.
    """

    base_url = 'http://www.facebook.com'

    proxy_server = None

    proxy_address = '127.0.0.1'
    proxy_port = 8888
    proxy_referer = None
    proxy_command = '{0} {1} --referer {2} --port {3}'

    def setUp(self):
        """
        Create the environment.
        """
        print('\nSetting up.')
        self.start_proxy()
        self.driver = utils.create_driver(proxy=self.proxy())

    def tearDown(self):
        """
        Cleanup the environment.
        """
        print('\nTearing down.')
        utils.close_driver(self.driver)
        self.stop_proxy()

    def proxy(self):
        """
        Create proxy settings for our Firefox profile.
        :return: Proxy
        """
        proxy_url = '{0}:{1}'.format(self.proxy_address, self.proxy_port)

        p = Proxy({
            'proxyType': ProxyType.MANUAL,
            'httpProxy': proxy_url,
            'ftpProxy': proxy_url,
            'sslProxy': proxy_url,
            'noProxy': 'localhost, 127.0.0.1'
        })

        return p

    def start_proxy(self):
        """
        Start the proxy process.
        """
        if not self.proxy_referer:
            raise Exception('Set the proxy_referer in child class!')

        python_path = sys.executable
        current_dir = os.path.dirname(__file__)
        proxy_file = os.path.normpath(os.path.join(current_dir, 'referer_proxy.py'))

        command = self.proxy_command.format(
            python_path, proxy_file, self.proxy_referer, self.proxy_port)

        print('Running the proxy command:')
        print(command)

        self.proxy_server = pexpect.spawnu(command)
        self.proxy_server.expect_exact(u'Running...', 2)

    def stop_proxy(self):
        """
        Override in child class to use a proxy.
        """
        print('Stopping proxy server...')
        self.proxy_server.close(True)
        print('Proxy server stopped.')

我希望我的单元测试在没有任何用户交互的情况下启动和停止代理服务器,并且找不到任何Python样本。这就是为什么我创建了github repo(上面的链接)。

希望这有助于某人。

答案 2 :(得分:3)

您要找的是referer spoofing

Selenium没有内置方法来执行此操作,但可以使用fiddler之类的代理来完成。 Fiddler还提供FiddlerCore component的纯API版本,以及对所有代理设置和数据的编程访问,从而允许您修改http响应的标头。

答案 3 :(得分:2)

不确定我是否正确理解您的问题,但如果您想覆盖您的HTTP请求,则无法直接使用webdriver。您必须通过代理运行您的请求。我更喜欢使用browsermob,你可以通过maven或类似的方式获得它。

ProxyServer server = new ProxyServer(proxy_port); //net.lightbody.bmp.proxy.ProxyServer;
server.start();
server.setCaptureHeaders(true);
Proxy proxy = server.seleniumProxy(); //org.openqa.selenium.Proxy
proxy.setHttpProxy("localhost").setSslProxy("localhost");

server.addRequestInterceptor(new RequestInterceptor() {
     @Override
     public void process(BrowserMobHttpRequest browserMobHttpRequest, Har har) {
        browserMobHttpRequest.addRequestHeader("Referer", "blabla");
     }
});

// configure it as a desired capability
DesiredCapabilities capabilities = new DesiredCapabilities();
capabilities.setCapability(CapabilityType.PROXY, proxy);
// start the driver
driver = new FirefoxDriver(capabilities);

或黑/白名单:

server.blacklistRequests("https?://.*\\.google-analytics\\.com/.*", 410);
server.whitelistRequests("https?://*.*.yoursite.com/.*. https://*.*.someOtherYourSite.*".split(","), 200);