Python:如何使用请求库通过几个不同的代理服务器访问URL?

时间:2013-08-22 00:04:10

标签: python httprequest python-requests

正如标题中所说,我试图通过几个不同的代理顺序访问一个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地址访问该网站。换句话说,它不是试图通过我给它的代理进行访问,它只是循环并一遍又一遍地使用我自己的代理。我做错了什么?

3 个答案:

答案 0 :(得分:3)

根据this主题,您需要将proxies字典指定为{"protocol" : "ip:port"},因此您的代理文件应该看起来像

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

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

答案 1 :(得分:2)

这里有两个明显的问题:

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

首先,因为for line in urls:中有for line in proxies:line将成为当前的网址,而不是当前的代理。此外,即使您没有重用line,它也将是JSON字符串表示,而不是您从JSON解码的字典。

然后,如果您将其修改为使用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

答案 2 :(得分:1)

直接从我的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'])

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