要使用webmagic爬虫首先要对该框架有一定了解,以下链接是webmagic的详细介绍和入门手册
webmagic中文手册
<dependencies>
<dependency>
<groupId>us.codecraftgroupId>
<artifactId>webmagic-coreartifactId>
<version>0.7.3version>
dependency>
<dependency>
<groupId>us.codecraftgroupId>
<artifactId>webmagic-extensionartifactId>
<version>0.7.3version>
<exclusions>
<exclusion>
<groupId>org.slf4jgroupId>
<artifactId>slf4j-log4j12artifactId>
exclusion>
exclusions>
dependency>
<dependency>
<groupId>us.codecraftgroupId>
<artifactId>webmagic-seleniumartifactId>
<version>0.7.3version>
dependency>
<dependency>
<groupId>commons-collectionsgroupId>
<artifactId>commons-collectionsartifactId>
<version>3.2.1version>
dependency>
<dependency>
<groupId>org.seleniumhq.seleniumgroupId>
<artifactId>selenium-javaartifactId>
<version>3.141.59version>
dependency>
<dependency>
<groupId>org.seleniumhq.seleniumgroupId>
<artifactId>selenium-chrome-driverartifactId>
<version>3.141.59version>
dependency>
<dependency>
<groupId>org.seleniumhq.seleniumgroupId>
<artifactId>selenium-serverartifactId>
<version>3.141.59version>
dependency>
<dependency>
<groupId>junitgroupId>
<artifactId>junitartifactId>
<version>4.12version>
<scope>compilescope>
dependency>
dependencies>
为了实现网站爬虫,我们实现pageprocessor接口对代码进行扩展
public class ImagePageProcessor implements PageProcessor {
@Override
public void process(Page page) {
/* 第一步,从当前页面中发现指定格式链接添加进目标用来进行下一步爬取 */
page.addTargetRequests(page.getHtml().links().regex("https://www\\.****\\.com/.*\\.html").all());
/* 第二步,从当前页面爬取数据 */
// 获取title标题(使用xpah获取指定数据)
String title=page.getHtml().xpath("//h1[@class='title']/text()").toString();
// 判断是否有标题,无标题跳过当前页
if (StringUtils.isEmpty(title)) {
// 跳过当前页,pipeline不会进行输出
page.setSkip(true);
}
//页面title装入page中的resultItems
page.putField("title", title);
//页面中得到指定位置的照片url,即img元素的src属性(使用xpah获取指定数据)
List<String> PicUrl = page.getHtml().xpath("//div[@class='image']/p/span").css("img", "src").all();
//另一种写法
//List PicUrl = page.getHtml().xpath("//div[@class='image']/p/span/img/@src").all();
//照片路径装入page中的resultItems
page.putField("PicUrl",PicUrl);
// console打印当前页面全部内容(测试时用)
//System.out.println(page.getHtml().toString());
}
@Override
public Site getSite() {
return Site.me().setRetryTimes(1).setSleepTime(2000);
}
//程序执行主程序入口
public static void main(String[] args) {
// 当需要使用seleniudownloader类时,加载webmaigc定义的属性参数,自定义指定路径
System.getProperties().setProperty("selenuim_config","E:\\***\\src\\main\\resources\\config.ini");
//spider创建ImagePageProcessor核心对象
Spider.create(new ImagePageProcessor())
//填写带照片的目标网址
.addUrl("https://www.****.com/***/***.html")
//实现console打印page中加入的resultItems元素
.addPipeline(new ConsolePipeline())
/*实现自定义ImagePiple打印page中加入的resultItems元素
*保存至E:\\spider文件下
*/
.addPipeline(new ImagePipeline("E:\\spider"))
//一般不配置,不使用
//.setScheduler(new QueueScheduler())
//设置浏览器核心,当网页使用动态加载图片时需要配置seleniumDownloader
.setDownloader(new SeleniumDownloader("E:\\***\\src\\main\\resources\\chromedriver.exe"))
//设置线程数
.thread(2)
.run();
}
/**
*SeleniumDownloader功能测试
*该代码使用的是chrome浏览器,chromedriver百度自行下载
*chrome和chromedriver版本保持严格匹配,我因为用错版本一直报错
*/
@Test
public void test2(){
System.setProperty("webdriver.chrome.driver",
"E:\\***\\src\\main\\resources\\chromedriver.exe");
// 第二步:初始化驱动
WebDriver driver = new ChromeDriver();
// 第三步:获取目标网页
driver.get("https://blog.csdn.net/qqzjyywx1/article/details/107702834");
// 第四步:解析。以下就可以进行解了。使用webMagic等进行必要的解析。
System.out.println("Page title is: " + driver.getTitle());
System.out.println("Page title is: " + driver.getPageSource());
}
}
接下来是执行文件保存功能的ImagePipeline,继承了FilePersistentBase类,实现了Pipeline接口
public class ImagePipeline extends FilePersistentBase implements Pipeline{
private Logger logger = LoggerFactory.getLogger(getClass());
//文件保存路径,之后配置
String savepath=null;
/**
* create a default path"/data/webmagic/"
*/
public ImagePipeline() {
setPath("/data/webmagic/");
}
public ImagePipeline(String path) {
setPath(path);
}
@Override
public void process(ResultItems resultItems, Task task) {
//保存路径我设置为 自定义路径/网站名/标题名/文件名.png
savepath = this.path+task.getUUID()+PATH_SEPERATOR+resultItems.get("title")+ PATH_SEPERATOR;
List<String> PicUrl=resultItems.get("PicUrl");
// 当图片链接存在,生成savepath路径的文件夹,然后下载图片
if(PicUrl.size()>0) {
checkAndMakeParentDirecotry(savepath);
downloadPicture(PicUrl);
}else{
//当图片链接不存在
System.out.println("该page图片链接不存在:" + resultItems.get("title"));
}
}
//下载图片链接方法代码
public void downloadPicture(List<String> urlList) {
URL url = null;
for (int i = 0; i < urlList.size(); i++) {
try {
String[] files = urlList.get(i).split("/");
String name = files[files.length - 1];
url = new URL(urlList.get(i));
File file = new File(savepath + name);
// 文件不存在
if(!file.exists()){
DataInputStream dataInputStream = new DataInputStream(url.openStream());
FileOutputStream fileOutputStream = new FileOutputStream(file);
byte[] buffer = new byte[1024 * 50];
int length;
while ((length = dataInputStream.read(buffer)) > 0) {
fileOutputStream.write(buffer, 0, length);
}
System.out.println("已经下载:" + savepath + name);
dataInputStream.close();
fileOutputStream.close();
}else{
System.out.println("该文件已存在" + savepath + name);
}
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (FileNotFoundException e) {
System.out.println("下载文件路径不存在:" + url);
}catch (IOException e) {
e.printStackTrace();
}
}
}
}
当网站没有动态数据,不使用
接下来是seleniumDownloader的config.ini文件配置,从GitHub上下载config.ini的源文件,配置相应的浏览器driver即可
# What WebDriver to use for the tests
#driver=phantomjs
#driver=firefox
driver=chrome
#driver=http://localhost:8910
#driver=http://localhost:4444/wd/hub
# PhantomJS specific config (change according to your installation)
#phantomjs_exec_path=/Users/Bingo/bin/phantomjs-qt5
phantomjs_exec_path=/Users/Bingo/Downloads/phantomjs-1.9.8-macosx/bin/phantomjs
#phantomjs_driver_path=/Users/Bingo/Documents/workspace/webmagic/webmagic-selenium/src/main.js
#phantomjs_driver_loglevel=DEBUG
执行ImagePageProcessor中test2方法,出现下图则配置正确