抓取QQ空间动态分词统计并生成标签图

/ 分享 / 无站内评论 / 574浏览

前言

元旦看着空间和朋友圈各种新年祝福愿望,于是萌生了想统计生成标签的想法。朋友圈有点难度,先空间练练手。

效果图

思路

抓包登陆发现http参数有点复杂,腾讯反抓取做的很厉害,于是尝试使用自动化测试工具进行抓取。

1.这里使用selenium

可以翻我历史,有写过相关文章介绍


登陆成功后,可以带着cookie去访问。但是接口太多了,懒得一个个分析,直接使用SelenIUM抓完了。

2.驱动使用PhantomJS

3.模拟下拉

历史的数据需要下拉才能展示


技术

<!-- guava -->
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>23.0</version>
</dependency>
<!-- selenium -->
<dependency>
<groupId>org.seleniumhq.selenium</groupId>
<artifactId>selenium-java</artifactId>
<version>3.3.1</version>
</dependency>
<!--httpclient-->
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
<version>4.5.3</version>
</dependency>
<dependency>
<!--分词-->
<dependency>
<groupId>org.apdplat</groupId>
<artifactId>word</artifactId>
<version>1.3</version>
</dependency>


代码

/**
* 抓取QQ空间动态分词统计并生成标签图
*/
public class label {
public static void main(String[] args) throws InterruptedException {
//登录
WebDriver login_frame = login("账号","密码");

//得到分词数据
ArrayList list = getData(login_frame, "昨天");

//保存数据
doWriteToFile(list, "E:\\cloud.txt");

//可以拿生成的数据到 https://worditout.com 在线生成标签
}

/**
* @param login_frame
* @param stopDate 抓取终止说说的最晚时间
* @return
* @throws InterruptedException
*/
private static ArrayList<String> getData(WebDriver login_frame, String stopDate) throws InterruptedException {
ArrayList<String> list = Lists.newArrayList();
Document document;
while (true) {
//模拟下拉操作
((JavascriptExecutor) login_frame).executeScript("window.scrollTo(0,document.body.scrollHeight)");
String pageSource = login_frame.getPageSource();
if (StringUtils.isEmpty(pageSource)) {
System.out.println("未抓取到页面元素");
break;
}
document = Jsoup.parse(pageSource);
//这里限制了今天,可以根据需要改
if (document.getElementsByClass("info-detail").html().contains(stopDate)) {
login_frame.quit();
break;
}
//说说账号
Elements nick = document.getElementsByClass("f-nick");
//说说内容
Elements info = document.getElementsByClass("f-info");

//分词
int max;
max = nick.size() > info.size() ? info.size() : nick.size();
for (int i = 0; i < max; i++) {
String nickVal = nick.get(i).getElementsByTag("a").first().text();
String infoVal = info.get(i).text();
List<String> strings = WordSegmenter.seg(infoVal).stream().map(Word::getText).collect(Collectors.toList());
list.addAll(strings);
System.out.println(nickVal + " " + infoVal);
}
Thread.sleep(1000L);
}
return list;
}

/**
* 将数据写到文件
*
* @param list 分词数据
* @param path 文件保存路径
*/
private static void doWriteToFile(ArrayList<String> list, String path) {
//list分词数据转成map并统计分词出现的次数(权重),权重越高,越靠中字越大
HashMap<String, Integer> map = Maps.newHashMap();
list.forEach(s -> {
if (map.containsKey(s)) {
map.put(s, map.get(s) + 1);
} else {
map.put(s, 1);
}
});

File newFile = new File(path);
map.forEach((s, integer) -> {
String str = s + " " + integer;
try {
//guava file
Files.append(str.concat(System.getProperty("line.separator")), newFile, Charsets.UTF_8);
//下面方式会自动回车并换行
// CharSink sink = Files.asCharSink(newFile, Charsets.UTF_8, FileWriteMode.APPEND);
// sink.writeLines(Collections.singleton(str.concat(System.getProperty("line.separator"))));
} catch (IOException e) {
e.printStackTrace();
}
});
}

/**
* 登录操作
* @param user 账号
* @param pwd 密码
* @return
*/
private static WebDriver login(String user, String pwd) {
//使用驱动工厂类创建
WebDriver driver = DriverStrategyFactory.getInstance(DriverEnum.PhantomJS);
driver.get("https://qzone.qq.com/");
WebDriver login_frame = driver.switchTo().frame(driver.findElement(By.id("login_frame")));
login_frame.findElement(By.id("switcher_plogin")).click();
new WebDriverWait(driver, 1);
login_frame.findElement(By.id("u")).sendKeys(user);
new WebDriverWait(driver, 1);
login_frame.findElement(By.id("p")).sendKeys(pwd);
new WebDriverWait(driver, 1);
login_frame.findElement(By.id("login_button")).click();
// 等待页面加载完毕,超时时间设为3
(new WebDriverWait(driver, 3)).until(new ExpectedCondition<Boolean>() {
@Override
public Boolean apply(WebDriver d) {
//这里对加了校验,如果不加校验,当页面DOM还没加载完成时去获取了DOM节点,此时会抛异常。这里对DOM进行校验,如果节点存在则往下走,抛异常则继续等待3秒。
return isLoad(d);
}

private Boolean isLoad(WebDriver d) {
try {
login_frame.findElement(By.id("tab_menu_friend")).findElement(By.className("qz-main"));
return true;
} catch (Exception e) {
return false;
}
}
});
login_frame.findElement(By.id("tab_menu_friend")).findElement(By.className("qz-main")).click();
return login_frame;
}
}


召唤蕾姆
琼ICP备18000156号

鄂公网安备 42011502000211号