一:为什么需要代理ip
在我们爬取数据的过程中,通常是本机ip以get或是post请求访问某一个网站,如果你访问过多,或者访问过快,那么服务器就会检测到,并且分析出该请求大概率是一个爬虫。
所以即便你在请求头(headers)内隐藏了自己“爬虫”的身份,还是会被分析到,那么你的ip就可能会被封,也就无法在继续执行爬取数据的操作了。
所以在爬数据的过程中,我们不仅要隐藏自己的身份,还需要尽可能的隐藏自己的真实ip,以代理ip的身份去爬数据。
二:代理ip池的构建
代理ip池有免费的和付费的,免费的百度搜索:免费代理ip便可找到。当然,免费的自然是不稳定的,而且可用率也很低,或许你爬了一百个免费的ip,能用的只有那么几个。
付费的代理ip可用率很高,这里推荐知乎上一位大佬对各个代理ip软件的测评:爬虫代理哪家强?十大付费代理详细对比评测出炉!
付费代理不用说,自然是拿来就能用的,这里我爬取免费网站的ip
三:免费ip的爬取
目标网站:西拉免费代理IP
1:ip和port的获取
先分析下网站的信息,查看源代码或者F12进入开发者,发现网站没有对页面信息隐藏,我们能看到的就能爬取下来。
对于ip和port的格式都是xxx.xxx.xxx.xxx:xxxx
那么我们只需要正则匹配(\d+.\d+.\d+.\d+:\d+)
即可
代码如下:
def getIPS(baseurl):
headers = {
'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:79.0) Gecko/20100101 Firefox/79.0'
}
for page in range(-67, -9):
html = requests.get(baseurl.format(abs(page)), headers=headers, timeout=10)
ips = re.findall(r'(\d+.\d+.\d+.\d+:\d+)', html.text, re.S) #找到ip
ip, port = [],[]
for t in ips:
ip.append(re.split(r'[:]', t)[0]) #分割ip和port
port.append(re.split(r'[:]', t)[1])
#print(ip,port)
def main():
baseurl = 'http://www.xiladaili.com/shareip_detail/164{}/' #爬取ip的网站
getIPS(baseurl)
代码解释:抓取到的信息是这样的:223.247.95.29:3000,所以正则这样写:
ips = re.findall(r'(\d+.\d+.\d+.\d+:\d+)', html.text, re.S)
。 re.S是为了除去换行的情况,因为有可能数据有回车分开。
在根据:
分隔符re.split(r'[:]', t)
,依次把数据放入ip
和port
两个列表内。要注意re.split
分割开后为一个元祖的格式
2:对爬取到的ip进行是否可用判断
def checkIp(ip, port):
proxies={
'http':'http://{}:{}'.format(ip,port),
'https':'https://{}:{}'.format(ip,port)
}
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.100 Safari/537.36'
}
try:
requests.adapters.DEFAULT_RETRIES = 2 #设置重复访问次数
print(proxies)
res = requests.get(url="http://icanhazip.com/", headers=headers, proxies=proxies, timeout = 2) #抛弃延迟高的
if (str(res.text).replace('\n','') == ip):
return True
else:
print("2代理IP无效!")
return False
except:
print("1代理IP无效!")
return False
访问ip的查询 该网站可用来查看访问者的ip,以此来判断该ip是否可用,传入的参数为ip地址和其端口。
要注意python3以上的proxies的格式是
http:'http://{180.160.48.62}:{22914}
https:'https://{180.160.48.62}:{22914}
3:对可用的数据放入数据库中
client = pymongo.MongoClient('localhost') #链接主机
db = client['代理ip池']
collection = db['ip地址']
def saveInDB(ip, port):
for index in range(0, len(ip)):
if checkIp(ip[index], port[index]) == True: # 如果有效
data = {
'ip': ip[index],
'pots': port[index]
}
print("{}:{}插入成功!".format(ip[index], port[index]))
collection.insert_one(data) # 插入进数据库
else:
return False
这里我采用了
mongodb
数据库,如果该ip可用则直接插入进数据库即可。
四:效果图
五:结语
单线程爬取太慢,所以我后面采用了多线程来爬去。但效果还是感人,爬了三十分钟也就爬出了十几个有用的ip,不想花钱的同学,可以找找多个提供免费ip的网站,放入一个列表循环进行爬取,再采用多个线程的形式。
后续对代理ip池的维护,只需提取数据库中的ip判断即可,剔除不可用的ip。
果然还是付费的好用啊。