【问题标题】:Python: How to use requests library to access a url through several different proxy servers?Python:如何使用 requests 库通过几个不同的代理服务器访问 url?
【发布时间】:2013-08-22 00:04:10
【问题描述】:

正如标题中所说,我试图通过几个不同的代理顺序访问一个 url(使用 for 循环)。现在这是我的代码:

import requests
import json
with open('proxies.txt') as proxies:
    for line in proxies:
        proxy=json.loads(line)
        with open('urls.txt') as urls:
        for line in urls:
            url=line.rstrip()
            data=requests.get(url, proxies={'http':line})
            data1=data.text
            print data1

还有我的 urls.txt 文件:

http://api.exip.org/?call=ip

还有我的 proxies.txt 文件:

{"https": "84.22.41.1:3128"}
{"http":"194.126.181.47:81"}
{"http":"218.108.170.170:82"}

我在 [www.hidemyass.com][1] 获得的

由于某种原因,输出是

68.6.34.253
68.6.34.253
68.6.34.253

好像它是通过我自己的路由器 IP 地址访问该网站一样。换句话说,它不是试图通过我给它的代理来访问,它只是循环并一遍又一遍地使用我自己的。我做错了什么?

【问题讨论】:

  • 正如我在您之前的一个问题中所建议的那样,如果您打印出您正在传递的一些中间值,或者在调试器中运行,您会发现更容易理解正在发生的事情或交互式可视化器或其他查看它们的方式。如果你打印出每个{'http': line},那么问题就很明显了。
  • 为什么要打印出每个 {'http':line}?那不只是多次打印网址吗?我不应该把网页上的html打印出来,这样我就可以验证它是代理服务器的ip地址吗?
  • 如果你不知道它会打印出什么,你就会知道发生了什么。如果你认为你知道它会打印出什么,你就会知道你是否正确。这是最基本的调试。显然,您的脚本中的某些内容没有达到您的预期。第一步是找出哪里出了问题,而这样做的唯一方法是查看这些值,看看它们是否错了。

标签: python httprequest python-requests


【解决方案1】:

根据this 线程,您需要将proxies 字典指定为{"protocol" : "ip:port"},因此您的代理文件应如下所示

{"https": "84.22.41.1.3128"}
{"http": "194.126.181.47:81"}
{"http": "218.108.170.170:82"}

编辑: 您正在为 URL 和代理重用 line。在内部循环中重用line 很好,但您应该使用proxies=proxy——您已经解析了JSON,不需要构建另一个字典。此外,正如 abanert 所说,您应该进行检查以确保您请求的协议与代理的协议相匹配。将代理指定为字典的原因是允许查找匹配的协议。

【讨论】:

  • 这个答案很有用,看来你是对的。但是,在我修复它之后,我遇到了同样的问题。有什么想法吗?
  • 以上应该可以解决它。如果不是,请告诉我(尽管要小心协议匹配点)。
  • 我对此进行了测试,它确实有效。只需将 proxies={'http':line} 替换为 proxies=proxy
【解决方案2】:

这里有两个明显的问题:

data=requests.get(url, proxies={'http':line})

首先,因为您在for line in proxies: 中有一个for line in urls:,所以line 将是此处的当前URL,而不是当前代理。此外,即使您没有重用 line,它也将是 JSON 字符串表示,而不是您从 JSON 解码的 dict。

然后,如果你修复它以使用proxy,而不是{'https': '83.22.41.1:3128'},你将传递{'http': {'https': '83.22.41.1:3128'}}。这显然不是一个有效的值。

要解决这两个问题,只需这样做:

data=requests.get(url, proxies=proxy)

同时,如果您有一个 HTTPS URL,但当前代理是 HTTP 代理,会发生什么情况?你不会使用代理。因此,您可能想添加一些内容以跳过它们,如下所示:

if urlparse.urlparse(url).scheme not in proxy:
    continue

【讨论】:

  • 我更新代码以匹配您的答案。我不确定我是否在正确的位置添加了 if 语句?
  • @BigBoy1337:我怎么知道你是否在我看不到的代码中的正确位置添加了 if 语句?
  • 对不起,我想更新问题的代码,但意识到这样的问题没有意义。因为它现在给出了正确的输出。我只是对你给出的 if 语句应该插入哪里感到困惑?
  • @BigBoy1337:在url=line.rstrip() 之后似乎是个好地方。它必须在我们要检查的 URL 之后,并且必须在我们要跳过的 get 之前,所以没有太多选择。
  • @BigBoy1337:如果你想使用urlparse模块,你需要import urlparse
【解决方案3】:

直接从我的another answer复制过来的。

嗯,其实你可以,我用几行代码就完成了,效果很好。

import requests


class Client:

    def __init__(self):
        self._session = requests.Session()
        self.proxies = None

    def set_proxy_pool(self, proxies, auth=None, https=True):
        """Randomly choose a proxy for every GET/POST request        
        :param proxies: list of proxies, like ["ip1:port1", "ip2:port2"]
        :param auth: if proxy needs auth
        :param https: default is True, pass False if you don't need https proxy
        """
        from random import choice

        if https:
            self.proxies = [{'http': p, 'https': p} for p in proxies]
        else:
            self.proxies = [{'http': p} for p in proxies]

        def get_with_random_proxy(url, **kwargs):
            proxy = choice(self.proxies)
            kwargs['proxies'] = proxy
            if auth:
                kwargs['auth'] = auth
            return self._session.original_get(url, **kwargs)

        def post_with_random_proxy(url, *args, **kwargs):
            proxy = choice(self.proxies)
            kwargs['proxies'] = proxy
            if auth:
                kwargs['auth'] = auth
            return self._session.original_post(url, *args, **kwargs)

        self._session.original_get = self._session.get
        self._session.get = get_with_random_proxy
        self._session.original_post = self._session.post
        self._session.post = post_with_random_proxy

    def remove_proxy_pool(self):
        self.proxies = None
        self._session.get = self._session.original_get
        self._session.post = self._session.original_post
        del self._session.original_get
        del self._session.original_post

    # You can define whatever operations using self._session

我是这样使用的:

client = Client()
client.set_proxy_pool(['112.25.41.136', '180.97.29.57'])

这很简单,但实际上对我有用。

【讨论】:

    猜你喜欢
    • 2016-01-06
    • 1970-01-01
    • 2017-12-23
    • 2010-10-19
    • 1970-01-01
    • 1970-01-01
    • 2015-06-23
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多