代码里的“随机应变”

说在前头

  有段时间没更新了,期间发生了很多事,这里就不一一赘述,有一个要说一下, 之前我放在github上的springbootquick代码结构我重新整理了一下,因为我觉得branch的方式去完善每个小功能不太直观,索性找个时间全都整理在了一起,方便大家观看
目录结构
项目地址为https://github.com/vector4wang/spring-boot-quick 里面有些是我工作中用到的,有些是我在平时玩玩积累的,如果对你有帮助,点个星,fork一下,我会感激不尽,如果有问题,请及时沟通我,我会在第一时间改正,我的原则是“交流、互助、提升”~
  今天就我之前写的一个小虫子说一下代码里的随机应变,以下观点均数个人看法,如有雷同纯属巧合,如果你对我的看法有意见欢迎拍砖,如果觉得我的理解有点意思,那有劳,点个赞分享一下,我定感激不尽,好的,言归正传!

起因

世充日踧月迫,力尽计穷,悬首面缚,翘足可待。建德远来助虐,粮运阻绝,此是天丧之时。请固武牢,屯军氾水,随机应变,则易为克殄 —旧唐书·郭孝恪传(指随着情况的变化灵活机动地应付)

之前写的领英爬虫目标数据比较随意,即抓取一段时间之后,后面得到的数据都是老外的,这不是我想要的,于是上级给了一个办法, “通过百度搜索去抓”,即在百度搜索某一个姓氏或常用名,通过百度返回的列表再依次去领英里去抓,如图
列表.png
后来验证这是可行的,其实这里也是一个“随机应变”的情景,这条路走不通立马换条路,而且是可行的。
  问题到这看似没有问题,但是用过百度的都知道,当你点击某一结果的时候,百度这边需要做一个重定向处理,即重新指定url,例如你点击百度链接http://www.baidu.com/link?url=6pwgxIUI8VfssEgJKHAHjdHBD_55cW5E72arpGIV9lZoAxLsaqV3do9p9O01kuzb3s3FlJKImEFkFsvWkDWL8a,经过重定向后就变成了http://cn.linkedin.com/in/johnsonwangnz,这一点htmlunit做的很好,自动获取重定向的页面,但是在防爬虫这一块,领英做的很好,这一点列一下我知道的限制

  • ip限制 一个ip对领英产生大量非人类行为的请求,他会对这个ip登录的账号做一个人机验证,比12306还好玩,大家可以试试,手动偷笑~
  • 请求限制 当产生大量请求是,它会对请求直接拒绝~
  • 账号限制 同一个ip或者ip所在的网段注册多个领英账号的时候,账号会出现各种繁琐的验证,没验证的直接禁掉!!!

目前我知道的就这几条。
好,因为是代码,请求的速度非常快,一秒通过百度指向领英跳转达到几十个,几分钟后代码就报错了,如下
999.png
  这啥啊,999感冒灵冲剂啊!!!查了下code码,原来是“访问被拒绝”,我得出的结果是领英那边检查出了大量的个人页面的请求,速度很快非人类所能达到,于是就禁止数据返回。
  我心想这下完蛋了,这条路难道也走不通!!!急的我抓耳挠腮~,然后我起身转了一圈,喝了点水,突然灵光一闪,“我想要的就是个人中心的链接啊,我可以先拿到这些链接存起来作为种子url,然后再将以前的爬虫改造一下,通过这些url去抓啊!”
于是,我将这些错误catch住,通过简单的正则来判断是否为拥有个人中心的链接地址,如下:

final Pattern r = Pattern.compile("in/[\\u4e00-\\u9fa5-0-9-a-z-A-z%]*");



Matcher m = r.matcher(e.getMessage());
String seed = "";
if (m.find()) {
    seed = m.group();
    seed = seed.substring(3, seed.length());
}
System.out.println(seed);

结果为
seed.png
没错,白色就是种子url,最后在直接访问http://www.linkedin.com/in/jingshi-wang-056b6245/ 就可以获取这个人一些职业信息啦~~~
职业档案.png

最终的是酱紫
结构.png
为什么领英爬虫还要回写种子DB,因为要将抓过的url打个标记抓过了,整体就这么简单。

现在种子抓了100多万了,领英这块抓了8万多,现在暂停了,因为帐号这块的问题还没有解决~~~,啊哈哈哈哈

后记

代码我放在了github上,点我,其实这里并不是说代码的这一块的,而是如何对代码反馈出来的结果做出灵活的应对以致快速总结出解决方案,这不就是对代码的“随机应变”吗~~

欢迎大家浏览我的个人博客http://vector4wang.tk

### MBTI 测试算法实现 MBTI(Myers-Briggs Type Indicator)是一种基于心理学理论的性格分类方法,其核心在于通过一系列问题评估个体在四个维度上的偏好。以下是关于如何实现 MBTI 测试的核心逻辑和代码示例。 #### 1. 数据结构设计 为了存储 MBTI 的测试数据,可以定义一个二维数组来表示每个问题及其对应的选项得分。例如: ```javascript const questions = [ { question: "你喜欢独自思考还是喜欢团队合作?", options: [ { text: "独自思考", score: { E: 0, I: 1 } }, { text: "团队合作", score: { E: 1, I: 0 } } ] }, { question: "你更倾向于计划好一切还是随机应变?", options: [ { text: "计划好一切", score: { S: 0, N: 1 } }, { text: "随机应变", score: { S: 1, N: 0 } } ] }, // 更多问题... ]; ``` 此部分的设计允许灵活扩展问题数量以及调整各个选项的权重[^1]。 #### 2. 用户输入处理 当用户提交答案,程序需要解析这些答案并更新用户的性格评分。可以通过遍历用户的选择列表计算总分: ```typescript function calculateMbtiScore(answers: number[]): Record<string, number> { const scores: Record<string, number> = { E: 0, I: 0, S: 0, N: 0, T: 0, F: 0, J: 0, P: 0 }; answers.forEach((answerIndex, questionIndex) => { const optionScores = questions[questionIndex].options[answerIndex].score; Object.keys(optionScores).forEach(key => { scores[key] += optionScores[key]; }); }); return scores; } ``` 这段函数接收用户选择的答案索引作为参数,并返回每种性格特征的累计分数[^1]。 #### 3. 结果判定 根据最终得分判断用户的 MBTI 类型。通常情况下,比较同一维度下两个对立面的得分即可得出结论: ```typescript function determineMbtiType(scores: Record<string, number>): string { let result = ""; result += scores.E >= scores.I ? "E" : "I"; result += scores.S >= scores.N ? "S" : "N"; result += scores.T >= scores.F ? "T" : "F"; result += scores.J >= scores.P ? "J" : "P"; return result; } ``` 该函数会依次对比 `E` 和 `I`, `S` 和 `N`, `T` 和 `F`, `J` 和 `P` 的得分,从而构建完整的 MBTI 字符串。 #### 4. 前端展示 如果是在前端项目中实现,则可参考如下 React/Taro 组件模板渲染问卷页面: ```tsx import React, { useState } from 'react'; import { View, Text, Button } from '@tarojs/components'; interface Question { question: string; options: Array<{ text: string; score: any }>; } const App = () => { const [currentQuestion, setCurrentQuestion] = useState<number>(0); const [answers, setAnswers] = useState<Array<number>>([]); const handleAnswerSelect = (selectedOptionIndex: number) => { setAnswers([...answers, selectedOptionIndex]); if (currentQuestion < questions.length - 1) { setCurrentQuestion(currentQuestion + 1); } }; return ( <View> {questions[currentQuestion] && ( <> <Text>{questions[currentQuestion].question}</Text> {questions[currentQuestion].options.map((option, index) => ( <Button key={index} onClick={() => handleAnswerSelect(index)}> {option.text} </Button> ))} </> )} </View> ); }; export default App; ``` 以上是一个简单的交互界面组件,用于逐步引导用户完成所有问题的回答[^2]。 --- ###
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值