首页 > 其他分享 >WebMagic 抓取,selenium模拟点击操作,模拟将抓取的数据入库

WebMagic 抓取,selenium模拟点击操作,模拟将抓取的数据入库

时间:2024-11-11 13:46:54浏览次数:4  
标签:codecraft selenium driver 抓取 import page 模拟 webmagic

动态页面爬虫前的准备:https://www.cnblogs.com/maohuidong/p/18517953

java 添加maven依赖:

<dependency>
<groupId>us.codecraft</groupId>
<artifactId>webmagic-core</artifactId>
<version>0.7.4</version>
</dependency>
<dependency>
<groupId>us.codecraft</groupId>
<artifactId>webmagic-extension</artifactId>
<version>0.7.4</version>
</dependency>
<!--selenium依赖-->
<dependency>
<groupId>org.seleniumhq.selenium</groupId>
<artifactId>selenium-java</artifactId>
<version>3.141.59</version>
</dependency>

ShowDocPageProcessor类:

import org.openqa.selenium.By;
import org.openqa.selenium.Cookie;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.chrome.ChromeOptions;
import org.openqa.selenium.remote.RemoteWebDriver;
import us.codecraft.webmagic.Page;
import us.codecraft.webmagic.Site;
import us.codecraft.webmagic.Spider;
import us.codecraft.webmagic.pipeline.JsonFilePipeline;
import us.codecraft.webmagic.processor.PageProcessor;

import java.util.List;
import java.util.Set;

/**
* 准备抓取这个页面:http://showdoc.external.xxxx.so/web/#/2?page_id=53
* 并把该页面所有的链接都抓取到(所有的链接通过selenium模拟点击操作获取)。将抓取的页面数据 通过实现Pipeline接口来模拟插入到数据库中。
* 但是这个页面需要登录后才能访问,登录页面为:http://showdoc.external.xxxx.so/web/#/user/login
*/
public class ShowDocPageProcessor implements PageProcessor {

private Site site = Site.me().setRetryTimes(3).setSleepTime(0).setTimeOut(3000);

//用来存储cookie信息
private Set<Cookie> cookies;

private RemoteWebDriver driver;

public ShowDocPageProcessor(){
System.setProperty("webdriver.chrome.driver","E:\\chromedriver-win64\\chromedriver-win64\\chromedriver.exe");

//创建浏览器参数对象
ChromeOptions chromeOptions = new ChromeOptions();
// 设置为 无界面浏览器 模式,若是不想看到浏览器打开,就可以配置此项

//解决 403 出错问题
chromeOptions.addArguments("--remote-allow-origins=*");
// chromeOptions.addArguments("--headless");
chromeOptions.addArguments("--window-size=1440,1080");// 设置浏览器窗口打开大小

RemoteWebDriver driver = new ChromeDriver(chromeOptions);
this.driver = driver;
}


@Override
public void process(Page page) {
String url = page.getUrl().get();
// 如果是要抓取的页面,则把该页面所有的子链接加入到WebMagic中,否则认为是子链接,直接抓取
if("http://showdoc.external.xxxx.so/web/#/2?page_id=53".equals(url)){
// selenium 模拟点击,把所有链接加入到WebMagic中
List<WebElement> elements = driver.findElements(By.xpath("//*[@id='left-side']/div/ul/li"));
for (int i = 1;i <= elements.size();i++) {
elements.get(i-1).click();
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
List<WebElement> divs = driver.findElements(By.xpath("//*[@id='left-side']/div/ul/li[" + i + "]/ul/li"));
if(divs.size() > 0){
for (WebElement div : divs) {
div.click();
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
System.out.println("当前的URL=" + driver.getCurrentUrl());
page.addTargetRequest(driver.getCurrentUrl());
}
}
}
}else{
// 将抓取的页面数据写到page中。
page.putField(page.getHtml().xpath("//*[@id='doc-title']/text()").get(),page.getHtml().xpath("//*[@id='editor-md']/ul[2]/li/code/text()").get());
}

}

//使用 selenium 来模拟用户的登录获取cookie信息
public void login(String loginUrl,String userName,String password)
{
driver.get(loginUrl);

driver.findElement(By.xpath("//form/div[1]//input")).clear();

//在******中填你的用户名
driver.findElement(By.xpath("//form/div[1]//input")).sendKeys(userName);

driver.findElement(By.xpath("//form/div[2]//input")).clear();
//在*******填你密码
driver.findElement(By.xpath("//form/div[2]//input")).sendKeys(password);

//模拟点击登录按钮
driver.findElement(By.xpath("//button")).click();

//获取cookie信息
cookies = driver.manage().getCookies();
// driver.close();
}


@Override
public Site getSite() {

//将获取到的cookie信息添加到webmagic中
for (Cookie cookie : cookies) {
site.addCookie(cookie.getName().toString(),cookie.getValue().toString());
}

return site.addHeader("User-Agent", "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.1 (KHTML, like Gecko) Chrome/22.0.1207.1 Safari/537.1");
}

public static void main(String[] args){

ShowDocPageProcessor pageProcessor = new ShowDocPageProcessor();

//调用selenium,进行模拟登录
pageProcessor.login("http://showdoc.external.xxx.so/web/#/user/login","xxx","xxx");
Spider.create(pageProcessor)
.addUrl("http://showdoc.external.rongyi.so/web/#/2?page_id=53")
.setDownloader(new MyDownloader(pageProcessor.driver))//可选择使用自定义的
// 输出到D盘webmagic文件夹
.addPipeline(new JsonFilePipeline("D:\\webmagic\\"))
.addPipeline(new MyPipeline())
//开启1个线程抓取
.thread(1)
//启动爬虫
.run();
System.out.println("爬取结束");
}
}


MyDownloader类:

import org.openqa.selenium.remote.RemoteWebDriver;
import us.codecraft.webmagic.Page;
import us.codecraft.webmagic.Request;
import us.codecraft.webmagic.Task;
import us.codecraft.webmagic.downloader.Downloader;
import us.codecraft.webmagic.selector.PlainText;
public class MyDownloader implements Downloader {
//声明驱动
private RemoteWebDriver driver;

public MyDownloader(RemoteWebDriver driver) {
this.driver = driver;
}

/**
*
*/
@Override
public Page download(Request request, Task task) {
try {
driver.get(request.getUrl());
Thread.sleep(2000);//等待打开浏览器
// 使用driver.navigate().refresh()方法手动刷新页面(在获取第二个链接时,我这里页面不刷新,用此方法可以解决)
driver.navigate().refresh();
Thread.sleep(2000);//等待打开浏览器
driver.executeScript("window.scrollTo(0, document.body.scrollHeight - 1000)");//需要滚动到页面的底部,获取完整的数据
Thread.sleep(2000);//等待滚动完成
//获取页面,打包成Page对象,传给PageProcessor 实现类
Page page = createPage(request.getUrl(), driver.getPageSource());
// driver.close();//看需要是否关闭浏览器
return page;
} catch (InterruptedException e) {
e.printStackTrace();
}
return null;
}

@Override
public void setThread(int threadNum) {

}

//构建page返回对象
private Page createPage(String url, String content) {
Page page = new Page();
page.setRawText(content);
page.setUrl(new PlainText(url));
page.setRequest(new Request(url));
page.setDownloadSuccess(true);
return page;
}
}

MyPipeline类:

import org.springframework.util.StringUtils;
import us.codecraft.webmagic.ResultItems;
import us.codecraft.webmagic.Task;
import us.codecraft.webmagic.pipeline.Pipeline;

import java.util.Map;

public class MyPipeline implements Pipeline {

@Override
public void process(ResultItems resultItems, Task task) {
Map<String, Object> all = resultItems.getAll();
if(all != null && all.size() > 0){
all.forEach((key,value) ->{
// 模拟保存到数据库的操作
if(StringUtils.isEmpty(key) || StringUtils.isEmpty(value)){
String url = resultItems.getRequest().getUrl();
System.out.println("有空数据");
}else {
System.out.println("key=" + key + "。value=" + value.toString());
}
});
}
}
}

标签:codecraft,selenium,driver,抓取,import,page,模拟,webmagic
From: https://www.cnblogs.com/maohuidong/p/18539528

相关文章

  • 拓扑AC NOIP模拟赛2
    100+35+10+10拿下rk7,拓扑AC的A题也太过困难了吧……T1题意给定数组\(a\),数组长度为\(n\)。定义\(f(x)\)表示有多少对\((i,j)\)满足\((a_i+x)\)是\((a_j+x)\)的子集。给定\(k\),保证\(a_i<2^k\),求\(\sum_{i=0}^{2^{k-1}}f(i)\)。\(n\leq20000,k\leq60\)。赛......
  • 多校A层冲刺NOIP2024模拟赛20
    多校A层冲刺NOIP2024模拟赛20昨天晚上打ABC了,所以今天才发。T1星际联邦直接上菠萝(Borůvka)算法就行了,当然还可以用线段树优化prim算法,但是没打过只是口胡:就是维护当前的连通块,但一个点$i$加入连通块时,后面那些点就可以有$a_j-a_i$的贡献,前面的点可以有$a_i-......
  • [赛记] 多校A层冲刺NOIP2024模拟赛20
    星际联邦80pts前连20条,后连20条80pts。。。考虑正解,发现向前连最大,向后连最小会出现重边,所以避免出现这种情况,我们只需要在做完向前连最大以后,在向后连最小的时候连不是同一个连通块的即可;时间复杂度:$\Theta(n\logn)$,瓶颈在排序;其实这个思想就是最小生成树的那个BUA算法......
  • Selenium等待条件
    Selenium提供了WebDriverWait类用于针对指定元素设置等待,其中内含until(self,method,str="")和until_not(self,method,str="")两个方法判断,其中的参数method(判断条件)通常与expected_conditions模块连用,其内部封装了判断方法,本文介绍expected_conditions模块下的方法。一、expecti......
  • 『模拟赛』NOIP2024(欢乐)加赛3
    Rank真欢乐吗,不过missionaccomplished.A.SakurakoandWaterCF2033B*900byd还懂难易搭配,不过这个b翻译甚至不着重以下主对角线差评,被硬控半个小时,直到手模样例才发觉不对。读懂题就很简单了,最优一定是找最长的对角线每次加,一共只有\(2n-1\)条线,枚举一下求出每条......
  • [考试记录] 2024.11.9 noip模拟赛9
    T1星际联邦菠萝算法。不过简化版。考虑从后往前遍历,如果当前的电的联通块大小为\(1\)的话,就把他和前缀最大值或者是前缀最小值连边。如果大于\(1\),那就将联通块里的最小权点和前缀最大值连边即可。#include<bits/stdc++.h>usingnamespacestd;#defineintlonglongcon......
  • 241110 noip 模拟赛
    省流:\(100+100+100+0\)。T1题意:给定长度为\(n\)的序列\(a,b\),你需要找到一个字典序最大的序列\(ans\)使得对于所有的\(1\leqi\leqn\),\(ans_i=((a_i\oplusans_{i-1})+(b_i\oplusans_{i-1}))\%2^{32}\),其中\(ans_0=ans_n\)。\(1\leqn\leq3\times......
  • 每周算法2:数学+模拟+哈希表+栈+线性dp+贪心(简单)
    目录1.统计数字描述输入描述:输出描述: 题解2.两个数组的交集(哈希表)描述题解 3.点击消除(栈)描述输入描述:输出描述: 题解4.牛牛的快递(模拟+补充)描述输入描述:输出描述:题解 5.最小花费爬楼梯(简单线性dp)描述输入描述:输出描述:示例1题解6.数组中两......
  • 还在搞传统爬虫吗?2025年用人工智能轻松抓取几乎所有网站
    今天,我将介绍一种简单的方法,帮助大家从各种网站上收集数据,搭建一个能够像人在浏览器中操作的网页爬虫。这种爬虫甚至可以在Upwork等平台上独立完成一些网页抓取的自由职业任务。自2024年以来,随着AI的发展,网页抓取发生了巨大的变化。以前,大公司如亚马逊或沃尔玛为了保持价......
  • noip模拟9
    来自官方题解.md星际联邦做法比较多,可以直接用Prim来做,但最简单的做法仍然是考虑Borůvka算法,我们在每一轮需要找到这个点向外到另一个联通块内的最小边。注意到当\(i\)固定时,最小边要么是前缀\([1,i)\)的最大值取到的,要么是\((i,n]\)内的最小值取到的。我们只需要......