致力于成为国内最好的Python开发者学习交流平台,这里有关于Python的国内外最新消息,每日推送有趣有料的技术干货和社区动态。 官方网站:www.python-cn.com |
專 欄
苍冥 ,Python中文社区专栏作者,澳洲华裔,目前在墨尔本某国际咨询公司任职Splunk Developer,擅长网络安全及攻防,热爱Python及爬虫,同时在学习Machine Learning。
Github:
github.com/eastrd
01 写在前面
常听到很多人抱怨自己的IP因爬虫次数太多而被网站屏蔽,不得不频繁使用各种代理IP,却又因为网上的公开代理大部分都是不能使用,而又要花钱花精力去申请VIP代理,几番波折又遭屏蔽。特此写一篇如何利用Python搭建代理池的文章,以降低时间及精力成本,实现自动化获取活跃代理IP的功能。
02 运作原理
一、 网站代理获取
1. 爬免费代理网站的IP列表测试是否可用及是否是高匿
2. 若都是,则放进数据库,否则丢弃。
3. 重复第2步
二、 保证失效的代理能被尽快从代理池中挑出
1. 从爬虫数据库获取IP
2. 测试IP的可用性和匿名性
3. 如果可用且匿名,则保留,否则丢弃。
4. 重复第1步
说明① :可建立一个爬虫程序守护程序(Daemon),有此方面需要的小伙伴可自行谷歌,在此不多做介绍。
说明② :可建立一个对外代理信息接口,无论你用NodeJS或者Flask/Django或者PHP来写都没关系,在此也不多做介绍。
03 实现
建议库: requests, BeautifulSoup, re, sqlite3。
其中,用requests库获取代理网站页面,用BeautifulSoup和re两库来进行代理信息获取,用sqlite3来对这些信息进行存取。
如果必要(如代理网站有反爬虫策略时),可用PhantomJS替代requests,或用相应库进行数据清理(如base64解码)。
下面简单展示一下各部分的代码:
首先是选择多个能爬取代理且不容易被屏蔽IP的网站,此处以proxy-list.org为例:
BASE_URL
=
"https://proxy-list.org/english/index.php?p="
#IP地址及端口的正则
Re_Pattern_IP
=
re
.
compile
(
"(.*):"
)
Re_Pattern_PORT
=
re
.
compile
(
":(.*)"
)
#网站有11页,所以循环11次获取所有代理IP及端口
for
startingURL_Param
in
range
(
1
,
11
):
HTML_ProxyPage
=
requests
.
get
(
BASE_URL
+
str
(
startingURL_Param
)).
content
soup
=
bs
(
HTML_ProxyPage
,
"html.parser"
)
for
Raw_ProxyInfo
in
soup
.
find_all
(
"ul"
,{
"class"
:
None
}):
#此网站有用Base64简单对代理进行了加密,所以这里对其解码
ip_port
=
base64
.
b64decode
(
Raw_ProxyInfo
.
find
(
"li"
,{
"class"
:
"proxy"
}).
text
.
replace
(
"Proxy('"
,
""
).
replace
(
"')"
,
""
))
#接下来利用正则从网页数据中提取我们需要的信息
IP
=
re
.
findall
(
Re_Pattern_IP
,
ip_port
)[
0
]
PORT
=
re
.
findall
(
Re_Pattern_PORT
,
ip_port
)[
0
]
TYPE
=
Raw_ProxyInfo
.
find
(
"li"
,{
"class"
:
"https"
}).
text
接下来是一段简易代理池框架类的代码,提供代理数据库的添加、删除、可连接性检测、匿名性检测:
class
ProxyPool
:
#初始化爬虫池数据库
def
__init__
(
self
,
ProxyPoolDB
):
self
.
ProxyPoolDB
=
ProxyPoolDB
self
.
conn
=
sqlite3
.
connect
(
self
.
ProxyPoolDB
,
isolation_level
=
None
)
self
.
cursor
=
self
.
conn
.
cursor
()
self
.
TB_ProxyPool
=
"TB_ProxyPool"
self
.
cursor
.
execute
(
"CREATE TABLE IF NOT EXISTS "
+
self
.
TB_ProxyPool
+
"(ip TEXT UNIQUE, port INTEGER, protocol TEXT)"
)
#添加代理IP进代理池的接口
def
addProxy
(
self
,
IP
,
PORT
,
PROTOCOL
):
self
.
cursor
.
execute
(
"INSERT OR IGNORE INTO "
+
self
.
TB_ProxyPool
+
"(ip, port, protocol) VALUES (?,?,?)"
,
[
IP
,
PORT
,
PROTOCOL
])
#检查代理的匿名性及可连接性
def
testConnection
(
self
,
IP
,
PORT
,
PROTOCOL
):
proxies
=
{
PROTOCOL
:
IP
+
":"
+
PORT
}
try
:
OrigionalIP
=
requests
.
get
(
"http://icanhazip.com"
,
timeout
=
REQ_TIMEOUT
).
content
MaskedIP
=
requests
.
get
(
"http://icanhazip.com"
,
timeout
=
REQ_TIMEOUT
,
proxies
=
proxies
).
content
if
OrigionalIP
!=
MaskedIP
:
return
True
else
:
return
False
except
:
return
False
#删除代理IP对应的数据库记录
def
delRecord
(
self
,
IP
):
self
.
cursor
.
execute
(
"DELETE FROM "
+
self
.
TB_ProxyPool
+
" WHERE ip=?"
,(
IP
,))
下面是对代理池进行去“失效IP”的代码:
#循环代理池,逐行测试IP地址端口协议是否可用
def
cleanNonWorking
(
self
):
for
info
in
self
.
cursor
.
execute
(
"SELECT * FROM "
+
self
.
TB_ProxyPool
).
fetchall
():
IP
=
info
[
0
]
PORT
=
str
(
info
[
1
])
PROTOCOL
=
info
[
2
].
lower
()
isAnonymous
=
self
.
testConnection
(
IP
,
PORT
,
PROTOCOL
)
if
isAnonymous
==
False
:
#这条代理的可用性失效了,从数据库里删除
self
.
delRecord
(
IP
)
#通过检测icanhazip.com回显来检测可用性及匿名性
def
testConnection
(
self
,
IP
,
PORT
,
PROTOCOL
):
proxies
=
{
PROTOCOL
:
IP
+
":"
+
PORT
}
try
:
OrigionalIP
=
requests
.
get
(
"http://icanhazip.com"
,
timeout
=
REQ_TIMEOUT
).
content
MaskedIP
=
requests
.
get
(
"http://icanhazip.com"
,
timeout
=
REQ_TIMEOUT
,
proxies
=
proxies
).
content
if
OrigionalIP
!=
MaskedIP
:
return
True
else
:
return
False
except
:
return
False
04
反思
这个项目是我年初时用Python练手写的,以现在的程度再来回顾,逻辑不够严谨,各类功能太过耦合,不少段落需要重写,因为代码是在校园网内所跑,所以还需要考虑到网络连接的稳定性,这就造成部分代码之间的混乱关系。
通过icanhazip.com来检测代理匿名性的方法或许有效,但却忽略了X-Forwarded-For的HTTP头,所以有很大风险,必须改进。
验证代理池内代理的有效性,需要多线程,目前的方案效率太低。
05
完整代码
放在此文章中的是代理池的核心代码,旨在提供各位读者能够自己实现的思路及参考。完整代码可在作者的Github主页中找到,Ubuntu 16.04及Kali下用Python 2.7测试可运行。
ARTICLES
近期热门文章
⊙
生成器
:
关于生成器的那些事儿
⊙
爬虫代理
:
如何构建爬虫代理服务
⊙
地理编码
:
怎样用Python实现地理编码
⊙
nginx日志
:
使用Python分析nginx日志
⊙
淘宝女郎
:
一个批量抓取淘女郎写真图片的爬虫
⊙
IP代理池
:
突破反爬虫的利器——开源IP代理池
⊙
布隆去重
:
基于Redis的Bloomfilter去重(附代码)
⊙
QQ空间爬虫
:
QQ空间爬虫最新分享,一天 400 万条数据
在公众号底部回复上述关键词可直接打开相应文章
我 们 终 将 改 变 潮 水 的 方 向
§
§
Python中文社区
www.python-cn.com
致力于成为
国内最好的Python社区
QQ群:152745094
专栏作者申请邮箱
— Life is short,we use Python —
|
理想聚焦 · 看起来,只有这招才能救美国了 8 年前 |
|
肌肉男训练营 · 可能是最简单有效的增肌计划 8 年前 |
|
爱手工 · 惊艳立体昆虫珠绣,高级定制自己做~ 8 年前 |
|
债海观潮 · 【国信宏观固收】债市日评:一季度不可不提配置力量 8 年前 |
|
趣拾家 · 马伊琍:有一种胜利来自煎熬 8 年前 |