Notes and thoughts from Tony

Scrapy 和 Tor

Comments

不太好分类,所以就分到了“编程思想”中,你懂的。

Scrapy 集成 Tor,又是一坑。

安装

Tor(The Onion Router,洋葱路由器)是实现匿名通信的自由软件。更通俗的内容查看关于 TOR 的常见问题解答,链接打不开的话,说明你还没准备好打开新世界的大门。

Tor 的安装非常简单:

$ brew install tor
# $ pip install nyx

配置

目前,大陆基本无法直接使用 Tor,需要为 Tor 设置“前置代理”,本文使用的是 shadowsocks。

/usr/local/etc/tor 下新建配置文件 torrc。找到 torrc.sample 文件,可以查看配置选项和说明。

几个重要的参数:

参数 说明
ControlPort 控制程序访问的端口,如果使用 nyx 之类的工具,则需要配置此端口
Socks5Proxy 前置 Socks 代理端口
HTTPProxy 前置 HTTP 代理端口
HTTPSProxy 前置 HTTPS 代理端口
SocksProt 外部程序访问 Tor 的端口
MaxCircuitDirtiness 自动切换 ip 的时间间隔

最终配置:

ControlPort 9051
CookieAuthentication 1

# 我本机的 shadowsocks 客户端提供的 HTTP 代理地址为 127.0.0.1:1087
HTTPProxy 127.0.0.1:1087
HTTPSProxy 127.0.0.1:1087

# 外部程序(比如说浏览器)中访问 Tor 的端口
SocksPort 9000
MaxCircuitDirtiness 1 minutes

现在在 Chrome 中用 SwitchySharp 新建名为 Tor 使用情景,手动配置代理为:SOCKS 代理,地址为 127.0.0.1,端口为 9000(也就是配置的 SocksPort)。

SwitchySharp 选择刚建好的情景,测试上网,OK。

实际上我在这里花费了一个下午的时间,最后通过查看文档才找对了 HTTPProxy 配置,(ಥ _ ಥ)…

现在 scrapy 依然无法直接使用 Tor,它们中间还需要一层将 Tor 提供的 Socks 代理转为 HTTP 代理的工具。

Privoxy

Privoxy 是一个 HTTP 协议过滤代理,常结合 Tor 使用。

$ brew install privoxy

/usr/local/etc/privoxy 下找到 config 配置文件(没有就新建),新增配置:

listen-address 0.0.0.0:8118
forward-socks5 / 127.0.0.1:9000 .

第一行设置 privoxy 监听任意 ip 地址的 8118 端口。第二行设置本地 Socks5 代理客户端端口,注意不要忘了最后有一个空格和点号。

然后执行

privoxy

这样就是用 /usr/local/etc/privoxy/config 配置文件启动。

执行以下命令查看运行状态:

netstat -na | grep 8118

如果有以下输出说明成功:

......
tcp4       0      0  127.0.0.1.8118         *.*                    LISTEN

同样可使用 SwitchySharp 新建代理配置,验证是否成功。更多可查看 如何用 Privoxy?

Scrapy 集成

class ProxyMiddleware(object):
    # 单个代理

    def __init__(self, settings):
        self.proxy = settings.get('PROXY')

    @classmethod
    def from_crawler(cls, crawler):
        return cls(crawler.settings)

    def process_request(self, request, spider):
        request.meta['proxy'] = self.proxy

settings.py 中:

PROXY = 'http://127.0.0.1:8118'
DOWNLOADER_MIDDLEWARES = {
    'scrapy.downloadermiddlewares.retry.RetryMiddleware': 90,
    'scrapydemo.middlewares.ProxyMiddleware': 100,
    'scrapy.downloadermiddlewares.httpproxy.HttpProxyMiddleware': 110,
}