通过抓取代理到数据库,实现时时拥有100+可用的代理。
前面说到过,因为调试豆瓣的时候被豆瓣把自己的IP给封了,一直想搞个免费的代理IP,现在有时间了发个帖一下。这里基于上一篇文章的scrapy 学习,如果有意向了解的,可以移步:http://blog.csdn.net/weixin_39378885/article/details/78431566 。欢迎围观。
(一)保存到数据库
-
1,实现方法:
-
数据库:
MongoDB
MongoDB简单使用,请参考: Python与MongoDB相关操作
爬虫手段: scrapy
全部实现方法,请参考: scrapy爬取西刺代理IP到Excel
主要通过在 scrapy中的 pipeline 中取处理 spider 获得的 IP,并保存到数据库。过程实现比较简单。需要注意的是: 数据库连接打开之后,切记要记得关闭!否则会导致端口占用严重
源代码:
from pymongo import MongoClient
import urllib.request
# 用来处理数据到数据库
class DbPipeline(object):
# 连接DB数据库
def connect_db(self):
try:
db = MongoClient("127.0.0.1",port=27017,)
# databasenames = db.database_names()
print("<connect_db> ---> 已连接数据库!")
return db # 返回对象
except Exception as e:
print("数据库连接失败 ! %s" %e)
# 函数描述:检查IP是否可用
# 传入参数:http or HTTPS, IP, port
def filter_ip(self, item):
#item = {1:{"kind":"http", "ip_address":"1275690842", "port":8888}}
kind = item["kind"]
ip = item["ip_address"]
port = item["port"] # port 为 int 型
# print(_id,kind,ip,port)
proxy = urllib.request.ProxyHandler({kind:"%s:%d"%(ip,port)})
opener = urllib.request.build_opener(proxy)
urllib.request.install_opener(opener)
req = urllib.request.Request(url="http://www.baidu.com",headers={"User-Agent":generate_user_agent()})
try:
# 通过加载百度页面来判断IP是否可用
response = urllib.request.urlopen(req,timeout=1)
if response.code >= 200 and response.code <= 300:
print("此IP可用! ",response.code)
item["_id"] = ip
#print(item)
self.save_to_db(value=item) # 这里必须使用dict(),不然会出错。因获得的item[row]是IPitem类型
else:
print("此IP不可用! 状态码:%s" %response.code)
pass
except Exception as e:
print("此IP不可用! %s" %e)
# 保存到数据库
def save_to_db(self,value):
db = self.connect_db() #
try:
db_test_ip = db.test.IP # 选择test数据库下的IP集合
db_test_ip.save(value)
db.close()
print("完成操作,关闭数据库!")
except Exception as e:
db.close()
print("出现异常,关闭数据库!")
print(e)
def process_item(self, item, spider):
for each in item.values(): # 刚好获取需要的字典部分
#print(each)
self.filter_ip(dict(each))
#for each in range(10):
#threading.Thread(target=self.filter_ip(item),name="Mythread").start()
#print("进程",each)
代码解读:
定义了一个类Dbpipeline来处理数据。
其中包含四个子函数:
①,connect_db: 用来连接数据库并返回一个数据库对象
②,filter_ip: 用来筛选出可用的数据库并保存到数据库
③,save_to_db: 用来供filter_ip调用。
④,process_item: 每一个继承自PIPELINE类必须调用的函数
详细解释,都在代码中。
样图:
——————————————-分割线——————————————-
(二)从数据库中取可用的IP
源代码:
# coding = "utf-8"
import urllib.request
from user_agent.base import generate_user_agent
from pymongo import MongoClient
import random
class Get_ip():
def __init__(self, number=1):
self.number = number
def connect_db(self):
try:
db = MongoClient(host="127.0.0.1", port=27017,)
print("<connect_db> ---> 数据库连接成功!")
return db
except Exception as e:
print("<connect_db> ---> 数据库连接失败,请检查地址是否正确! ",e)
# 函数描述:从数据库随机获取一个IP,并检查其可用性
# 函数返回:kind IP port (分别是 http或HTTPS, IP号, 端口号)
def get_ip_from_db(self):
db = self.connect_db() # 获取实例化数据库对象
try:
db_test_ip = db.test.IP # 选择IP集合
ip_list = []
for each in db_test_ip.find(): # Curser 对象必须通过遍历
ip_list.append(each)
ip_item = []
for each in range(self.number):
ip_item.append(random.choice(ip_list)) # 随机获取一个IP字典
db.close()
print("关闭数据库!")
return db,ip_item
except Exception as e:
db.close()
print("<get_ip_from_db> ---> 获取IP异常", "关闭数据库!",e)
# 可以用返回该IP信息。包括 协议类型,IP地址,端口。
# 不可用将其从数据库中删除
def main(self):
test_url = "http://www.baidu.com/"
db,ip_item = self.get_ip_from_db()
for each in ip_item:
kind = each["kind"]
ip = each["ip_address"]
port = each["port"]
try:
Proxy = urllib.request.ProxyHandler({kind:"%s:%s"%(ip,port)})
opener = urllib.request.build_opener(Proxy)
urllib.request.install_opener(opener)
head = {"User-Agent":generate_user_agent()}
req = urllib.request.Request(url=test_url,headers=head,)
response = urllib.request.urlopen(req, timeout=1)
if response.code >= 200 and response.code <= 300: # 可用的状态码范围
db.close() # 即使关闭数据库,防止端口占用
yield kind,ip,port # 返回地址信息的生成器
else:
db_test_ip = db.test.IP # 选择IP集合
db_test_ip.deleteOne(ip_item) # 从数据库删除不可用IP
print("%s \n该IP不可用,已从数据库中删除!")
self.main() # 再次取值
except Exception as e:
db.close()
print("<main> ---> 出错啦! ",e)
# 返回一个包含IP信息的生成器
if __name__ == "__main__":
number = int(input("********************** 欢迎使用免费IP获取脚本应用程序 ************************\n\t\t\t\t\t 请输入要获取IP的数量:"))
test = Get_ip(number)
generator = test.main()
for each in generator:
kind,ip,port = each
print("IP地址为:%s//:%s:%s"%(kind,ip,port))
调试结果:
代码解读:
①,这里单独使用一个文件即可,毕竟只是从数据库中读取IP。
②,都是一些简单的数据库操作。具体请看代码中详解。
③,其他问题,可以参考以下。上面给的两个链接
-
To The End:
-
博主水平有限,代码也很简陋。如有什么问题跟意见,欢迎评论指出。感激不尽。