爬虫
和代理
这两个关键词总能不期而遇。在获取代理的途经中有一个免费的高质量代理方案是使用Tor代理。接下来整理下Python中如何使用Tor代理及对Tor代理进行简单的统计
(一)安装Tor及配置
Fedora:
dnf install tor
编辑 /etc/tor/torrc
,去掉下面的注释
ControlPort 9051
HashedControlPassword 16:872860B76453A77D60CA2BB8C1A7042072093276A3D701AD684053EC4C
如果想设置新的密码
tor --hash-password mypassword
启动tor
systemctl start tor
查看9050
和9051
端口是否开启
[root@the5 py]# netstat -tunlp | grep 9050
tcp 0 0 127.0.0.1:9050 0.0.0.0:* LISTEN 6919/tor
[root@the5 py]# netstat -tunlp | grep 9051
tcp 0 0 127.0.0.1:9051 0.0.0.0:* LISTEN 6919/tor
这样,python就可以通过9051端口对tor进行操作了
(二)Python使用Tor代理
pip install stem
python需要安装stem包来操作tor,它是tor project开发的。去看了官方的文档,相当的齐全,如下是官方的hello world
import getpass
import sys
import stem
import stem.connection
from stem.control import Controller
if __name__ == '__main__':
try:
controller = Controller.from_port()
except stem.SocketError as exc:
print("Unable to connect to tor on port 9051: %s" % exc)
sys.exit(1)
try:
controller.authenticate()
except stem.connection.MissingPassword:
pw = getpass.getpass("Controller password: ")
try:
controller.authenticate(password = pw)
except stem.connection.PasswordAuthFailed:
print("Unable to authenticate, password is incorrect")
sys.exit(1)
except stem.connection.AuthenticationFailure as exc:
print("Unable to authenticate: %s" % exc)
sys.exit(1)
print("Tor is running version %s" % controller.get_version())
controller.close()
如果需要切换IP,那么可以试试如下代码,应该是在sf找的,原链接找不到了
import time
import socket
import socks
import requests
from stem import Signal
from stem.control import Controller
controller = Controller.from_port(port=9051)
def connectTor():
socks.setdefaultproxy(socks.PROXY_TYPE_SOCKS5 , "127.0.0.1", 9050, True)
socket.socket = socks.socksocket
def renew_tor():
controller.authenticate()
controller.signal(Signal.NEWNYM)
def showmyip():
r = requests.get('http://icanhazip.com/')
ip_address = r.text.strip())
print(ip_address)
for i in range(10):
renew_tor()
connectTor()
showmyip()
time.sleep(10)
- 上边程序的
http://icanhazip.com/
会回显你的IP,如果链接不可用了,可以试试http://ifconfig.me/ip
,或者自己使用任何web框架,返回ip就行,很好搭建。 - 测试中发现10s基本上是最小的时间间隔,如果改得再小不会切换IP了,可能官方文档有说明,不过没有详细的去考证
(三)统计数据方案
运行上面的程序能看到终端每隔10s就输出一个IP,还是很开心的。但是有一个疑问就是这些IP的是不是究竟有多少是重复的呢
于是我把代理的IP存入了redis,本地的redis貌似不行...我引入了redis模块会报错,不知道是不是socks的原因,于是曲线救国,用另一个VPS搭建了个flask,来接收ip地址,存入redis的队列中。
下面代码进行取值统计
#!/bin/env python
# -*- coding:utf-8 -*-
import redis
redis = redis.Redis(host="localhost", port=6379, password="dong")
res = redis.lrange("torip", 0, -1)
print res
print "数量:", len(res)
print "数量:", len(set(res))
ip_list = set(res)
ip_dict = {}
for ip in ip_list:
ip_dict[ip] = res.count(ip)
data = sorted(ip_dict.items(), lambda x, y: cmp(x[1], y[1]), reverse=True)
for item in data:
print item[1], "\t", item[0]
在收集了100个IP不重复IP的时候运行结果如下:
如图可见,请求了416次才得到了100个IP
这时,我比较好奇,如果再多运行些时间,获得的IP和总的请求量会有什么关系呢
换句话说,Tor的IP会是无穷多的供爬虫使用吗?
带着疑问,我写了点辅助的脚本,比如定时任务,每隔一分钟请求一下统计接口,获取形如83,336
的数据,前边的是ip的数量,后边的是请求的次数,然后追加写入到csv文件中。
它看起来是这样的:
1,1
5,6
11,12
13,17
16,22
19,27
24,33
28,38
29,44
30,49
32,54
36,60
40,65
41,71
42,76
45,81
47,87
49,92
52,98
53,103
因为是一分钟记录一次,没10s一个请求,所以我也希望它有一个时间的列,用脚本转化一下
awk '$0=""NR","$0' old.csv > data.csv
1,1,1
2,5,6
3,11,12
4,13,17
5,16,22
6,19,27
7,24,33
8,28,38
9,29,44
10,30,49
11,32,54
12,36,60
13,40,65
14,41,71
15,42,76
16,45,81
17,47,87
18,49,92
19,52,98
20,53,103
本次我用的测试数据:data.csv
更加完整的数据:data-full.csv
刚刚接触R语言,所以照葫芦画瓢,来做个数据可视化~吼吼
照着《R语言实战》的3.3例子修改代码如下:
data = read.table("data.csv", header=FALSE, sep=",")
dose <- data[,1]
drugA <- data[,2]
drugB <- data[,3]
pdf("finish3.pdf")
opar <- par(no.readonly = TRUE)
par(lwd = 2, cex = 1.5, font.lab = 2)
plot(dose, drugA, type = "l", lty = 1, col = "red",
ylim = c(0, 500), main = "Requests Counts & Ip Number", xlab = "Ip Number",
ylab = "Requests Counts")
lines(dose, drugB, type = "l", lty = 1,
col = "blue")
abline(h = c(30), lwd = 1.5, lty = 2, col = "grey")
library(Hmisc)
minor.tick(nx = 3, ny = 3, tick.ratio = 0.5)
legend("topright", inset = 0.05, title = "Desc",
c("IP", "REQ"), lty = c(1, 1), col = c("red", "blue"))
par(opar)
下面是调整参数后输出的几个pdf截图:
再来个放大的~
一图胜千言,还是有图看着开心~
总结如下:
Tor的IP并不是取之不尽的,至少一台机器六个小时内获得的IP数量一百二三十,而且无论看图片趋势还是上边更完整的数据,IP的数量的增长已然趋近为0,这可能是tor机制的限制
幸运的是,虽然IP数量有限制,但是至少IP是随机轮询的,如果爬虫在不那么高频的访问的情况下,似乎也不会被封。
待验证问题:不知道如果两个VPS一起运行,对ip列表的影响会有多大,每个机器tor网络都会为它分配一个一百多IP的池子吗?那么两个池子的IP重复率又有多少呢?