0

我有一个 Python 脚本,它使用 urllib2 从外部站点检索数据。我在需要代理身份验证的公司网络上。

在命令行上,我可以在 .bashrc 中导出代理设置,以允许脚本通过代理退出并发出请求。

所以脚本确实在代理后面工作。

这是问题所在:我需要从网站上的 php 脚本调用这个 Python 脚本。我尝试了几种方法来通过调用脚本来实现这一点:exec()、popen()、shell_exec()

我无法让脚本返回任何结果。当拖尾 /var/log/httpd/error* * 我可以看到正在生成的错误:

urllib2.URLError: <urlopen error [Errno 110] Connection timed out>, referer:

这是我在 .bashrc 中设置代理之前收到的相同错误

我已将 suPHP 设置并配置为以特定用户身份运行脚本。我还设置了所有文件,包括该用户拥有的 python 脚本,并调整了权限,尝试 +x 并且出于测试目的不安全地设置为 777。

我可以从网站的同一目录运行一个 php 脚本,并验证 Apache 是否在该用户下运行,只需:

echo exec('whoami');

我还可以使用相同的设置从同一个 PHP 页面执行一个简单的 Python 脚本,该设置只打印到标准输出,我可以将该值返回到网页,所以我知道我可以使用这种方法执行 Python 脚本。

在命令行中,我 su 到与运行 Apache 的用户相同的用户,并在该帐户中设置代理,但是,从网页执行时脚本仍然无法正确执行,仍然只能在命令行界面。

只是为了测试,我在 Python 脚本中添加了一行写入文件,目的是将数据写入我需要返回的文件,并认为我可以稍后再读取该文件。我注意到,文件的创建工作,但没有数据写入它,因为 urllib2 代码超时并且从不写入文件。

知道如何让我的 PHP 脚本执行这个需要代理访问的 Python 脚本吗?

我需要明确告诉 urllib2 使用代理吗?我正在使用的 urllib2 例程是 Python 模块的一部分,该模块被编码为仅使用操作系统的代理设置,而且我知道它可以工作,因为我可以在 CLI 的 Apache 用户下执行它。

任何帮助是极大的赞赏。

4

2 回答 2

1

要通知 urllib2 使用代理,您可以使用ProxyHandler

proxy = urllib2.ProxyHandler({'http': '127.0.0.1'})
opener = urllib2.build_opener(proxy)
urllib2.install_opener(opener)
urllib2.urlopen('http://www.google.com')

令人惊讶的是,您必须明确地这样做,因为文档urlopen说:

此外,如果检测到代理设置(例如,设置了 http_proxy 等 *_proxy 环境变量时),则默认安装 ProxyHandler 并确保通过代理处理请求。

您是否在脚本运行的环境中正确设置了http_proxy环境变量?


您将在上一个问题中找到有关如何使用带有 urllib2 的代理的更多信息:带有 urllib2 的代理

于 2013-06-14T19:01:47.520 回答
0

您可以尝试将显式代理设置传递给您的 Python 脚本,看看是否可以为您解决问题。我最近编写了一个脚本,允许您使用可能对这种情况有用的命令行参数设置代理设置。脚本的重要部分如下:

# Import the required libraries
from urllib import urlencode
from urllib2 import Request, urlopen, URLError, ProxyHandler, build_opener, install_opener
import argparse

# Set up our argument parser
parser = argparse.ArgumentParser(description='Does stuff through a proxy')
parser.add_argument('webAddr', type=str, help='Web address of target server')
parser.add_argument('--proxServ', metavar='SERV', type=str, help='Web address of proxy server, i.e. http://proxy.server.com:80')
parser.add_argument('--proxType', metavar='TYPE', type=str, default='http', help='Type of proxy server, i.e. http')

# Get the arguments from the parser
args = parser.parse_args()

# Define data to pass to server (could generate this from arguments as well)
values = {'name': 'data'}   # generate data to pass to server

# Define proxy settings if proxy server is input.
if args.proxServ:       # set up the proxy server support
    proxySupport = ProxyHandler({args.proxType: args.proxServ})
    opener = build_opener(proxySupport)
    install_opener(opener)

# Set up the data object
data = urlencode(values)
data = data.encode('utf-8')

# Send request to the server and receive response, with error handling!
try:
    req = Request(args.webAddr, data)

    # Read the response and print to a file
    response = urlopen(req)
    print response.read()

except URLError, e:
    if hasattr(e, 'reason'):    # URL error case
        # a tuple containing error code and text error message
        print 'Error: Failed to reach a server.'
        print 'Reason: ', e.reason
    elif hasattr(e, 'code'):    # HTTP error case
        # HTTP error code, see section 10 of RFC 2616 for details
        print 'Error: The server could not fulfill the request.'
        print 'Error code: ', e.code

urllib2应该使用您的系统设置进行任何代理处理,但我想有时这可能无法按您希望的方式工作。明确定义设置可能不会受到伤害。您也可以查看此文档以获取更多信息。

于 2013-06-14T18:57:13.373 回答