请选择 进入手机版 | 继续访问电脑版

VRPIP 虚拟化平台

 找回密码
 注册VRPIP
搜索
热搜: 活动 交友 discuz
查看: 18300|回复: 2

小白 学pyton 爬虫五

[复制链接]

8

主题

11

帖子

55

积分

注册会员

Rank: 2

积分
55
发表于 2020-10-3 16:09:25 | 显示全部楼层 |阅读模式
本帖最后由 Tinken 于 2020-10-6 01:27 编辑

ip地址池 —— 爬虫必备
小白学习阶段,首选免费代理ip,需要做如下几部:
选择免费代理网站:西西、快代理...等
安装数据库:Redis(以后再考虑持久化的问题)
然后是爬免费的代理ip、检测、存储、开放接口、然后再反复检测IP有效性

第一步:安装Redis
下载地址:https://github.com/tporadowski/redis/releases
cmd 切换路径到redis目录,然后启动服务器:redis-server.exe redis.windows.conf
服务器cmd窗口保持打开状态,不要关闭
然后另开cmd窗口,启动客户端:redis-cli.exe -h 127.0.0.1 -p 6379
小插曲,客户端报错:Could not connect to Redis at 127.0.0.1:6379: 由于目标计算机积极拒绝,无法连接。
解决办法:
关闭上面的第一个cmd,redis服务器,通过redis目录中的:redis-server.exe 文件启动服务器
启动redis-server.exe 会有一个弹窗,网络是否允许,这个可能就是出现上面计算机拒绝,无法连接的原因。点击允许即可
再通过cmd:redis-cli.exe -h 127.0.0.1 -p 6379
或者直接在文件中双击:redis-cli.exe 均可成功启动客服端

完美解决!

忍不住尝试了一下,set和get,操作很简单


-------------------------------------------
redis 可视化了解工具,如果无法忍受cmd黑白dos窗口,可以自由选择
Redis Desktop Manager(又名 RDM)是一款适用于 Windows、Linux、MacOS 和 iPadOS 的 Redis 数据库快速管理应用程序
下载地址:https://redisdesktop.com/
省略一万字……

第二步 python 安装redis模块
命令行:pip install redis

项目引入:import redis

第三步 寻找IP代理网站,爬取IP,写入redis
选择的代理网站:https://www.kuaidaili.com/free/intr/1/
很不幸的是:503错误

应该ip封禁了,原来爬代理ip地址也需要代理ip,可怜我还在测试中经过分析,requests请求报503的原因是,同一时间内进行了2次请求,请求时间过快
改进后,去掉了第一次对url进行res.status_code == 200的判断,这样就不用请求两次了
然后在每一个循环后增加延时 time.sleep(5)避免再次出现503

最后的结果非常,成功将代理IP数据存入redis

第三步 对存入redis的ip进行验证,检测
设置一个定时任务,定时执行:将无法使用ip删除,保留可用IP
安装定时任务模块:pip install apscheduler
  1. # 以后台的方式运行
  2. sched = BlockingScheduler()
  3. sched.add_job(aps_detection_ip, 'interval', seconds=10, args=[redis_conn_1])
  4. sched.start()
复制代码

经过以上几个步骤,最终初步完成ip代理池功能
附上源码
  1. #!/usr/bin/env python
  2. # -*- coding:utf-8 -*-

  3. # @ClassName proxy
  4. # @Description TODO
  5. # @Author lanlo
  6. # @Date 2020-10-03 22:48
  7. # @Version 1.0

  8. import requests
  9. from bs4 import BeautifulSoup
  10. import redis
  11. import time
  12. import random
  13. import datetime

  14. # 存储在redis中
  15. # from apscheduler.jobstores.redis import RedisJobStore
  16. # 存储在mongo中
  17. # from apscheduler.jobstores.mongodb import MongoDBJobStore
  18. # 存储在数据库中
  19. # from apscheduler.jobstores.sqlalchemy import SQLAlchemyJobStore
  20. # 以后台的方式运行
  21. from apscheduler.schedulers.background import BackgroundScheduler
  22. # 以阻塞的方式运行, 前台运行
  23. from apscheduler.schedulers.background import BlockingScheduler


  24. # 快代理 国内高匿
  25. url_inha = "https://www.kuaidaili.com/free/inha/"
  26. # 快代理 国内普通
  27. url_intr = "https://www.kuaidaili.com/free/intr/"

  28. # 本地redis连接
  29. pool = redis.ConnectionPool(host='localhost', port=6379, decode_responses=True)
  30. # 存储爬取的代理ip
  31. redis_conn_0 = redis.Redis(connection_pool=pool, max_connections=10, db=0)
  32. # 存储经过检测后,可用的ip
  33. redis_conn_1 = redis.Redis(connection_pool=pool, max_connections=10, db=1)

  34. # 模拟浏览器的请求头
  35. headers = {
  36.         'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/67.0.3396.62 Safari/537.36'
  37.     }

  38. # 将ip和端口 写入redis数据库
  39. def add_ip(ip, port, redis_conn):
  40.     redis_conn.zadd("ip", {ip: port}, nx=False)
  41.     print("redis 添加 --> {}:{} ".format(ip, port))

  42. def spider_ip(url, redis_conn):
  43.     print("从{}中:爬取免费代理ip".format(url))

  44.     try:
  45.         if "kuaidaili" in url:
  46.             for i in range(1, 6):
  47.                 # 拼接页面后的链接
  48.                 url_ = url + str(i)
  49.                 print("循环{}:{}".format(i, url_))
  50.                 # requests请求,获取html页面
  51.                 res = requests.get(url_, headers=headers)
  52.                 print(res.status_code)
  53.                 # 将html页面转化为BeautifulSoup文件,并设置解析器
  54.                 soup = BeautifulSoup(res.text, "html.parser")
  55.                 # 经过查看元素,我们需要的ip数据都在一个表格中,我们查找所有行,对每一行的ip和端口进行单独处理
  56.                 for child in soup.find_all("tr"):
  57.                     # 会有页面其他行搜索进来,使用try避免后续错误
  58.                     try:
  59.                         # 分析元素得到ip
  60.                         ip = child.select("td[data-title='IP']")[0].string
  61.                         # 分析元素得到端口号
  62.                         port = child.select("td[data-title='PORT']")[0].string
  63.                         print("以获取:{}:{}".format(ip, port))
  64.                         # 调用redis写入函数,将数据写入redis
  65.                         add_ip(str(ip), str(port), redis_conn)
  66.                     except:
  67.                         print("*** 找到一个不含IP的tr ***")
  68.                 print("第{}代理IP获取页完成".format(i))
  69.                 # 延迟10秒,避免应请求太快被服务器限制IP
  70.                 time.sleep(5)
  71.         else:
  72.             print("该网址{}无法获取代理ip地址,请检查源码".format(url))
  73.     except:
  74.         print("网址{}请求失败".format(url))


  75. # 获取redis 拥有ip的数量
  76. def get_ip_num(redis_conn):
  77.     num = redis_conn.zcard("ip")
  78.     print("redis 拥有ip的数量:{}个".format(num))
  79.     return num

  80. # 获取ip的端口
  81. def get_port(ip,redis_conn):
  82.     port = redis_conn.zscore("ip", ip)
  83.     port = str(port).replace(".0", "")
  84.     return port

  85. # 随机 获取一个ip
  86. def get_random_ip(redis_conn):
  87.     # 获取ip数量
  88.     end_num = get_ip_num(redis_conn)
  89.     if end_num == 0:
  90.         # ip地址池没有ip了,应该去爬取更多的ip
  91.         spider_ip(url_intr, redis_conn_0)
  92.         return ""
  93.     # 从现有ip数量中,获得一个随机编号
  94.     num = random.randint(0, end_num)
  95.     # 获得随机的ip
  96.     random_ip = redis_conn.zrange("ip", num, num)
  97.     # 如果随机ip获得不成功
  98.     if not random_ip:
  99.         return ""
  100.     random_ip = str(random_ip[0]).replace("b", '').replace("'", "")
  101.     port = get_port(random_ip, redis_conn)
  102.     # 返回ip 和 port
  103.     print("获得随机IP:{},{}".format(random_ip, port))
  104.     return random_ip, port

  105. # 删除redis数据库里的ip
  106. def remove_ip(ip,redis_conn):
  107.     redis_conn.zrem("ip", ip)
  108.     print("已删除ip:{}".format(ip))

  109. # 检测ip是否可用
  110. def aps_detection_ip(redis_conn):
  111.     # 获得一个随机ip
  112.     res = get_random_ip(redis_conn)
  113.     if not res:
  114.         print("获得随机ip失败")
  115.         return ""
  116.     ip = res[0]
  117.     port = res[1]
  118.     try:
  119.         print("{}:{} 检测中...".format(ip, port))
  120.         requests.get("http://www.vrpip.com", proxies={'http': '{ip}:{port}'.format(ip=ip, port=port)}, timeout=10)
  121.         print("可用ip:{}:{}".format(ip, port))
  122.         add_ip(str(ip), str(port), redis_conn_1)
  123.     except Exception:
  124.         # ip错误失效就删除
  125.         remove_ip(ip, redis_conn)

  126. def text_print(int):
  127.     print("测试函数:{}".format(int))


  128. # 以后台的方式运行
  129. sched = BlockingScheduler()
  130. sched.add_job(aps_detection_ip, 'interval', seconds=15, args=[redis_conn_1])


  131. if __name__ == '__main__':
  132.     # 暂时单独跑高匿分类 和 普通分类,未做分类的循环
  133.     spider_ip(url_inha, redis_conn_0)
  134.     # spider_ip(url_intr, redis_conn_0)
  135.     print(datetime.datetime.now())
  136.     sched.start()






复制代码

虽然代码还有很多不完善,还有很多漏洞,但不重要
重要的是,我们有了一个清晰的概率,可以自己写出来基本的东西,还怕完善不完善吗?再到后面实战、实操,将ip代理池应用到正式项目中的时候再来改。




本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册VRPIP

x
回复

使用道具 举报

8

主题

11

帖子

55

积分

注册会员

Rank: 2

积分
55
 楼主| 发表于 2020-10-6 01:23:22 | 显示全部楼层
本帖最后由 Tinken 于 2020-10-6 02:05 编辑

  • 新增 89代理的ip获取功能
  • 新增 西拉代理的ip获取功能
  • 新增 ip地址获取接口
  • 优化 从redis获取地址为空的问题

  1. #!/usr/bin/env python
  2. # -*- coding:utf-8 -*-

  3. # @ClassName proxy
  4. # @Description TODO
  5. # @Author lanlo
  6. # @Date 2020-10-03 22:48
  7. # @Version 1.0

  8. import requests
  9. from bs4 import BeautifulSoup
  10. import redis
  11. import time
  12. import random
  13. import datetime

  14. # 存储在redis中
  15. # from apscheduler.jobstores.redis import RedisJobStore
  16. # 存储在mongo中
  17. # from apscheduler.jobstores.mongodb import MongoDBJobStore
  18. # 存储在数据库中
  19. # from apscheduler.jobstores.sqlalchemy import SQLAlchemyJobStore
  20. # 以后台的方式运行
  21. from apscheduler.schedulers.background import BackgroundScheduler
  22. # 以阻塞的方式运行, 前台运行
  23. from apscheduler.schedulers.background import BlockingScheduler


  24. # 快代理 国内高匿
  25. url_inha = "https://www.kuaidaili.com/free/inha/"
  26. # 快代理 国内普通
  27. url_intr = "https://www.kuaidaili.com/free/intr/"
  28. # 89代理
  29. url_89 = "https://www.89ip.cn/index_.html"
  30. # 西拉代理
  31. url_xl = "http://www.xiladaili.com/gaoni/"

  32. # 本地redis连接
  33. pool = redis.ConnectionPool(host='localhost', port=6379, decode_responses=True)
  34. # 存储爬取的代理ip
  35. redis_conn = redis.Redis(connection_pool=pool, max_connections=10, db=0)


  36. # 模拟浏览器的请求头
  37. headers = {
  38.         'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/67.0.3396.62 Safari/537.36'
  39.     }

  40. # 将ip和端口 写入redis数据库
  41. def add_ip(ip, port, redis_conn):
  42.     redis_conn.zadd("ip", {ip: port}, nx=False)
  43.     print("redis 添加 --> {}:{} ".format(ip, port))

  44. def spider_ip(url, redis_conn):
  45.     print("从{}中:爬取免费代理ip".format(url))

  46.     try:
  47.         # 从kuaidaili获得免费代理ip
  48.         if "kuaidaili" in url:
  49.             for i in range(1, 6):
  50.                 # 拼接页面后的链接
  51.                 url_ = url + str(i)
  52.                 print("循环{}:{}".format(i, url_))
  53.                 # requests请求,获取html页面
  54.                 res = requests.get(url_, headers=headers)
  55.                 print(res.status_code)
  56.                 # 将html页面转化为BeautifulSoup文件,并设置解析器
  57.                 soup = BeautifulSoup(res.text, "html.parser")
  58.                 # 经过查看元素,我们需要的ip数据都在一个表格中,我们查找所有行,对每一行的ip和端口进行单独处理
  59.                 for child in soup.find_all("tr"):
  60.                     # 会有页面其他行搜索进来,使用try避免后续错误
  61.                     try:
  62.                         # 分析元素得到ip
  63.                         ip = child.select("td[data-title='IP']")[0].string
  64.                         # 分析元素得到端口号
  65.                         port = child.select("td[data-title='PORT']")[0].string
  66.                         print("以获取:{}:{}".format(ip, port))
  67.                         # 调用redis写入函数,将数据写入redis
  68.                         add_ip(str(ip), str(port), redis_conn)
  69.                     except:
  70.                         print("*** 找到一个不含IP的tr ***")
  71.                 print("第{}页 代理IP获取完成".format(i))
  72.                 # 延迟10秒,避免应请求太快被服务器限制IP
  73.                 time.sleep(5)
  74.         # 从89ip获得免费代理ip
  75.         elif "89ip" in url:
  76.             for i in range(1, 6):
  77.                 # 拼接页面后的链接
  78.                 url_ = "https://www.89ip.cn/index_{}.html".format(i)
  79.                 print("循环{}:{}".format(i, url_))
  80.                 # requests请求,获取html页面
  81.                 res = requests.get(url_, headers=headers)
  82.                 print("页面响应:", res.status_code)
  83.                 # 将html页面转化为BeautifulSoup文件,并设置解析器
  84.                 soup = BeautifulSoup(res.text, "html.parser")
  85.                 # 经过查看元素,我们需要的ip数据都在一个表格中,我们查找所有行,对每一行的ip和端口进行单独处理
  86.                 for child in soup.find_all("tr"):
  87.                     # 会有页面其他行搜索进来,使用try避免后续错误
  88.                     try:
  89.                         # 分析元素得到ip
  90.                         ip = child.select("td")[0].string.replace("\n", '').replace("\t", "")
  91.                         # 分析元素得到端口号
  92.                         port = child.select("td")[1].string.replace("\n", '').replace("\t", "")
  93.                         print("已获取:{}:{}".format(ip, port))
  94.                         # 调用redis写入函数,将数据写入redis
  95.                         add_ip(str(ip), str(port), redis_conn)
  96.                     except:
  97.                         print("*** 找到一个不含IP的tr ***")
  98.                 print("第{}页 代理IP获取完成".format(i))
  99.                 # 延迟10秒,避免应请求太快被服务器限制IP
  100.                 time.sleep(5)

  101.         # 从西拉获取代理ip
  102.         elif "xiladaili" in url:
  103.             for i in range(1, 2):
  104.                 # 拼接页面后的链接
  105.                 url_ = url + str(i)
  106.                 print("循环{}:{}".format(i, url_))
  107.                 # requests请求,获取html页面
  108.                 res = requests.get(url_, headers=headers)
  109.                 print("页面响应:", res.status_code)
  110.                 # 将html页面转化为BeautifulSoup文件,并设置解析器
  111.                 soup = BeautifulSoup(res.text, "html.parser")
  112.                 # 经过查看元素,我们需要的ip数据都在一个表格中,我们查找所有行,对每一行的ip和端口进行单独处理
  113.                 for child in soup.find_all("tr"):
  114.                     # 会有页面其他行搜索进来,使用try避免后续错误
  115.                     try:
  116.                         # 分析元素得到ip
  117.                         ip = child.select("td")[0].string.split(":")[0]
  118.                         port = child.select("td")[0].string.split(":")[1]
  119.                         print("已获取:{}:{}".format(ip, port))
  120.                         # 调用redis写入函数,将数据写入redis
  121.                         add_ip(str(ip), str(port), redis_conn)
  122.                     except:
  123.                         print("*** 找到一个不含IP的tr ***")
  124.                 print("第{}页 代理IP获取完成".format(i))
  125.                 # 延迟10秒,避免应请求太快被服务器限制IP
  126.                 time.sleep(5)

  127.         else:
  128.             print("该网址{}无法获取代理ip地址,请检查源码".format(url))
  129.     except:
  130.         print("网址{}请求失败".format(url))


  131. # 获取redis 拥有ip的数量
  132. def get_ip_num(redis_conn):
  133.     num = redis_conn.zcard("ip")
  134.     print("redis 拥有ip的数量:{}个".format(num))
  135.     return num

  136. # 获取ip的端口
  137. def get_port(ip,redis_conn):
  138.     port = redis_conn.zscore("ip", ip)
  139.     port = str(port).replace(".0", "")
  140.     return port

  141. # 随机 获取一个ip
  142. def get_random_ip(redis_conn):
  143.     # 获取ip数量
  144.     end_num = get_ip_num(redis_conn)
  145.     if end_num == 0:
  146.         # ip地址池没有ip了,应该去爬取更多的ip
  147.         spider_ip(url_intr, redis_conn)
  148.         return ""
  149.     # 从现有ip数量中,获得一个随机编号
  150.     num = random.randint(0, end_num-1)
  151.     # 获得随机的ip
  152.     random_ip = redis_conn.zrange("ip", num, num)
  153.     # 如果随机ip获得不成功
  154.     if not random_ip:
  155.         return ""
  156.     random_ip = str(random_ip[0]).replace("b", '').replace("'", "")
  157.     port = get_port(random_ip, redis_conn)
  158.     # 返回ip 和 port
  159.     print("获得随机IP:{},{}".format(random_ip, port))
  160.     return random_ip, port

  161. # 获得代理ip的接口
  162. def get_proxy_ip():
  163.     # 获取ip数量
  164.     end_num = get_ip_num(redis_conn)
  165.     if end_num == 0:
  166.         return ""
  167.     # 从现有ip数量中,获得一个随机编号
  168.     num = random.randint(0, end_num-1)
  169.     print("获得redis的ip编号为:{}".format(num))
  170.     # 获得随机的ip
  171.     random_ip = redis_conn.zrange("ip", num, num)
  172.     # 如果随机ip获得不成功
  173.     if len(random_ip) == 0:
  174.         return ""
  175.     random_ip = str(random_ip[0]).replace("b", '').replace("'", "")
  176.     port = get_port(random_ip, redis_conn)
  177.     # 返回ip 和 port
  178.     print("获得随机IP:{},{}".format(random_ip, port))
  179.     return {'http': '{}:{}'.format(random_ip, port)}

  180. # 删除redis数据库里的ip
  181. def remove_ip(ip,redis_conn):
  182.     redis_conn.zrem("ip", ip)
  183.     print("已删除ip:{}".format(ip))

  184. # 检测ip是否可用
  185. def aps_detection_ip(redis_conn):
  186.     # 获得一个随机ip
  187.     res = get_random_ip(redis_conn)
  188.     if not res:
  189.         print("获得随机ip失败")
  190.         return ""
  191.     ip = res[0]
  192.     port = res[1]
  193.     try:
  194.         print("{}:{} 检测中...".format(ip, port))
  195.         requests.get("http://www.vrpip.com", proxies={'http': '{}:{}'.format(ip, port)}, timeout=5)
  196.         print("可用ip:{}:{}".format(ip, port))
  197.     except Exception:
  198.         # ip错误失效就删除
  199.         remove_ip(ip, redis_conn)

  200. def text_print(int):
  201.     print("测试函数:{}".format(int))


  202. # 以后台的方式运行、15秒检测一个
  203. sched = BlockingScheduler()
  204. sched.add_job(aps_detection_ip, 'interval', seconds=6, args=[redis_conn])


  205. if __name__ == '__main__':
  206.     # 暂时单独跑高匿分类 和 普通分类,未做分类的循环
  207.     # spider_ip(url_inha, redis_conn)
  208.     # spider_ip(url_intr, redis_conn)

  209.     # spider_ip(url_89, redis_conn)

  210.     spider_ip(url_xl, redis_conn)
  211.     print(datetime.datetime.now())
  212.     sched.start()

复制代码


回复

使用道具 举报

8

主题

11

帖子

55

积分

注册会员

Rank: 2

积分
55
 楼主| 发表于 2020-10-6 15:51:22 | 显示全部楼层
本帖最后由 Tinken 于 2020-10-6 22:17 编辑

  • 新增 多线程代理ip获取功能:加快免费代理ip获取速度
  • 新增 多线程ip检测功能:加快ip可用性的检测速度

  1. #!/usr/bin/env python
  2. # -*- coding:utf-8 -*-

  3. # @ClassName proxy_pool
  4. # @Description TODO 代理ip 地址池
  5. # @Author lanlo
  6. # @Date 2020-10-03 22:48
  7. # @Version 1.0

  8. import requests
  9. from bs4 import BeautifulSoup
  10. import redis
  11. import time
  12. import random
  13. import datetime
  14. # 多线程模块
  15. import threading
  16. # 定时任务模块
  17. from apscheduler.schedulers.background import BlockingScheduler
  18. # 线程池
  19. get_ip_threads = []
  20. ip_threads = []

  21. # 快代理 国内高匿
  22. url_inha = "https://www.kuaidaili.com/free/inha/"
  23. # 快代理 国内普通
  24. url_intr = "https://www.kuaidaili.com/free/intr/"
  25. # 89代理
  26. url_89 = "https://www.89ip.cn/index_.html"
  27. # 西拉代理
  28. url_xl = "http://www.xiladaili.com/gaoni/"

  29. # 本地redis连接
  30. pool = redis.ConnectionPool(host='localhost', port=6379, decode_responses=True)
  31. # 存储爬取的代理ip
  32. redis_conn = redis.Redis(connection_pool=pool, max_connections=10, db=0)


  33. # 模拟浏览器的请求头
  34. headers = {
  35.         'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/67.0.3396.62 Safari/537.36'
  36.     }

  37. # 将ip和端口 写入redis数据库
  38. def add_ip(ip, port, redis_conn):
  39.     redis_conn.zadd("ip", {ip: port}, nx=False)
  40.     print("redis 添加 --> {}:{} ".format(ip, port))

  41. def spider_ip(url, redis_conn):
  42.     print("从{}中:爬取免费代理ip".format(url))

  43.     try:
  44.         # 从kuaidaili获得免费代理ip
  45.         if "kuaidaili" in url:
  46.             print("从kuaidaili获取代理ip")
  47.             for i in range(1, 6):
  48.                 # 拼接页面后的链接
  49.                 url_ = url + str(i)
  50.                 print("循环{}:{}".format(i, url_))
  51.                 # requests请求,获取html页面
  52.                 res = requests.get(url_, headers=headers)
  53.                 print(res.status_code)
  54.                 # 将html页面转化为BeautifulSoup文件,并设置解析器
  55.                 soup = BeautifulSoup(res.text, "html.parser")
  56.                 # 经过查看元素,我们需要的ip数据都在一个表格中,我们查找所有行,对每一行的ip和端口进行单独处理
  57.                 for child in soup.find_all("tr"):
  58.                     # 会有页面其他行搜索进来,使用try避免后续错误
  59.                     try:
  60.                         # 分析元素得到ip
  61.                         ip = child.select("td[data-title='IP']")[0].string
  62.                         # 分析元素得到端口号
  63.                         port = child.select("td[data-title='PORT']")[0].string
  64.                         print("以获取:{}:{}".format(ip, port))
  65.                         # 调用redis写入函数,将数据写入redis
  66.                         add_ip(str(ip), str(port), redis_conn)
  67.                     except:
  68.                         print("*** 找到一个不含IP的tr ***")
  69.                 print("快代理免费代理 第{}页代理IP 获取完成".format(i))
  70.                 # 延迟10秒,避免应请求太快被服务器限制IP
  71.                 time.sleep(5)
  72.         # 从89ip获得免费代理ip
  73.         elif "89ip" in url:
  74.             print("从89ip获取代理ip")
  75.             for i in range(1, 6):
  76.                 # 拼接页面后的链接
  77.                 url_ = "https://www.89ip.cn/index_{}.html".format(i)
  78.                 print("循环{}:{}".format(i, url_))
  79.                 # requests请求,获取html页面
  80.                 res = requests.get(url_, headers=headers)
  81.                 print("页面响应:", res.status_code)
  82.                 # 将html页面转化为BeautifulSoup文件,并设置解析器
  83.                 soup = BeautifulSoup(res.text, "html.parser")
  84.                 # 经过查看元素,我们需要的ip数据都在一个表格中,我们查找所有行,对每一行的ip和端口进行单独处理
  85.                 for child in soup.find_all("tr"):
  86.                     # 会有页面其他行搜索进来,使用try避免后续错误
  87.                     try:
  88.                         # 分析元素得到ip
  89.                         ip = child.select("td")[0].string.replace("\n", '').replace("\t", "")
  90.                         # 分析元素得到端口号
  91.                         port = child.select("td")[1].string.replace("\n", '').replace("\t", "")
  92.                         print("已获取:{}:{}".format(ip, port))
  93.                         # 调用redis写入函数,将数据写入redis
  94.                         add_ip(str(ip), str(port), redis_conn)
  95.                     except:
  96.                         print("*** 找到一个不含IP的tr ***")
  97.                 print("89ip免费代理 第{}页代理IP 获取完成".format(i))
  98.                 # 延迟10秒,避免应请求太快被服务器限制IP
  99.                 time.sleep(5)

  100.         # 从西拉获取代理ip
  101.         elif "xiladaili" in url:
  102.             print("从西拉获取代理ip")
  103.             for i in range(1, 2):
  104.                 # 拼接页面后的链接
  105.                 url_ = url + str(i)
  106.                 print("循环{}:{}".format(i, url_))
  107.                 # requests请求,获取html页面
  108.                 res = requests.get(url_, headers=headers)
  109.                 print("页面响应:", res.status_code)
  110.                 # 将html页面转化为BeautifulSoup文件,并设置解析器
  111.                 soup = BeautifulSoup(res.text, "html.parser")
  112.                 # 经过查看元素,我们需要的ip数据都在一个表格中,我们查找所有行,对每一行的ip和端口进行单独处理
  113.                 for child in soup.find_all("tr"):
  114.                     # 会有页面其他行搜索进来,使用try避免后续错误
  115.                     try:
  116.                         # 分析元素得到ip
  117.                         ip = child.select("td")[0].string.split(":")[0]
  118.                         port = child.select("td")[0].string.split(":")[1]
  119.                         print("已获取:{}:{}".format(ip, port))
  120.                         # 调用redis写入函数,将数据写入redis
  121.                         add_ip(str(ip), str(port), redis_conn)
  122.                     except:
  123.                         print("*** 找到一个不含IP的tr ***")
  124.                 print("西拉免费代理 第{}页代理IP 获取完成".format(i))
  125.                 # 延迟10秒,避免应请求太快被服务器限制IP
  126.                 time.sleep(5)

  127.         else:
  128.             print("该网址{}无法获取代理ip地址,请检查源码".format(url))
  129.     except:
  130.         print("网址{}请求失败".format(url))


  131. # 获取redis 拥有ip的数量
  132. def get_ip_num(redis_conn):
  133.     num = redis_conn.zcard("ip")
  134.     print("redis 拥有ip的数量:{}个".format(num))
  135.     return num

  136. # 获取ip的端口
  137. def get_port(ip,redis_conn):
  138.     port = redis_conn.zscore("ip", ip)
  139.     port = str(port).replace(".0", "")
  140.     return port

  141. # 随机 获取一个ip
  142. def get_random_ip(redis_conn):
  143.     # 获取ip数量
  144.     end_num = get_ip_num(redis_conn)
  145.     if end_num == 0:
  146.         # ip地址池没有ip了,应该去爬取更多的ip
  147.         spider_ip(url_intr, redis_conn)
  148.         return ""
  149.     # 从现有ip数量中,获得一个随机编号
  150.     num = random.randint(0, end_num-1)
  151.     # 获得随机的ip
  152.     random_ip = redis_conn.zrange("ip", num, num)
  153.     # 如果随机ip获得不成功
  154.     if not random_ip:
  155.         return ""
  156.     random_ip = str(random_ip[0]).replace("b", '').replace("'", "")
  157.     port = get_port(random_ip, redis_conn)
  158.     # 返回ip 和 port
  159.     print("获得随机IP:{},{}".format(random_ip, port))
  160.     return random_ip, port

  161. # 获得代理ip的接口
  162. def get_proxy_ip():
  163.     # 获取ip数量
  164.     end_num = get_ip_num(redis_conn)
  165.     if end_num == 0:
  166.         return ""
  167.     # 从现有ip数量中,获得一个随机编号
  168.     num = random.randint(0, end_num-1)
  169.     print("获得redis的ip编号为:{}".format(num))
  170.     # 获得随机的ip
  171.     random_ip = redis_conn.zrange("ip", num, num)
  172.     # 如果随机ip获得不成功
  173.     if len(random_ip) == 0:
  174.         return ""
  175.     random_ip = str(random_ip[0]).replace("b", '').replace("'", "")
  176.     port = get_port(random_ip, redis_conn)
  177.     # 返回ip 和 port
  178.     print("获得随机IP:{},{}".format(random_ip, port))
  179.     return {'http': '{}:{}'.format(random_ip, port)}

  180. # 删除redis数据库里的ip
  181. def remove_ip(ip,redis_conn):
  182.     redis_conn.zrem("ip", ip)
  183.     print("已删除ip:{}".format(ip))

  184. # 检测ip是否可用
  185. def aps_detection_ip(redis_conn):
  186.     # 获得一个随机ip
  187.     res = get_random_ip(redis_conn)
  188.     if not res:
  189.         print("获得随机ip失败")
  190.         return ""
  191.     ip = res[0]
  192.     port = res[1]
  193.     try:
  194.         print("{}:{} 检测中...".format(ip, port))
  195.         requests.get("http://www.vrpip.com", proxies={'http': '{}:{}'.format(ip, port)}, timeout=5)
  196.         print("可用ip:{}:{}".format(ip, port))
  197.     except Exception:
  198.         # ip错误失效就删除
  199.         remove_ip(ip, redis_conn)



  200. # 以后台的方式运行、15秒检测一个
  201. sched = BlockingScheduler()
  202. sched.add_job(aps_detection_ip, 'interval', seconds=6, args=[redis_conn])


  203. # 多线程 获取ip
  204. def ip_is_enable(ip, port):
  205.     try:
  206.         print("{}:{} 检测中...".format(ip, port))
  207.         requests.get("http://www.vrpip.com", proxies={'http': '{}:{}'.format(ip, port)}, timeout=5)
  208.         print("可用ip:{}:{}".format(ip, port))
  209.     except Exception:
  210.         # ip错误失效就删除
  211.         remove_ip(ip, redis_conn)

  212. # 多线程 开启检测ip
  213. def all_ip_thread():
  214.     end_num = get_ip_num(redis_conn)
  215.     for i in range(0, end_num):
  216.         if i == end_num:
  217.             i = i - 1
  218.         ip = redis_conn.zrange("ip", i, i)
  219.         ip = str(ip[0]).replace("b", '').replace("'", "")
  220.         port = get_port(ip, redis_conn)
  221.         ip_thread = threading.Thread(target=ip_is_enable, args=(ip, port), name="all_ip_thread_".format(i))
  222.         ip_thread.start()
  223.         ip_threads.append(ip_thread)

  224. def get_all_ip_thread():
  225.     get_ip_thread_inha = threading.Thread(target=spider_ip, args=(url_inha, redis_conn))
  226.     get_ip_thread_intr = threading.Thread(target=spider_ip, args=(url_intr, redis_conn))
  227.     get_ip_thread_89 = threading.Thread(target=spider_ip, args=(url_89, redis_conn))
  228.     get_ip_thread_xl = threading.Thread(target=spider_ip, args=(url_xl, redis_conn))
  229.     get_ip_thread_inha.start()
  230.     get_ip_thread_intr.start()
  231.     get_ip_thread_89.start()
  232.     get_ip_thread_xl.start()
  233.     get_ip_threads.append(get_ip_thread_inha)
  234.     get_ip_threads.append(get_ip_thread_intr)
  235.     get_ip_threads.append(get_ip_thread_89)
  236.     get_ip_threads.append(get_ip_thread_xl)


  237. if __name__ == '__main__':
  238.     print(datetime.datetime.now())

  239.     # 快代理 高匿分类
  240.     # spider_ip(url_inha, redis_conn)
  241.     # 快代理 普通分类
  242.     # spider_ip(url_intr, redis_conn)
  243.     # 89代理
  244.     # spider_ip(url_89, redis_conn)
  245.     # 西拉代理
  246.     # spider_ip(url_xl, redis_conn)


  247.     # 多线程 获取免费代理ip
  248.     get_all_ip_thread()
  249.     for t in get_ip_threads:
  250.         t.join()
  251.     # 多线程检测ip是否可用
  252.     all_ip_thread()
  253.     for t in ip_threads:
  254.         t.join()
  255.     # 定时任务 检测ip
  256.     # sched.start()


复制代码


回复

使用道具 举报

您需要登录后才可以回帖 登录 | 注册VRPIP

本版积分规则

快速回复 返回顶部 返回列表