commit 4ec92f513fd21fcac77813ab86044e5c81c1a3a0 Author: maojian <550076202@qq.com> Date: Wed Jan 8 15:18:21 2025 +0800 代理ip管理服务 diff --git a/.classpath b/.classpath new file mode 100644 index 0000000..f7e4a1d --- /dev/null +++ b/.classpath @@ -0,0 +1,40 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..e3b721c --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +/target/ +/logs/ +/.idea/ \ No newline at end of file diff --git a/.project b/.project new file mode 100644 index 0000000..28f0888 --- /dev/null +++ b/.project @@ -0,0 +1,23 @@ + + + ipPool_Manger + + + + + + org.eclipse.jdt.core.javabuilder + + + + + org.eclipse.m2e.core.maven2Builder + + + + + + org.eclipse.jdt.core.javanature + org.eclipse.m2e.core.maven2Nature + + diff --git a/.settings/org.eclipse.core.resources.prefs b/.settings/org.eclipse.core.resources.prefs new file mode 100644 index 0000000..839d647 --- /dev/null +++ b/.settings/org.eclipse.core.resources.prefs @@ -0,0 +1,5 @@ +eclipse.preferences.version=1 +encoding//src/main/java=UTF-8 +encoding//src/main/resources=UTF-8 +encoding//src/test/java=UTF-8 +encoding/=UTF-8 diff --git a/.settings/org.eclipse.jdt.core.prefs b/.settings/org.eclipse.jdt.core.prefs new file mode 100644 index 0000000..71df522 --- /dev/null +++ b/.settings/org.eclipse.jdt.core.prefs @@ -0,0 +1,9 @@ +eclipse.preferences.version=1 +org.eclipse.jdt.core.compiler.codegen.methodParameters=generate +org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8 +org.eclipse.jdt.core.compiler.compliance=1.8 +org.eclipse.jdt.core.compiler.problem.enablePreviewFeatures=disabled +org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning +org.eclipse.jdt.core.compiler.problem.reportPreviewFeatures=ignore +org.eclipse.jdt.core.compiler.release=disabled +org.eclipse.jdt.core.compiler.source=1.8 diff --git a/.settings/org.eclipse.m2e.core.prefs b/.settings/org.eclipse.m2e.core.prefs new file mode 100644 index 0000000..f897a7f --- /dev/null +++ b/.settings/org.eclipse.m2e.core.prefs @@ -0,0 +1,4 @@ +activeProfiles= +eclipse.preferences.version=1 +resolveWorkspaceProjects=true +version=1 diff --git a/ipPool_Manger.iml b/ipPool_Manger.iml new file mode 100644 index 0000000..78b2cc5 --- /dev/null +++ b/ipPool_Manger.iml @@ -0,0 +1,2 @@ + + \ No newline at end of file diff --git a/pom.xml b/pom.xml new file mode 100644 index 0000000..16f361c --- /dev/null +++ b/pom.xml @@ -0,0 +1,155 @@ + + + 4.0.0 + + org.springframework.boot + spring-boot-starter-parent + 2.2.4.RELEASE + + org.example + ipPool_Manger + 1.0-SNAPSHOT + http://www.example.com + + UTF-8 + 1.8 + 1.8 + + + + junit + junit + 4.11 + test + + + org.springframework.boot + spring-boot-starter-web + + + com.squareup.okhttp3 + okhttp + 3.9.1 + + + org.projectlombok + lombok + 1.18.10 + compile + + + com.alibaba + fastjson + 2.0.17 + + + org.apache.httpcomponents + httpclient + 4.5.3 + + + mysql + mysql-connector-java + 8.0.30 + + + org.mybatis.spring.boot + mybatis-spring-boot-starter + 2.0.0 + + + + org.springframework.boot + spring-boot-starter-mail + + + + + + + + maven-clean-plugin + 3.1.0 + + + + maven-resources-plugin + 3.0.2 + + + maven-compiler-plugin + 3.8.0 + + + maven-surefire-plugin + 2.22.1 + + + maven-jar-plugin + 3.0.2 + + + maven-install-plugin + 2.5.2 + + + maven-deploy-plugin + 2.8.2 + + + + maven-site-plugin + 3.7.1 + + + maven-project-info-reports-plugin + 3.0.0 + + + + + org.springframework.boot + spring-boot-maven-plugin + + com.bfd.crawl.Application + ZIP + + + ${project.groupId} + ${project.artifactId} + + + + + + + repackage + + + + + + org.apache.maven.plugins + maven-dependency-plugin + + + copy + package + + copy-dependencies + + + jar + jar + runtime + ${project.build.directory}/libs + + + + + + + + \ No newline at end of file diff --git a/src/main/java/com/bfd/crawl/Application.java b/src/main/java/com/bfd/crawl/Application.java new file mode 100644 index 0000000..b10f6f8 --- /dev/null +++ b/src/main/java/com/bfd/crawl/Application.java @@ -0,0 +1,27 @@ +package com.bfd.crawl;//import com.bfd.crawl.process.ElasticsearchMaoJian; + +import com.bfd.crawl.process.ipManger; +import lombok.extern.slf4j.Slf4j; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.scheduling.annotation.EnableScheduling; + +/** + * @author:zhaoying + * @className:Application + * @version:1.0 + * @description:主入口 + * @Date:2023-12-15 14:30:41 + */ +@SpringBootApplication +@EnableScheduling +@Slf4j +public class Application { + + public static void main(String[] args) { + SpringApplication.run(com.bfd.crawl.Application.class, args); + ipManger ipManger = new ipManger(); + Thread ipMangerThread = new Thread(ipManger); + ipMangerThread.start(); + } +} diff --git a/src/main/java/com/bfd/crawl/controller/GetDataController.java b/src/main/java/com/bfd/crawl/controller/GetDataController.java new file mode 100644 index 0000000..96de494 --- /dev/null +++ b/src/main/java/com/bfd/crawl/controller/GetDataController.java @@ -0,0 +1,162 @@ +package com.bfd.crawl.controller; + +import com.bfd.crawl.model.Ips; +import com.bfd.crawl.util.SendEmail; +import lombok.extern.slf4j.Slf4j; +import okhttp3.*; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RestController; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.Random; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.locks.Lock; +import java.util.concurrent.locks.ReentrantLock; + +/** + * @PROJECT_NAME: + * @DESCRIPTION:获取一个时效内的ip + * @AUTHOR: ying.zhao + * @DATE: 2023/4/3 18:17 + */ +@Slf4j +@RestController + +public class GetDataController { + @Autowired + private SendEmail sendEmail; + private static final Lock lock = new ReentrantLock(); + + @GetMapping(value = "/getIp") + public String testFrom() { +// 静态锁,所有请求共享 + String ip = ""; + String html = ""; +// while (ip.equals("")) { + Long randomKey = getRandomEligibleKey(); + if (randomKey != null) { + log.info("时效内的key: {}", randomKey); + ip = Ips.ipMap.get(randomKey); + log.info("时效内的ip: {}", ip); + } else { + if (lock.tryLock()) { + try { + // 执行你的业务逻辑 + if (Ips.ipMap.size() < 1) { + html = getIpList(); + if(html.contains("msg")){ + log.info("ip请求异常"); + return html; + } + } else { + log.info("已获取一次iP"); + } + } finally { + // 确保在执行完后释放锁 + lock.unlock(); + } + } else { + log.info("锁上了 等会儿吧。。。。。。。。。"); + } + } + return ip; + } + + /** + * @Param: + * @DESCRIPTION: 请求获取ip + * @Author: ying.zhao + * @date: 2024/9/12 + */ + public String getIpList() { + OkHttpClient.Builder builder = new OkHttpClient.Builder(); + builder.readTimeout(200, TimeUnit.SECONDS); + builder.connectTimeout(200, TimeUnit.SECONDS); + OkHttpClient client = new OkHttpClient().newBuilder() + .build(); + MediaType mediaType = MediaType.parse("text/plain"); + RequestBody body = RequestBody.create(mediaType, ""); + Request request = new Request.Builder() + .url("http://api.tianqiip.com/getip?secret=x7it4ebj&num=10&type=txt&port=1&mr=1&sign=899ce225ae2cd14731d60fe48c338d0a") + .method("GET", null) + .build(); + Response response = null; + String html = ""; + try { + response = client.newCall(request).execute(); + html = response.body().string(); + } catch (IOException e) { + e.printStackTrace(); + } + if (!html.equals("")) { + log.info("请求得到页面:{}", html); + if (html.contains("msg")) { + try { + sendEmail.send("Alarm", "ip请求异常报警!!!!!!!!", html); + } catch (Exception e) { + e.printStackTrace(); + } + } else { + // 按换行符拆分字符串 + Ips.ipList = new ArrayList(Arrays.asList(html.split("\n"))); + for (String ip : Ips.ipList) { + log.info("ip:{}", ip); + Ips.ipMap.put(System.currentTimeMillis(), ip); + try { + Thread.sleep(1); // 延迟1毫秒 + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); // 处理中断异常 + } + } + } + + + } + return html; + + } + + /** + * @Param: + * @DESCRIPTION: 随机获取一个eligibleKeys中的key,确保每轮都被取到一次 + * @Author: ying.zhao + * @date: 2024/9/12 + */ + public static Long getRandomEligibleKey() { + if (Ips.eligibleKeys.isEmpty()) { + return null; // 如果列表为空,返回null + } + + // 如果所有符合条件的key都已经被取用,重新填充轮次 + if (Ips.keysInCurrentRound.size() == Ips.eligibleKeys.size()) { + Ips.keysInCurrentRound.clear(); // 清空当前轮次的标记 + } + + // 筛选出尚未被取用的key + List remainingKeys = new ArrayList<>(); + for (Long key : Ips.eligibleKeys) { + if (!Ips.keysInCurrentRound.contains(key)) { + remainingKeys.add(key); + } + } + + // 如果没有剩余的key可供选择 + if (remainingKeys.isEmpty()) { + return null; // 所有key都已被取用 + } + + // 随机选择一个尚未被取用的key + Random random = new Random(); + int randomIndex = random.nextInt(remainingKeys.size()); + Long randomKey = remainingKeys.get(randomIndex); + + // 标记已取用的key + Ips.keysInCurrentRound.add(randomKey); + + return randomKey; + } +} diff --git a/src/main/java/com/bfd/crawl/model/Ips.java b/src/main/java/com/bfd/crawl/model/Ips.java new file mode 100644 index 0000000..6a17105 --- /dev/null +++ b/src/main/java/com/bfd/crawl/model/Ips.java @@ -0,0 +1,22 @@ +package com.bfd.crawl.model; + +import lombok.Data; + +import java.util.*; +import java.util.logging.Handler; + +/** + * @PROJECT_NAME: + * @DESCRIPTION: + * @AUTHOR: ying.zhao + * @DATE: 2023/4/4 9:39 + */ +@Data +public class Ips { + public static List ipList = new ArrayList<>(); + public static Map ipMap = new HashMap(16); + // 临时列表存储符合条件的key + public static List eligibleKeys = new ArrayList<>(); + // 用于标记当前轮次中已取用的key + public static Set keysInCurrentRound = Collections.synchronizedSet(new HashSet<>()); +} diff --git a/src/main/java/com/bfd/crawl/process/ipManger.java b/src/main/java/com/bfd/crawl/process/ipManger.java new file mode 100644 index 0000000..ea773e3 --- /dev/null +++ b/src/main/java/com/bfd/crawl/process/ipManger.java @@ -0,0 +1,54 @@ +package com.bfd.crawl.process; + +import com.bfd.crawl.model.Ips; +import lombok.extern.slf4j.Slf4j; + +import java.util.List; +import java.util.stream.Collectors; + +/** + * @PROJECT_NAME: ipPool_Manger + * @DESCRIPTION: + * @AUTHOR: ying.zhao + * @DATE: 2024/9/12 14:22 + */ +@Slf4j +public class ipManger implements Runnable { + @Override + public void run() { +// long tenMinutesInMillis = 3 * 60 * 1000; // 10分钟对应的毫秒数 + long tenMinutesInMillis =(long) (2.7 * 60 * 1000); // 2.7分钟对应的毫秒数 + while (true) { + log.info("正在监控ipMap中一共有:{}个", Ips.ipMap.size()); + log.info("正在监控可用ip有:{}个", Ips.eligibleKeys.size()); + long currentTime = System.currentTimeMillis(); // 当前时间戳 + if (Ips.ipMap.size() > 0) { + // 添加符合条件的key + for (Long key : Ips.ipMap.keySet()) { + if (currentTime - key <= tenMinutesInMillis && !Ips.eligibleKeys.contains(key)) { + Ips.eligibleKeys.add(key); // 只添加还未加入的key + } + } + + // 找到超过10分钟的key,先做入库操作 +// List keysToBeRemoved = Ips.eligibleKeys.stream() +// .filter(key -> currentTime - key > tenMinutesInMillis) +// .collect(Collectors.toList()); + +// if (!keysToBeRemoved.isEmpty()) { +//// saveToDatabase(keysToBeRemoved); // 保存这些key到数据库 +// } + + // 移除超过10分钟的key + Ips.eligibleKeys.removeIf(key -> currentTime - key > tenMinutesInMillis); + Ips.ipMap.entrySet().removeIf(entry -> currentTime - entry.getKey() > tenMinutesInMillis); + } + // 休眠一段时间,避免频繁循环 + try { + Thread.sleep(2 * 1000); + } catch (InterruptedException e) { + e.printStackTrace(); + } + } + } +} diff --git a/src/main/java/com/bfd/crawl/util/SendEmail.java b/src/main/java/com/bfd/crawl/util/SendEmail.java new file mode 100644 index 0000000..a12f925 --- /dev/null +++ b/src/main/java/com/bfd/crawl/util/SendEmail.java @@ -0,0 +1,69 @@ +package com.bfd.crawl.util; + +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Component; + +import javax.mail.Message; +import javax.mail.MessagingException; +import javax.mail.Session; +import javax.mail.Transport; +import javax.mail.internet.InternetAddress; +import javax.mail.internet.MimeMessage; +import java.io.UnsupportedEncodingException; +import java.util.Date; +import java.util.Properties; + +/** + * @author:zhaoying + * @className:SendEmail + * @version:1.0 + * @description: + * @Date:2023-08-03 18:19:41 + */ + +@Slf4j +@Component +public class SendEmail { + @Value("${spring.email.host}") + private String host; + @Value("${spring.email.auth}") + private String auth; + @Value("${spring.email.user}") + private String user; + @Value("${spring.email.password}") + private String password; + @Value("${spring.email.receive}") + private String receive; + public void send(String sendUser, String title, String msage) throws MessagingException, UnsupportedEncodingException { + Properties props = new Properties(); + props.put("mail.smtp.host",host); + props.put("mail.smtp.auth", auth); + Session session = Session.getDefaultInstance(props, null); + Transport transport = session.getTransport(); + transport.connect(user, password); + + MimeMessage msg = new MimeMessage(session); + msg.setSentDate(new Date()); + //邮件发送人 + InternetAddress fromAddress = new InternetAddress(user, sendUser); + msg.setFrom(fromAddress); + //邮件接收人 + String[] receives = receive.split("#@#"); + for (int i=0;i + + + + + + + %d{HH:mm:ss.SSS} %-5level %logger{80} - %msg%n + + + + + true + + ${logging.level} + + + + ${logging.path}/data.log + + + ${logging.path}/data.log.%d{yyyy-MM-dd} + 7 + + + %d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %line %-5level %logger{50} - %msg%n + UTF-8 + + + + + + + +