热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

社工入门之如何分析一个人的作息规律

电影中的社工高手可以很轻易操控目标对象,使其愿意去做某项事(科幻片拍的像玄幻片…),虽然现实没有那么玄幻,但是真实的社工,或者你想要了解某个人,必然会有一个环节就是通过社交网络之类的对目标对象进行建模

电影中的社工高手可以很轻易操控目标对象,使其愿意去做某项事(科幻片拍的像玄幻片…),虽然现实没有那么玄幻,但是真实的社工,或者你想要了解某个人,必然会有一个环节就是通过社交网络之类的对目标对象进行建模,即用一些特征来描述目标对象(也可想象为对人贴标签)。举一个例子我们平时如果加了一个新的QQ好友,可能会去QQ空间、腾讯微博等看下他以往的历史记录来确认他是个怎样的人,因为人的思维通常比较简单,所以当接触到一个陌生的人时急切需要在他身上寻找符合某个标签的某个特征,一旦这家伙显现出来某个特征,好,赶紧把对应的标签给他贴上,这样贴几个标签可以确定以后与其相处的策略,虽然可能比较偏激,但大多数人基本上都是这么干的。虽然你们可能没有说过几句话,但经过这么一番调查之后你已经对这个人有了一些比较深入的了解,至少是自以为有深入了解 :)

所以社工这玩意儿基本人人都会,说白了就是信息收集,如果是经常在网络上活动的人,留下的痕迹比较多,甚至有可能画出一条时间轴,能够大致描述他的人生轨迹,这个可以对自己感兴趣的人试一试,个人推荐使用时间轴作为主线的方式来分析。

对于信息收集,其中一个比较小的点就是如何分析一个人的作息规律,从而推测出特定的时间点他很有可能在做什么,比如统计某个人习惯在什么时间点刷知乎、泡论坛之类的,这个我有一个思路就是对于某类信息比较大,比如论坛上的留言,知乎上的点赞之类,可以通过爬虫技术先采集再分析。我想对自己有个更深刻的了解,所以这里就用一个例子,写一个小小的爬虫来分析我发博客的时间分布情况。

 

首先确定要抓取的字段,其实只需要发布时间字段就可以了,但是想到为了以后可能还会有其它的分析,就把其它方便抓取的字段比如阅读量、评论数之类一并抓取了。

PostMetaInfo:

package cc11001100.crawler;

import java.util.Date;

/**
 * @author CC11001100
 */
public class PostMetaInfo {

	private String id;
	private String title;
	private Date postTime;
	// like uv but not
	private Integer visited;
	private Integer reviewNum;

	public String getId() {
		return id;
	}

	public void setId(String id) {
		this.id = id;
	}

	public String getTitle() {
		return title;
	}

	public void setTitle(String title) {
		this.title = title;
	}

	public Date getPostTime() {
		return postTime;
	}

	public void setPostTime(Date postTime) {
		this.postTime = postTime;
	}

	public Integer getVisited() {
		return visited;
	}

	public void setVisited(Integer visited) {
		this.visited = visited;
	}

	public Integer getReviewNum() {
		return reviewNum;
	}

	public void setReviewNum(Integer reviewNum) {
		this.reviewNum = reviewNum;
	}
}

CnBlogPostMetaInfoCrawler:

package cc11001100.crawler;

import com.alibaba.fastjson.JSON;
import org.apache.commons.io.FileUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;

import java.io.File;
import java.io.IOException;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Collections;
import java.util.Date;
import java.util.List;
import java.util.concurrent.TimeUnit;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

import static java.util.stream.Collectors.toList;

/**
 * 博客园活跃时间统计
 *
 * @author CC11001100
 */
public class CnBlogPostMetaInfoCrawler {

	private static final Logger log = LogManager.getLogger(CnBlogPostMetaInfoCrawler.class);

	private static void grabMetaInfoByUserName(String username) {
		final String savePath = getSavePathByUserName(username);
		final String urlPattern = String.format("http://www.cnblogs.com/%s/default.html?page=", username);
		for (int pageNum = 1; true; pageNum++) {
			String currentPageListUrl = urlPattern + pageNum;
			List parseResultList = parsePostList(currentPageListUrl);
			if (parseResultList.isEmpty()) {
				break;
			}
			save(parseResultList, savePath);
			try {
				TimeUnit.SECONDS.sleep(1);
			} catch (InterruptedException e) {
				log.info("InterruptedException");
			}
		}
	}

	private static String getSavePathByUserName(String username) {
		return "CnBlog_" + username + "_post_meta_info.data";
	}

	private static void save(List postMetaInfoList, String savePath) {
		List lineList = postMetaInfoList.stream().map(JSON::toJSONString).collect(toList());
		try {
			FileUtils.writeLines(new File(savePath), "UTF-8", lineList, "\n", true);
		} catch (IOException e) {
			log.info("save list to file={} failed", savePath);
		}
	}

	private static List parsePostList(String listUrl) {
		String htmlRespOnse= getHtml(listUrl);
		if (StringUtils.isBlank(htmlResponse)) {
			log.error("url={}, cannot get html content", listUrl);
			return Collections.emptyList();
		}

		Document document = Jsoup.parse(htmlResponse);
		return document.select(".postDesc").stream().map(elt -> {
			PostMetaInfo postMetaInfo = new PostMetaInfo();
			String text = elt.ownText();

			String id = extractByPattern(elt.select(">a").attr("href"), "postid=(\\d+)");
			postMetaInfo.setId(id);

			String title = document.select(String.format("a.postTitle2[href~=/p/%s.html]", postMetaInfo.getId())).text();
			postMetaInfo.setTitle(title);

			Date postTime = extractByPatternAndToDate(text, "posted @ (\\d{4}-\\d{2}-\\d{2} \\d{2}:\\d{2})", "yyyy-MM-dd HH:mm");
			postMetaInfo.setPostTime(postTime);

			postMetaInfo.setVisited(extractByPatternAndToInt(text, "阅读\\((\\d+)\\)"));
			postMetaInfo.setVisited(extractByPatternAndToInt(text, "评论\\((\\d+)\\)"));
			return postMetaInfo;
		}).collect(toList());
	}

	private static String extractByPattern(String content, String pattern) {
		Matcher matcher = Pattern.compile(pattern).matcher(content);
		if (matcher.find()) {
			return matcher.group(1);
		}
		return "";
	}

	private static int extractByPatternAndToInt(String content, String extractPattern) {
		String rawString = extractByPattern(content, extractPattern);
		try {
			return Integer.parseInt(rawString);
		} catch (NumberFormatException e) {
			log.info("NumberFormatException, string={}", rawString);
		}
		return 0;
	}

	private static Date extractByPatternAndToDate(String content, String extractPattern, String dateFormatPattern) {
		String rawString = extractByPattern(content, extractPattern);
		try {
			return new SimpleDateFormat(dateFormatPattern).parse(rawString);
		} catch (ParseException e) {
			log.info("SimpleDateFormat parse exception, string={}", rawString);
		}
		return null;
	}

	private static String getHtml(String url) {
		final int DEFAULT_RETRY_TIMES = 10;
		for (int i = 1; i <= DEFAULT_RETRY_TIMES; i++) {
			try {
				return Jsoup.connect(url).execute().body();
			} catch (IOException e) {
				log.info("url={}, retry={}", url, i);
			}
		}
		return "";
	}

	private static void show(final String username) {
		final String savePath = getSavePathByUserName(username);
		try {
			List postMetaInfoList = FileUtils.readLines(new File(savePath), "UTF-8");
			postMetaInfoList.stream().map(postMetaInfo -> JSON.parseObject(postMetaInfo, PostMetaInfo.class).getPostTime().getHours())
					.collect(Collectors.groupingBy(x -> x))
					.forEach((k, v) -> {
						// 柱状图总共使用1000个小条条,根据屏幕大小进行调节选择最舒适的视图
						int length = (int) (v.size() * 1000.0 / postMetaInfoList.size());
						System.out.printf("%2s : %s %d\n", k, StringUtils.repeat("=", length), v.size());
					});
		} catch (IOException e) {
			log.info("read file error, path={}", savePath);
		}
	}

	public static void main(String[] args) {
		final String username = "CC11001100";
		grabMetaInfoByUserName(username);
		show(username);
	}

}

上面的代码做的事情就是爬取某个人的所有博客,并将发布时间以小时为单位做一个group by … count,然后使用横向的柱状图画一个简单的图表,我的图表如下:

 image

时间大部分集中在23:00~02:00之间,从上面的图表可以看出这个家伙很经常熬夜,由此恶毒的猜测他应该需要搞点枸杞泡着喝  :(

 

.


推荐阅读
  • 在JavaWeb开发中,文件上传是一个常见的需求。无论是通过表单还是其他方式上传文件,都必须使用POST请求。前端部分通常采用HTML表单来实现文件选择和提交功能。后端则利用Apache Commons FileUpload库来处理上传的文件,该库提供了强大的文件解析和存储能力,能够高效地处理各种文件类型。此外,为了提高系统的安全性和稳定性,还需要对上传文件的大小、格式等进行严格的校验和限制。 ... [详细]
  • MySQL Decimal 类型的最大值解析及其在数据处理中的应用艺术
    在关系型数据库中,表的设计与SQL语句的编写对性能的影响至关重要,甚至可占到90%以上。本文将重点探讨MySQL中Decimal类型的最大值及其在数据处理中的应用技巧,通过实例分析和优化建议,帮助读者深入理解并掌握这一重要知识点。 ... [详细]
  • 本文介绍了如何使用 Node.js 和 Express(4.x 及以上版本)构建高效的文件上传功能。通过引入 `multer` 中间件,可以轻松实现文件上传。首先,需要通过 `npm install multer` 安装该中间件。接着,在 Express 应用中配置 `multer`,以处理多部分表单数据。本文详细讲解了 `multer` 的基本用法和高级配置,帮助开发者快速搭建稳定可靠的文件上传服务。 ... [详细]
  • 本文介绍了如何利用Struts1框架构建一个简易的四则运算计算器。通过采用DispatchAction来处理不同类型的计算请求,并使用动态Form来优化开发流程,确保代码的简洁性和可维护性。同时,系统提供了用户友好的错误提示,以增强用户体验。 ... [详细]
  • Python 程序转换为 EXE 文件:详细解析 .py 脚本打包成独立可执行文件的方法与技巧
    在开发了几个简单的爬虫 Python 程序后,我决定将其封装成独立的可执行文件以便于分发和使用。为了实现这一目标,首先需要解决的是如何将 Python 脚本转换为 EXE 文件。在这个过程中,我选择了 Qt 作为 GUI 框架,因为之前对此并不熟悉,希望通过这个项目进一步学习和掌握 Qt 的基本用法。本文将详细介绍从 .py 脚本到 EXE 文件的整个过程,包括所需工具、具体步骤以及常见问题的解决方案。 ... [详细]
  • 在Java Web服务开发中,Apache CXF 和 Axis2 是两个广泛使用的框架。CXF 由于其与 Spring 框架的无缝集成能力,以及更简便的部署方式,成为了许多开发者的首选。本文将详细介绍如何使用 CXF 框架进行 Web 服务的开发,包括环境搭建、服务发布和客户端调用等关键步骤,为开发者提供一个全面的实践指南。 ... [详细]
  • 本指南介绍了 `requests` 库的基本使用方法,详细解释了其七个主要函数。其中,`requests.request()` 是构建请求的基础方法,支持其他高级功能的实现。此外,我们还重点介绍了如何使用 `requests.get()` 方法来获取 HTML 网页内容,这是进行网页数据抓取和解析的重要步骤。通过这些基础方法,读者可以轻松上手并掌握网页数据抓取的核心技巧。 ... [详细]
  • 本文详细解析了客户端与服务器之间的交互过程,重点介绍了Socket通信机制。IP地址由32位的4个8位二进制数组成,分为网络地址和主机地址两部分。通过使用 `ipconfig /all` 命令,用户可以查看详细的IP配置信息。此外,文章还介绍了如何使用 `ping` 命令测试网络连通性,例如 `ping 127.0.0.1` 可以检测本机网络是否正常。这些技术细节对于理解网络通信的基本原理具有重要意义。 ... [详细]
  • 本文详细解析了Java类加载系统的父子委托机制。在Java程序中,.java源代码文件编译后会生成对应的.class字节码文件,这些字节码文件需要通过类加载器(ClassLoader)进行加载。ClassLoader采用双亲委派模型,确保类的加载过程既高效又安全,避免了类的重复加载和潜在的安全风险。该机制在Java虚拟机中扮演着至关重要的角色,确保了类加载的一致性和可靠性。 ... [详细]
  • 基于Net Core 3.0与Web API的前后端分离开发:Vue.js在前端的应用
    本文介绍了如何使用Net Core 3.0和Web API进行前后端分离开发,并重点探讨了Vue.js在前端的应用。后端采用MySQL数据库和EF Core框架进行数据操作,开发环境为Windows 10和Visual Studio 2019,MySQL服务器版本为8.0.16。文章详细描述了API项目的创建过程、启动步骤以及必要的插件安装,为开发者提供了一套完整的开发指南。 ... [详细]
  • Android 构建基础流程详解
    Android 构建基础流程详解 ... [详细]
  • Keepalived 提供了多种强大且灵活的后端健康检查机制,包括 HTTP_GET、SSL_GET、TCP_CHECK、SMTP_CHECK 和 MISC_CHECK 等多种检测方法。这些健康检查功能确保了高可用性环境中的服务稳定性和可靠性。通过合理配置这些检查方式,可以有效监测后端服务器的状态,及时发现并处理故障,从而提高系统的整体性能和可用性。 ... [详细]
  • 在Linux系统中,网络配置是至关重要的任务之一。本文详细解析了Firewalld和Netfilter机制,并探讨了iptables的应用。通过使用`ip addr show`命令来查看网卡IP地址(需要安装`iproute`包),当网卡未分配IP地址或处于关闭状态时,可以通过`ip link set`命令进行配置和激活。此外,文章还介绍了如何利用Firewalld和iptables实现网络流量控制和安全策略管理,为系统管理员提供了实用的操作指南。 ... [详细]
  • 深入探索HTTP协议的学习与实践
    在初次访问某个网站时,由于本地没有缓存,服务器会返回一个200状态码的响应,并在响应头中设置Etag和Last-Modified等缓存控制字段。这些字段用于后续请求时验证资源是否已更新,从而提高页面加载速度和减少带宽消耗。本文将深入探讨HTTP缓存机制及其在实际应用中的优化策略,帮助读者更好地理解和运用HTTP协议。 ... [详细]
  • 在PHP中实现腾讯云接口签名,以完成人脸核身功能的对接与签名配置时,需要注意将文档中的POST请求改为GET请求。具体步骤包括:使用你的`secretKey`生成签名字符串`$srcStr`,格式为`GET faceid.tencentcloudapi.com?`,确保参数正确拼接,避免因请求方法错误导致的签名问题。此外,还需关注API的其他参数要求,确保请求的完整性和安全性。 ... [详细]
author-avatar
莪乜子12
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有