Commit 359e965c authored by code4craft's avatar code4craft

init

parents
target/*
*.iml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<groupId>us.codecraft</groupId>
<version>0.0.1-SNAPSHOT</version>
<modelVersion>4.0.0</modelVersion>
<artifactId>webmagic</artifactId>
<dependencies>
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
<version>4.2.1</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.7</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>13.0.1</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.1</version>
</dependency>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency>
<dependency>
<groupId>commons-collections</groupId>
<artifactId>commons-collections</artifactId>
<version>3.2.1</version>
</dependency>
<dependency>
<groupId>net.sourceforge.htmlcleaner</groupId>
<artifactId>htmlcleaner</artifactId>
<version>2.4</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-io</artifactId>
<version>1.3.2</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-resources-plugin</artifactId>
<configuration>
<encoding>UTF-8</encoding>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-source-plugin</artifactId>
<executions>
<execution>
<id>attach-sources</id>
<goals>
<goal>jar</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-javadoc-plugin</artifactId>
<executions>
<execution>
<id>attach-javadocs</id>
<goals>
<goal>jar</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-release-plugin</artifactId>
<version>2.0-beta-7</version>
</plugin>
</plugins>
</build>
</project>
\ No newline at end of file
package us.codecraft.spider;
import org.apache.commons.lang3.StringUtils;
import us.codecraft.spider.selector.Selectable;
import us.codecraft.spider.utils.UrlUtils;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
/**
* User: cairne
* Date: 13-4-21
* Time: 上午11:22
*/
public class Page {
private Request request;
private Map<String, Selectable> fields = new ConcurrentHashMap<String, Selectable>();
private Selectable html;
private Selectable url;
private List<Request> targetRequests = new ArrayList<Request>();
public void process() {
fields.put("title", html.x("").r(""));
}
public Page() {
}
public Map<String, Selectable> getFields() {
return fields;
}
public void putField(String key, Selectable field) {
fields.put(key, field);
}
public Selectable getHtml() {
return html;
}
public void setHtml(Selectable html) {
this.html = html;
}
public List<Request> getTargetRequests() {
return targetRequests;
}
public void addTargetRequests(List<String> requests) {
synchronized (targetRequests) {
for (String s : requests) {
if (StringUtils.isBlank(s) || s.equals("#") || s.startsWith("javascript:")) {
break;
}
s = UrlUtils.fixRelativeUrl(s, url.toString());
targetRequests.add(new Request(s));
}
}
}
public void addTargetRequests(String requestString) {
if (StringUtils.isBlank(requestString) || requestString.equals("#")) {
return;
}
synchronized (targetRequests) {
requestString = UrlUtils.fixRelativeUrl(requestString, url.toString());
targetRequests.add(new Request(requestString));
}
}
public Selectable getUrl() {
return url;
}
public void setUrl(Selectable url) {
this.url = url;
}
public Request getRequest() {
return request;
}
public void setRequest(Request request) {
this.request = request;
}
}
package us.codecraft.spider;
import us.codecraft.spider.Site;
import java.util.List;
/**
* User: cairne
* Date: 13-4-21
* Time: 上午11:37
*/
public class Request {
private String url;
private Object[] extra;
public Request(String url, Object... extra) {
this.url = url;
this.extra = extra;
}
public Object[] getExtra() {
return extra;
}
public String getUrl() {
return url;
}
}
package us.codecraft.spider;
import java.util.HashSet;
import java.util.Set;
/**
* User: cairne
* Date: 13-4-21
* Time: 下午12:13
*/
public class Site {
private String domain;
private String userAgent;
private String cookie;
private String encoding;
private String startUrl;
private int sleepTime = 3000;
private static final Set<Integer> DEFAULT_STATUS_CODE_SET = new HashSet<Integer>();
private Set<Integer> acceptStatCode = DEFAULT_STATUS_CODE_SET;
static {
DEFAULT_STATUS_CODE_SET.add(200);
}
public static Site me() {
return new Site();
}
public Site setCookie(String cookie) {
this.cookie = cookie;
return this;
}
public Site setUserAgent(String userAgent) {
this.userAgent = userAgent;
return this;
}
public String getCookie() {
return cookie;
}
public String getUserAgent() {
return userAgent;
}
public String getDomain() {
return domain;
}
public Site setDomain(String domain) {
this.domain = domain;
return this;
}
public String getEncoding() {
return encoding;
}
public Site setEncoding(String encoding) {
this.encoding = encoding;
return this;
}
public Set<Integer> getAcceptStatCode() {
return acceptStatCode;
}
public Site setAcceptStatCode(Set<Integer> acceptStatCode) {
this.acceptStatCode = acceptStatCode;
return this;
}
public String getStartUrl() {
return startUrl;
}
public Site setStartUrl(String startUrl) {
this.startUrl = startUrl;
return this;
}
public int getSleepTime() {
return sleepTime;
}
public Site setSleepTime(int sleepTime) {
this.sleepTime = sleepTime;
return this;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Site site = (Site) o;
if (acceptStatCode != null ? !acceptStatCode.equals(site.acceptStatCode) : site.acceptStatCode != null)
return false;
if (cookie != null ? !cookie.equals(site.cookie) : site.cookie != null) return false;
if (!domain.equals(site.domain)) return false;
if (encoding != null ? !encoding.equals(site.encoding) : site.encoding != null) return false;
if (userAgent != null ? !userAgent.equals(site.userAgent) : site.userAgent != null) return false;
return true;
}
@Override
public int hashCode() {
int result = domain.hashCode();
result = 31 * result + (userAgent != null ? userAgent.hashCode() : 0);
result = 31 * result + (cookie != null ? cookie.hashCode() : 0);
result = 31 * result + (encoding != null ? encoding.hashCode() : 0);
result = 31 * result + (acceptStatCode != null ? acceptStatCode.hashCode() : 0);
return result;
}
}
package us.codecraft.spider;
import org.apache.commons.collections.CollectionUtils;
import org.apache.log4j.Logger;
import us.codecraft.spider.downloader.Downloader;
import us.codecraft.spider.downloader.HttpClientDownloader;
import us.codecraft.spider.pipeline.ConsolePipeline;
import us.codecraft.spider.pipeline.Pipeline;
import us.codecraft.spider.processor.PageProcessor;
import us.codecraft.spider.schedular.QueueSchedular;
import us.codecraft.spider.schedular.Schedular;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
/**
* User: cairne
* Date: 13-4-21
* Time: 上午6:53
*/
public class Spider implements Runnable {
private Downloader downloader = new HttpClientDownloader();
private Pipeline pipeline = new ConsolePipeline();
private PageProcessor pageProcessor;
private Schedular schedular = new QueueSchedular();
private Logger logger = Logger.getLogger(getClass());
public static Spider me() {
return new Spider();
}
public Spider processor(PageProcessor pageProcessor) {
this.pageProcessor = pageProcessor;
schedular.push(new Request(pageProcessor.getSite().getStartUrl()), pageProcessor.getSite());
return this;
}
public Thread thread() {
return new Thread(this);
}
public Spider schedular(Schedular schedular) {
this.schedular = schedular;
return this;
}
public Spider pipeline(Pipeline pipeline) {
this.pipeline = pipeline;
return this;
}
@Override
public void run() {
Site site = pageProcessor.getSite();
Request request = schedular.poll(site);
while (request != null) {
Page page = downloader.download(request,site);
if (page == null) {
sleep(site.getSleepTime());
continue;
}
pageProcessor.process(page);
addRequest(page);
pipeline.process(page,site);
sleep(site.getSleepTime());
request = schedular.poll(site);
}
}
private void sleep(int time) {
try {
Thread.sleep(time);
} catch (InterruptedException e) {
e.printStackTrace();
;
}
}
private void addRequest(Page page) {
if (CollectionUtils.isNotEmpty(page.getTargetRequests())) {
for (Request request : page.getTargetRequests()) {
schedular.push(request,pageProcessor.getSite());
}
}
}
}
package us.codecraft.spider.downloader;
import us.codecraft.spider.Page;
import us.codecraft.spider.Request;
import us.codecraft.spider.Site;
/**
* User: cairne
* Date: 13-4-21
* Time: 下午12:14
*/
public interface Downloader {
public Page download(Request request,Site site);
}
package us.codecraft.spider.downloader;
import org.apache.commons.io.IOUtils;
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.log4j.Logger;
import us.codecraft.spider.Page;
import us.codecraft.spider.Request;
import us.codecraft.spider.Site;
import us.codecraft.spider.selector.Html;
import us.codecraft.spider.selector.PlainText;
import us.codecraft.spider.utils.UrlUtils;
/**
* User: cairne
* Date: 13-4-21
* Time: 下午12:15
*/
public class HttpClientDownloader implements Downloader {
private Logger logger = Logger.getLogger(getClass());
@Override
public Page download(Request request, Site site) {
logger.info("downloading page " + request.getUrl());
HttpClient httpClient = HttpClientPool.getInstance().getClient(site);
try {
HttpGet httpGet = new HttpGet(request.getUrl());
HttpResponse httpResponse = httpClient.execute(httpGet);
int statusCode = httpResponse.getStatusLine().getStatusCode();
if (site.getAcceptStatCode().contains(statusCode)) {
String content = IOUtils.toString(httpResponse.getEntity().getContent(),
site.getEncoding() == null ? site.getEncoding() : httpResponse.getEntity().getContentType().getValue());
Page page = new Page();
page.setHtml(new Html(UrlUtils.fixAllRelativeHrefs(content, request.getUrl())));
page.setUrl(new PlainText(request.getUrl()));
page.setRequest(request);
return page;
} else {
logger.warn("code error " + statusCode);
}
} catch (Exception e) {
logger.warn("download page " + request.getUrl() + " error", e);
}
return null;
}
}
package us.codecraft.spider.downloader;
import org.apache.http.HttpVersion;
import org.apache.http.client.HttpClient;
import org.apache.http.client.params.ClientPNames;
import org.apache.http.client.params.CookiePolicy;
import org.apache.http.conn.scheme.PlainSocketFactory;
import org.apache.http.conn.scheme.Scheme;
import org.apache.http.conn.scheme.SchemeRegistry;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.impl.conn.PoolingClientConnectionManager;
import org.apache.http.params.*;
import us.codecraft.spider.Site;
/**
* User: cairne
* Date: 13-4-21
* Time: 下午12:29
*/
public class HttpClientPool {
public static final HttpClientPool INSTANCE = new HttpClientPool(5);
public static HttpClientPool getInstance() {
return INSTANCE;
}
private int poolSize;
private HttpClientPool(int poolSize) {
this.poolSize = poolSize;
}
public HttpClient getClient(Site site) {
return generateClient(site);
}
private HttpClient generateClient(Site site) {
HttpParams params = new BasicHttpParams();
params.setParameter(CoreProtocolPNames.USER_AGENT, site.getUserAgent());
params.setIntParameter(CoreConnectionPNames.SO_TIMEOUT, 1000);
params.setIntParameter(CoreConnectionPNames.CONNECTION_TIMEOUT, 2000);
HttpProtocolParamBean paramsBean = new HttpProtocolParamBean(params);
paramsBean.setVersion(HttpVersion.HTTP_1_1);
paramsBean.setContentCharset("UTF-8");
paramsBean.setUseExpectContinue(false);
SchemeRegistry schemeRegistry = new SchemeRegistry();
schemeRegistry.register(new Scheme("http", 80, PlainSocketFactory.getSocketFactory()));
PoolingClientConnectionManager connectionManager = new PoolingClientConnectionManager(schemeRegistry);
connectionManager.setMaxTotal(100);
connectionManager.setDefaultMaxPerRoute(100);
HttpClient httpClient = new DefaultHttpClient(connectionManager, params);
httpClient.getParams().setIntParameter("http.socket.timeout", 60000);
httpClient.getParams().setParameter(ClientPNames.COOKIE_POLICY, CookiePolicy.BEST_MATCH);
return httpClient;
}
public void pushBack(HttpClient httpClient) {
}
}
package us.codecraft.spider.pipeline;
import us.codecraft.spider.Page;
import us.codecraft.spider.Site;
import us.codecraft.spider.selector.Selectable;
import java.util.Map;
/**
* User: cairne
* Date: 13-4-21
* Time: 下午1:45
*/
public class ConsolePipeline implements Pipeline{
@Override
public void process(Page page,Site site) {
System.out.println("get page: "+page.getUrl());
for (Map.Entry<String, Selectable> entry : page.getFields().entrySet()) {
System.out.println(entry.getKey()+":\t"+entry.getValue().toStrings());
}
}
}
package us.codecraft.spider.pipeline;
import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.lang3.StringUtils;
import us.codecraft.spider.Page;
import us.codecraft.spider.Site;
import us.codecraft.spider.selector.Selectable;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Map;
/**
* User: cairne
* Date: 13-4-21
* Time: 下午6:28
*/
public class FilePipeline implements Pipeline {
private String path = "/data/temp/spider/";
public FilePipeline(){
}
public FilePipeline(String path) {
this.path = path;
}
@Override
public void process(Page page,Site site) {
String domain = site.getDomain();
domain = StringUtils.removeStart(domain, "http://");
domain = StringUtils.removeStart(domain, "https://");
domain = StringUtils.replace(domain, "/", "");
String path = this.path + "" + domain + "/";
File file = new File(path);
if (!file.exists()) {
file.mkdir();
}
try {
PrintWriter printWriter = new PrintWriter(new FileWriter(path + DigestUtils.md5Hex(page.getUrl().toString()) + ".html"));
printWriter.println("url:\t" + page.getUrl());
for (Map.Entry<String, Selectable> entry : page.getFields().entrySet()) {
printWriter.println(entry.getKey() + ":\t" + entry.getValue().toStrings());
}
printWriter.close();
} catch (IOException e) {
e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates.
}
}
}
package us.codecraft.spider.pipeline;
import us.codecraft.spider.Page;
import us.codecraft.spider.Site;
/**
* User: cairne
* Date: 13-4-21
* Time: 下午1:39
*/
public interface Pipeline {
public void process(Page page,Site site);
}
package us.codecraft.spider.processor;
import us.codecraft.spider.Page;
import us.codecraft.spider.Site;
/**
* User: cairne
* Date: 13-4-21
* Time: 上午11:42
*/
public interface PageProcessor {
/**
* extends the class to implements variaty spiders
* @param page
*/
public void process(Page page);
/**
* the site the processor for
* @return
*/
public Site getSite();
}
package us.codecraft.spider.processor;
import us.codecraft.spider.Page;
import us.codecraft.spider.Site;
import us.codecraft.spider.utils.UrlUtils;
import java.util.List;
/**
* User: cairne
* Date: 13-4-22
* Time: 下午9:15
*/
public class SimplePageProcessor implements PageProcessor {
private String urlPattern;
private static final String UA = "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_7_2) AppleWebKit/537.31 (KHTML, like Gecko) Chrome/26.0.1410.65 Safari/537.31";
private Site site;
public SimplePageProcessor(String startUrl, String urlPattern) {
this.site = Site.me().setStartUrl(startUrl).
setDomain(UrlUtils.getDomain(startUrl)).setUserAgent(UA);
this.urlPattern = "("+urlPattern.replace(".","\\.").replace("*","[^\"'#]*")+")";
}
@Override
public void process(Page page) {
List<String> requests = page.getHtml().as().rs(urlPattern).toStrings();
page.addTargetRequests(requests);
page.putField("title", page.getHtml().x("//title"));
page.putField("content", page.getHtml().sc());
}
@Override
public Site getSite() {
return site;
}
}
package us.codecraft.spider.schedular;
import org.apache.commons.lang3.math.NumberUtils;
import org.apache.log4j.Logger;
import us.codecraft.spider.Site;
import us.codecraft.spider.Request;
import java.io.*;
import java.util.LinkedHashSet;
import java.util.Set;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.Executors;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;
/**
* User: cairne
* Date: 13-4-21
* Time: 下午1:13
*/
public class FileCacheQueueSchedular implements Schedular {
private Logger logger = Logger.getLogger(getClass());
private String filePath = System.getProperty("java.io.tmpdir");
private String fileUrlAllName = ".urls.txt";
private Site site;
private String fileCursor = ".cursor.txt";
private PrintWriter fileUrlWriter;
private PrintWriter fileCursorWriter;
private AtomicInteger cursor = new AtomicInteger();
private AtomicBoolean inited = new AtomicBoolean(false);
private BlockingQueue<Request> queue;
private Set<String> urls;
public FileCacheQueueSchedular(Site site) {
this.site = site;
}
public FileCacheQueueSchedular(Site site, String filePath) {
this.filePath = filePath;
this.site = site;
}
private void flush() {
fileUrlWriter.flush();
fileCursorWriter.flush();
}
private void init() {
readFile();
initWriter();
initFlushThread();
inited.set(true);
logger.info("init cache schedular success");
}
private void initFlushThread() {
Executors.newScheduledThreadPool(1).scheduleAtFixedRate(new Runnable() {
@Override
public void run() {
flush();
}
}, 10, 10, TimeUnit.SECONDS);
}
private void initWriter() {
try {
fileUrlWriter = new PrintWriter(new FileWriter(filePath + site.getDomain() + fileUrlAllName, true));
fileCursorWriter = new PrintWriter(new FileWriter(filePath + site.getDomain() + fileCursor, false));
} catch (IOException e) {
throw new RuntimeException("init cache schedular error", e);
}
}
private void readFile() {
try {
queue = new LinkedBlockingQueue<Request>();
urls = new LinkedHashSet<String>();
readCursorFile();
readUrlFile();
} catch (IOException e) {
}
}
private void readUrlFile() throws IOException {
String line;
BufferedReader fileUrlReader = new BufferedReader(new FileReader(filePath + site.getDomain() + fileUrlAllName));
int lineReaded = 0;
while ((line = fileUrlReader.readLine()) != null) {
urls.add(line.trim());
lineReaded++;
if (lineReaded > cursor.get()) {
queue.add(new Request(line, site));
}
}
}
private void readCursorFile() throws IOException {
BufferedReader fileCursorReader = new BufferedReader(new FileReader(filePath + site.getDomain() + fileCursor));
String line = null;
//read the last number
while ((line = fileCursorReader.readLine()) != null) {
cursor = new AtomicInteger(NumberUtils.toInt(line));
}
}
@Override
public synchronized void push(Request request,Site site) {
if (!inited.get()) {
init();
}
if (logger.isDebugEnabled()) {
logger.debug("push to queue " + request.getUrl());
}
if (urls.add(request.getUrl())) {
queue.add(request);
fileUrlWriter.println(request.getUrl());
}
}
@Override
public synchronized Request poll(Site site) {
if (!inited.get()) {
init();
}
fileCursorWriter.println(cursor.incrementAndGet());
return queue.poll();
}
}
package us.codecraft.spider.schedular;
import org.apache.log4j.Logger;
import us.codecraft.spider.Request;
import us.codecraft.spider.Site;
import java.util.HashSet;
import java.util.Set;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;
/**
* User: cairne
* Date: 13-4-21
* Time: 下午1:13
*/
public class QueueSchedular implements Schedular {
private Logger logger = Logger.getLogger(getClass());
private BlockingQueue<Request> queue = new LinkedBlockingQueue<Request>();
private Set<String> urls = new HashSet<String>();
@Override
public synchronized void push(Request request,Site site) {
if (logger.isDebugEnabled()){
logger.debug("push to queue "+request.getUrl());
}
if (urls.add(request.getUrl())){
queue.add(request);
}
}
@Override
public synchronized Request poll(Site site) {
return queue.poll();
}
}
package us.codecraft.spider.schedular;
import us.codecraft.spider.Request;
import us.codecraft.spider.Site;
/**
* User: cairne
* Date: 13-4-21
* Time: 下午1:12
*/
public interface Schedular {
public void push(Request request,Site site);
public Request poll(Site site);
}
package us.codecraft.spider.selector;
import org.apache.commons.collections.CollectionUtils;
import java.util.ArrayList;
import java.util.List;
/**
* User: cairne
* Date: 13-4-21
* Time: 上午7:54
*/
public class Html extends PlainText {
public Html(List<String> strings) {
super(strings);
}
public Html(String text) {
super(text);
}
@Override
public Selectable x(String xpath) {
XpathSelector xpathSelector = SelectorFactory.getInstatnce().newXpathSelector(xpath);
return select(xpathSelector,strings);
}
@Override
protected Selectable select(Selector selector, List<String> strings) {
List<String> results = new ArrayList<String>();
for (String string : strings) {
String result = selector.select(string);
if (result!=null){
results.add(result);
}
}
return new Html(results);
}
@Override
protected Selectable selectList(Selector selector, List<String> strings) {
List<String> results = new ArrayList<String>();
for (String string : strings) {
List<String> result = selector.selectList(string);
results.addAll(result);
}
return new Html(results);
}
@Override
public Selectable sc() {
SmartContentSelector smartContentSelector = SelectorFactory.getInstatnce().newSmartContentSelector();
return select(smartContentSelector,strings);
}
@Override
public Selectable a() {
XpathSelector xpathSelector = SelectorFactory.getInstatnce().newXpathSelector("//a/@href");
return select(xpathSelector,strings);
}
@Override
public Selectable as() {
XpathSelector xpathSelector = SelectorFactory.getInstatnce().newXpathSelector("//a/@href");
return selectList(xpathSelector,strings);
}
@Override
public Selectable xs(String xpath) {
XpathSelector xpathSelector = SelectorFactory.getInstatnce().newXpathSelector(xpath);
return selectList(xpathSelector, strings);
}
}
package us.codecraft.spider.selector;
import org.apache.commons.collections.CollectionUtils;
import java.util.ArrayList;
import java.util.List;
/**
* User: cairne
* Date: 13-4-21
* Time: 上午7:54
*/
public class PlainText implements Selectable {
protected List<String> strings;
public PlainText(List<String> strings) {
this.strings = strings;
}
public PlainText(String text) {
List<String> results = new ArrayList<String>();
results.add(text);
this.strings = results;
}
@Override
public Selectable x(String xpath) {
throw new UnsupportedOperationException();
}
@Override
public Selectable xs(String xpath) {
throw new UnsupportedOperationException();
}
@Override
public Selectable sc() {
throw new UnsupportedOperationException();
}
@Override
public Selectable a() {
throw new UnsupportedOperationException();
}
@Override
public Selectable as() {
throw new UnsupportedOperationException();
}
@Override
public Selectable r(String regex) {
RegexSelector regexSelector = SelectorFactory.getInstatnce().newRegexSelector(regex);
return select(regexSelector, strings);
}
@Override
public Selectable rs(String regex) {
RegexSelector regexSelector = SelectorFactory.getInstatnce().newRegexSelector(regex);
return selectList(regexSelector, strings);
}
protected Selectable select(Selector selector, List<String> strings) {
List<String> results = new ArrayList<String>();
for (String string : strings) {
String result = selector.select(string);
if (result!=null){
results.add(result);
}
}
return new PlainText(results);
}
protected Selectable selectList(Selector selector, List<String> strings) {
List<String> results = new ArrayList<String>();
for (String string : strings) {
List<String> result = selector.selectList(string);
results.addAll(result);
}
return new PlainText(results);
}
@Override
public Selectable rp(String regex, String replacement) {
ReplaceSelector replaceSelector = SelectorFactory.getInstatnce().newReplaceSelector(regex, replacement);
return select(replaceSelector, strings);
}
@Override
public List<String> toStrings() {
return strings;
}
@Override
public String toString() {
if (CollectionUtils.isNotEmpty(toStrings())) {
return toStrings().get(0);
} else {
return null;
}
}
}
package us.codecraft.spider.selector;
/**
* User: cairne
* Date: 13-4-21
* Time: 上午7:39
*/
class RegexResult {
private String[] groups;
public static final RegexResult EMPTY_RESULT = new RegexResult();
public RegexResult() {
}
public RegexResult(String[] groups) {
this.groups = groups;
}
public String get(int groupId) {
if (groups == null) {
return null;
}
return groups[groupId];
}
}
package us.codecraft.spider.selector;
import org.apache.commons.lang3.StringUtils;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.regex.PatternSyntaxException;
/**
* User: cairne
* Date: 13-4-21
* Time: 上午7:09
*/
public class RegexSelector implements Selector {
private String regexStr;
private Pattern regex;
public RegexSelector(String regexStr) {
if (StringUtils.isBlank(regexStr)){
throw new IllegalArgumentException("regex must not be empty");
}
if (!StringUtils.contains(regexStr,"(")||!StringUtils.contains(regexStr,")")){
throw new IllegalArgumentException("regex must have capture group 1");
}
this.regexStr = regexStr;
try {
regex = Pattern.compile(regexStr,Pattern.DOTALL|Pattern.CASE_INSENSITIVE);
} catch (PatternSyntaxException e) {
throw new IllegalArgumentException("invalid regex", e);
}
}
@Override
public String select(String text) {
return selectGroup(text).get(1);
}
@Override
public List<String> selectList(String text) {
List<String> strings=new ArrayList<String>();
List<RegexResult> results = selectGroupList(text);
for (RegexResult result : results) {
strings.add(result.get(1));
}
return strings;
}
public RegexResult selectGroup(String text) {
Matcher matcher = regex.matcher(text);
if (matcher.find()) {
String[] groups = new String[matcher.groupCount()+1];
for (int i = 0; i < groups.length; i++) {
groups[i] = matcher.group(i);
}
return new RegexResult(groups);
}
return RegexResult.EMPTY_RESULT;
}
public List<RegexResult> selectGroupList(String text) {
Matcher matcher = regex.matcher(text);
List<RegexResult> resultList = new ArrayList<RegexResult>();
while (matcher.find()) {
String[] groups = new String[matcher.groupCount()+1];
for (int i = 0; i < groups.length; i++) {
groups[i] = matcher.group(i);
}
resultList.add(new RegexResult(groups));
}
return resultList;
}
@Override
public String toString() {
return regexStr;
}
}
package us.codecraft.spider.selector;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.regex.PatternSyntaxException;
/**
* User: cairne
* Date: 13-4-21
* Time: 上午7:09
*/
public class ReplaceSelector implements Selector {
private String regexStr;
private String replacement;
private Pattern regex;
public ReplaceSelector(String regexStr, String replacement) {
this.regexStr = regexStr;
this.replacement = replacement;
try {
regex = Pattern.compile(regexStr);
} catch (PatternSyntaxException e) {
throw new IllegalArgumentException("invalid regex", e);
}
}
@Override
public String select(String text) {
Matcher matcher = regex.matcher(text);
return matcher.replaceAll(replacement);
}
@Override
public List<String> selectList(String text) {
throw new UnsupportedOperationException();
}
@Override
public String toString() {
return regexStr + "_" + replacement;
}
}
package us.codecraft.spider.selector;
import java.util.List;
/**
* User: cairne
* Date: 13-4-20
* Time: 下午7:51
*/
public interface Selectable {
/**
* select with xpath
*
* @param xpath
* @return new Selectable after extract
*/
public Selectable x(String xpath);
/**
* select list with xpath
*
* @param xpath
* @return new Selectable after extract
*/
public Selectable xs(String xpath);
/**
* select smart content with ReadAbility algorithm
*
* @return content
*/
public Selectable sc();
/**
* select a link
*
* @return
*/
public Selectable a();
/**
* select all links
*
* @return
*/
public Selectable as();
/**
* select with regex
*
* @param regex
* @return new Selectable after extract
*/
public Selectable r(String regex);
/**
* select list with regex
*
* @param regex
* @return new Selectable after extract
*/
public Selectable rs(String regex);
/**
* replace with regex
*
* @param regex
* @param replacement
* @return new Selectable after extract
*/
public Selectable rp(String regex, String replacement);
/**
* single string result
*
* @return single string result
*/
public String toString();
/**
* multi string result
*
* @return multi string result
*/
public List<String> toStrings();
}
package us.codecraft.spider.selector;
import java.util.List;
/**
* User: cairne
* Date: 13-4-20
* Time: 下午8:02
*/
public interface Selector {
public String select(String text);
public List<String> selectList(String text);
}
package us.codecraft.spider.selector;
import org.apache.commons.lang3.StringUtils;
import java.lang.reflect.Constructor;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
/**
* User: cairne
* Date: 13-4-21
* Time: 上午7:56
*/
public class SelectorFactory {
private Map<String, Selector> innerCache = new ConcurrentHashMap<String, Selector>();
private static final SelectorFactory INSTATNCE = new SelectorFactory();
public static SelectorFactory getInstatnce() {
return INSTATNCE;
}
public RegexSelector newRegexSelector(String regex) {
return newSelector(RegexSelector.class, regex);
}
public ReplaceSelector newReplaceSelector(String regex, String replacement) {
return newSelector(ReplaceSelector.class, regex, replacement);
}
public XpathSelector newXpathSelector(String xpath) {
return newSelector(XpathSelector.class, xpath);
}
public SmartContentSelector newSmartContentSelector(){
return newSelector(SmartContentSelector.class);
}
public <T extends Selector> T newAndCacheSelector(Class<T> clazz, String... param) {
String cacheKey = getCacheKey(RegexSelector.class, param);
if (innerCache.get(cacheKey) != null) {
return (T) innerCache.get(cacheKey);
}
T selector = newSelector(clazz, param);
if (selector != null) {
innerCache.put(cacheKey, selector);
}
return selector;
}
public <T extends Selector> T newSelector(Class<T> clazz, String... param) {
try {
if (param.length == 0) {
Constructor<T> constructor
= clazz.getConstructor();
T selector = constructor.newInstance();
return selector;
} else if (param.length == 1) {
Constructor<T> constructor
= clazz.getConstructor(String.class);
T selector = constructor.newInstance(param[0]);
return selector;
} else if (param.length == 2) {
Constructor<T> constructor
= clazz.getConstructor(String.class, String.class);
T selector = constructor.newInstance(param[0], param[1]);
return selector;
} else {
throw new UnsupportedOperationException();
}
} catch (ReflectiveOperationException e) {
throw new IllegalArgumentException("init object error", e);
}
}
private String getCacheKey(Class<?> clazz, String... param) {
return clazz.toString() + "_" + StringUtils.join(param, "_");
}
}
package us.codecraft.spider.selector;
import org.apache.log4j.Logger;
import org.htmlcleaner.HtmlCleaner;
import org.htmlcleaner.TagNode;
import java.util.*;
import java.util.concurrent.atomic.AtomicInteger;
/**
* 找到clear
* User: cairne
* Date: 13-4-21
* Time: 下午4:42
*/
public class SmartContentSelector implements Selector {
private Logger logger = Logger.getLogger(getClass());
public SmartContentSelector() {
}
@Override
public String select(String text) {
HtmlCleaner htmlCleaner = new HtmlCleaner();
TagNode tagNode = htmlCleaner.clean(text);
if (tagNode == null) {
return null;
}
TagNode[] nodes = tagNode.getElementsByName("p", true);
TagNode[] pres = tagNode.getElementsByName("pre", true);
Map<TagNode, Double> pDensityCountMap = new HashMap<TagNode, Double>();
countPdensity(nodes, pDensityCountMap);
countPdensity(pres, pDensityCountMap);
for (TagNode pre : pres) {
addCounter(pre, pDensityCountMap, 2);
}
List<Map.Entry<TagNode, Double>> sortList = new ArrayList<Map.Entry<TagNode, Double>>();
if (pDensityCountMap.size() == 0) {
return null;
}
for (Map.Entry<TagNode, Double> entry : pDensityCountMap.entrySet()) {
// if (logger.isDebugEnabled()) {
// logger.debug("p\t" + entry.getKey().getName() + "#" + entry.getKey().getAttributeByName("id") +
// "@" + entry.getKey().getAttributeByName("class") + ":" + entry.getValue());
// }
sortList.add(entry);
}
Collections.sort(sortList, new Comparator<Map.Entry<TagNode, Double>>() {
@Override
public int compare(Map.Entry<TagNode, Double> o1, Map.Entry<TagNode, Double> o2) {
Double d1 = o1.getValue();
Double d2 = o2.getValue();
return -d1.compareTo(d2);
}
});
TagNode contentNode = sortList.get(0).getKey();
if (logger.isDebugEnabled()) {
logger.debug("p\t" + contentNode.getName() + "#" + contentNode.getAttributeByName("id") +
"@" + contentNode.getAttributeByName("class"));
}
return htmlCleaner.getInnerHtml(contentNode);
}
private void addCounter(TagNode node, Map<TagNode, Double> countMap, double delta) {
Double counter = countMap.get(node);
if (counter == null) {
countMap.put(node, delta);
} else {
countMap.put(node, counter + delta);
}
}
private static final double parentWeight = 0.7;
private void countPdensity(TagNode[] nodes, Map<TagNode, Double> pDensityCountMap) {
for (TagNode node : nodes) {
if (node == null) {
continue;
}
TagNode parent = node.getParent();
double pDensity = 1;
while (parent != null) {
addCounter(parent, pDensityCountMap, pDensity);
parent = parent.getParent();
pDensity = pDensity * parentWeight;
}
}
}
private TagNode findLowestCommonParent(List<TagNode> tagNodes, int maxMargin, Map<TagNode, AtomicInteger> countMap) {
TagNode contentNode = tagNodes.get(0);
return contentNode;
}
@Override
public List<String> selectList(String text) {
throw new UnsupportedOperationException();
}
}
package us.codecraft.spider.selector;
import org.htmlcleaner.*;
import java.util.ArrayList;
import java.util.List;
/**
* User: cairne
* Date: 13-4-21
* Time: 上午9:39
*/
public class XpathSelector implements Selector {
private String xpathStr;
public XpathSelector(String xpathStr) {
this.xpathStr = xpathStr;
}
@Override
public String select(String text) {
HtmlCleaner htmlCleaner = new HtmlCleaner();
TagNode tagNode = htmlCleaner.clean(text);
if (tagNode == null) {
return null;
}
try {
Object[] objects = tagNode.evaluateXPath(xpathStr);
if (objects != null && objects.length >= 1) {
if (objects[0] instanceof TagNode) {
TagNode tagNode1 = (TagNode) objects[0];
return htmlCleaner.getInnerHtml(tagNode1);
} else {
return objects[0].toString();
}
}
} catch (XPatherException e) {
e.printStackTrace();
}
return null;
}
@Override
public List<String> selectList(String text) {
HtmlCleaner htmlCleaner = new HtmlCleaner();
TagNode tagNode = htmlCleaner.clean(text);
if (tagNode == null) {
return null;
}
List<String> results = new ArrayList<String>();
try {
Object[] objects = tagNode.evaluateXPath(xpathStr);
if (objects != null && objects.length >= 1) {
for (int i = 0; i < objects.length; i++) {
if (objects[i] instanceof TagNode) {
TagNode tagNode1 = (TagNode) objects[i];
results.add(htmlCleaner.getInnerHtml(tagNode1));
} else {
results.add(objects[i].toString());
}
}
}
} catch (XPatherException e) {
e.printStackTrace();
}
return results;
}
}
package us.codecraft.spider.utils;
import org.apache.commons.lang3.StringUtils;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* User: cairne
* Date: 13-4-21
* Time: 下午1:52
*/
public class UrlUtils {
private static Pattern relativePathPattern = Pattern.compile("^([\\.]+)/");
public static String fixRelativeUrl(String url, String refer) {
if (StringUtils.isBlank(url) || StringUtils.isBlank(refer)) {
return url;
}
if (url.startsWith("http") || url.startsWith("ftp") || url.startsWith("mailto") || url.startsWith("javascript:")) {
return url;
}
if (StringUtils.startsWith(url, "/")) {
String host = getHost(refer);
return host + url;
} else if (!StringUtils.startsWith(url, ".")) {
refer = reversePath(refer, 1);
return refer + "/" + url;
} else {
Matcher matcher = relativePathPattern.matcher(url);
if (matcher.find()) {
int reverseDepth = matcher.group(1).length();
refer = reversePath(refer, reverseDepth);
String substring = StringUtils.substring(url, matcher.end());
return refer + "/" + substring;
} else {
refer = reversePath(refer, 1);
return refer + "/" + url;
}
}
}
public static String reversePath(String url, int depth) {
int i = StringUtils.lastOrdinalIndexOf(url, "/", depth);
if (i < 10) {
url = getHost(url);
} else {
url = StringUtils.substring(url, 0, i);
}
return url;
}
public static String getHost(String url) {
String host = url;
int i = StringUtils.ordinalIndexOf(url, "/", 3);
if (i > 0) {
host = StringUtils.substring(url, 0, i);
}
return host;
}
private static Pattern patternForProtocal = Pattern.compile("[\\w]+://");
public static String removeProtocal(String url) {
return patternForProtocal.matcher(url).replaceAll("");
}
public static String getDomain(String url) {
String domain = removeProtocal(url);
int i = StringUtils.indexOf(domain, "/", 1);
if (i > 0) {
domain = StringUtils.substring(domain, 0, i);
}
return domain;
}
private static Pattern patternForHref = Pattern.compile("(<a[^<>]*href=)[\"']{0,1}([^\"']*)[\"']{0,1}", Pattern.CASE_INSENSITIVE);
public static String fixAllRelativeHrefs(String html, String url) {
StringBuilder stringBuilder = new StringBuilder();
Matcher matcher = patternForHref.matcher(html);
int lastEnd = 0;
while (matcher.find()) {
stringBuilder.append(StringUtils.substring(html, lastEnd, matcher.start()));
stringBuilder.append(matcher.group(1));
stringBuilder.append("\"" + fixRelativeUrl(matcher.group(2), url) + "\"");
lastEnd = matcher.end();
}
stringBuilder.append(StringUtils.substring(html, lastEnd));
return stringBuilder.toString();
}
}
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">
<log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/">
<appender name="stdout" class="org.apache.log4j.ConsoleAppender">
<layout class="org.apache.log4j.PatternLayout">
<param name="ConversionPattern" value="%d{yy-MM-dd HH:mm:ss,SSS} %-5p %c(%F:%L) ## %m%n" />
</layout>
</appender>
<logger name="org.springframework" additivity="false">
<level value="warn" />
<appender-ref ref="stdout" />
</logger>
<logger name="net.sf.ehcache" additivity="false">
<level value="warn" />
<appender-ref ref="stdout" />
</logger>
<root>
<level value="info" />
<appender-ref ref="stdout" />
</root>
</log4j:configuration>
package us.codecraft.spider;
import org.junit.Assert;
import org.junit.Test;
import us.codecraft.spider.selector.Html;
/**
* User: cairne
* Date: 13-4-21
* Time: 上午8:42
*/
public class HtmlTest {
@Test
public void testRegexSelector() {
Html selectable = new Html("aaaaaaab");
Assert.assertEquals("abbabbab", (selectable.r("(.*)").rp("aa(a)", "$1bb").toString()));
}
}
package us.codecraft.spider;
import org.junit.Ignore;
import org.junit.Test;
import us.codecraft.spider.pipeline.ConsolePipeline;
import us.codecraft.spider.pipeline.FilePipeline;
import us.codecraft.spider.processor.SimplePageProcessor;
import us.codecraft.spider.samples.DianpingBlogProcessor;
import us.codecraft.spider.samples.HuxiuProcessor;
import us.codecraft.spider.schedular.FileCacheQueueSchedular;
/**
* User: cairne
* Date: 13-4-20
* Time: 下午7:46
*/
public class SpiderTest {
@Test
public void testSpider() throws InterruptedException {
Spider me = Spider.me().pipeline(new FilePipeline()).processor(new HuxiuProcessor());
me.run();
}
@Test
public void testGlobalSpider(){
SimplePageProcessor pageProcessor = new SimplePageProcessor("http://2012guang.diandian.com/", "http://2012guang.diandian.com/post/*");
Spider.me().pipeline(new FilePipeline()).schedular(new FileCacheQueueSchedular(pageProcessor.getSite(),"/data/temp/spider/cache/")).
processor(pageProcessor).thread().start();
SimplePageProcessor pageProcessor2 = new SimplePageProcessor("http://lol.duowan.com/", "http://lol.duowan.com/*.html");
Spider.me().pipeline(new FilePipeline()).schedular(new FileCacheQueueSchedular(pageProcessor2.getSite(),"/data/temp/spider/cache/")).
processor(pageProcessor2).run();
Spider.me().processor(new SimplePageProcessor("http://my.oschina.net/", "http://my.oschina.net/*/blog/*")).run();
}
@Test
public void test(){
System.out.println(System.getProperty("java.io.tmpdir"));
}
@Ignore
@Test
public void languageSchema() {
/**
*
* _hrefs = rs("<a[^<>]*href=[\"']{1}(/yewu/.*?)[\"']{1}")
* title = r(""<title>(.*)</title>"")
* body = x("//dd[@class='w133']")
*
* site.domain = "sh.58.com"
* site.ua=""
* site.cookie="aa:bb"
*
*/
/**
*
*
* if (page == r('') && refer(1) == 1) {
*
* type = _refer(1)
* content = _text.t().c()
* title = x("asd@asd").r("",1)
* body[r(_currentUrl).g(1)] = body[r(_currentUrl).g(1)] + (x("").r("",1,2).c())
*
* body=body[r(_currentUrl).g(1)]
* tags[%] = (tags[%] + xs('')) . r('')
*
* _targetUrls.add('' + x('').r(''))
* _sourceUrls.add()
* _header.put("","");
* _cookie.add("asdsadasdsa");
*
*
* }
*
* _cookie.add(_cookie[''])
*
* if (page == r('') && refer(1) == 1)
* (
* _targetUrl = '' + x('') & r('')
* _sourceUrl = ''
* )
*
*/
/**
* <condition></>
* <selector>
* <fields>
*
* <type>
* <selector></selector>
* <selector></selector>
* </type>
* </>
* </>
*/
/**
*
* if (model.url('') && model.refer(1) == 1)
* (
*
* model.set(type, model.refer(1))
* content = t(_html) > c()
* title = x(_html, 'asd@asd') > r('',1)
* body[r(_currentUrl).g(1)] = body[r(_currentUrl).g(1)] + (x('') > r('',1,2) > c()) | x('')
* tags[%] = tags + xs('') > r('')
* model.setTargetUrl();
*
* _targetUrl = '' + x('') & r('')
* _sourceUrl = ''
* )
*
* _cookie.add(_cookie[''])
*
* if (page == r('') && refer(1) == 1)
* (
* _targetUrl = '' + x('') & r('')
* _sourceUrl = ''
* )
*
*/
}
}
package us.codecraft.spider.samples;
import us.codecraft.spider.Site;
import us.codecraft.spider.Page;
import us.codecraft.spider.processor.PageProcessor;
import java.util.List;
/**
* User: cairne
* Date: 13-4-21
* Time: 下午8:08
*/
public class DiandianBlogProcessor implements PageProcessor {
@Override
public void process(Page page) {
//http://progressdaily.diandian.com/post/2013-01-24/40046867275
List<String> requests = page.getHtml().rs("<a[^<>]*href=[\"']{1}(http://17dujingdian\\.com/post/[^#]*?)[\"']{1}").toStrings();
page.addTargetRequests(requests);
page.putField("title",page.getHtml().x("//div[@id='content']//h2/a"));
page.putField("content",page.getHtml().sc());
}
@Override
public Site getSite() {
return Site.me().setDomain("www.diandian.com").setStartUrl("http://17dujingdian.com/").
setUserAgent("Mozilla/5.0 (Macintosh; Intel Mac OS X 10_7_2) AppleWebKit/537.31 (KHTML, like Gecko) Chrome/26.0.1410.65 Safari/537.31");
}
}
package us.codecraft.spider.samples;
import us.codecraft.spider.Site;
import us.codecraft.spider.Page;
import us.codecraft.spider.processor.PageProcessor;
import java.util.List;
/**
* User: cairne
* Date: 13-4-21
* Time: 下午8:08
*/
public class DianpingBlogProcessor implements PageProcessor {
@Override
public void process(Page page) {
//http://progressdaily.diandian.com/post/2013-01-24/40046867275
List<String> requests = page.getHtml().rs("<a[^<>]*href=[\"']{1}(/shop/.*?)[\"']{1}").toStrings();
page.addTargetRequests(requests);
requests = page.getHtml().rs("<a[^<>]*href=[\"']{1}(/search/category/.*?)[\"']{1}").toStrings();
page.addTargetRequests(requests);
if (page.getUrl().toString().contains("shop")){
page.putField("title", page.getHtml().x("//h1[@class='shop-title']"));
page.putField("content", page.getHtml().sc());
}
}
@Override
public Site getSite() {
return Site.me().setDomain("www.dianping.com").setStartUrl("http://www.dianping.com/").
setUserAgent("Mozilla/5.0 (Macintosh; Intel Mac OS X 10_7_2) AppleWebKit/537.31 (KHTML, like Gecko) Chrome/26.0.1410.65 Safari/537.31");
}
}
package us.codecraft.spider.samples;
import us.codecraft.spider.Site;
import us.codecraft.spider.Page;
import us.codecraft.spider.processor.PageProcessor;
import java.util.List;
/**
* User: cairne
* Date: 13-4-21
* Time: 下午1:48
*/
public class F58PageProcesser implements PageProcessor {
@Override
public void process(Page page) {
List<String> strings = page.getHtml().rs("<a[^<>]*href=[\"']{1}(/yewu/.*?)[\"']{1}").toStrings();
page.addTargetRequests(strings);
page.putField("title",page.getHtml().r("<title>(.*)</title>"));
page.putField("body",page.getHtml().x("//dd[@class='w133']"));
}
@Override
public Site getSite() {
return Site.me().setDomain("sh.58.com").setStartUrl("http://sh.58.com/"); //To change body of implemented methods use File | Settings | File Templates.
}
}
package us.codecraft.spider.samples;
import us.codecraft.spider.Site;
import us.codecraft.spider.Page;
import us.codecraft.spider.processor.PageProcessor;
import java.util.List;
/**
* User: cairne
* Date: 13-4-21
* Time: 下午8:08
*/
public class HuxiuProcessor implements PageProcessor {
@Override
public void process(Page page) {
//http://progressdaily.diandian.com/post/2013-01-24/40046867275
List<String> requests = page.getHtml().rs("<a[^<>\"']*href=[\"']{1}([/]{0,1}article[^<>#\"']*?)[\"']{1}").toStrings();
page.addTargetRequests(requests);
page.putField("title",page.getHtml().x("//div[@class='neirong']//h1[@class='ph xs5']"));
page.putField("content",page.getHtml().sc());
}
@Override
public Site getSite() {
return Site.me().setDomain("www.huxiu.com").setStartUrl("http://www.huxiu.com/").
setUserAgent("Mozilla/5.0 (Macintosh; Intel Mac OS X 10_7_2) AppleWebKit/537.31 (KHTML, like Gecko) Chrome/26.0.1410.65 Safari/537.31");
}
}
package us.codecraft.spider.samples;
import us.codecraft.spider.Site;
import us.codecraft.spider.Page;
import us.codecraft.spider.processor.PageProcessor;
import java.util.List;
/**
* User: cairne
* Date: 13-4-21
* Time: 下午8:08
*/
public class NjuBBSProcessor implements PageProcessor {
@Override
public void process(Page page) {
List<String> requests = page.getHtml().rs("<a[^<>]*href=(bbstcon\\?board=Pictures&file=[^>]*)").toStrings();
page.addTargetRequests(requests);
page.putField("title",page.getHtml().x("//div[@id='content']//h2/a"));
page.putField("content",page.getHtml().sc());
}
@Override
public Site getSite() {
return Site.me().setDomain("bbs.nju.edu.cn").setStartUrl("http://bbs.nju.edu.cn/board?board=Pictures").
setUserAgent("Mozilla/5.0 (Macintosh; Intel Mac OS X 10_7_2) AppleWebKit/537.31 (KHTML, like Gecko) Chrome/26.0.1410.65 Safari/537.31");
}
}
package us.codecraft.spider.samples;
import us.codecraft.spider.Site;
import us.codecraft.spider.Page;
import us.codecraft.spider.processor.PageProcessor;
import java.util.List;
/**
* User: cairne
* Date: 13-4-21
* Time: 下午1:48
*/
public class OschinaBlogPageProcesser implements PageProcessor {
@Override
public void process(Page page) {
List<String> strings = page.getHtml().as().r("(http://my\\.oschina\\.net)").toStrings();
page.addTargetRequests(strings);
page.putField("title", page.getHtml().xs("//div[@class='BlogEntity']/div[@class='BlogTitle']/h1"));
page.putField("content", page.getHtml().sc());
page.putField("author", page.getUrl().r("my\\.oschina\\.net/(\\w+)/blog/\\d+"));
}
@Override
public Site getSite() {
return Site.me().setDomain("my.oschina.net").setStartUrl("http://www.oschina.net/").
setUserAgent("Mozilla/5.0 (Macintosh; Intel Mac OS X 10_7_2) AppleWebKit/537.31 (KHTML, like Gecko) Chrome/26.0.1410.65 Safari/537.31");
}
}
package us.codecraft.spider.samples;
import us.codecraft.spider.Site;
import us.codecraft.spider.Page;
import us.codecraft.spider.processor.PageProcessor;
import java.util.List;
/**
* User: cairne
* Date: 13-4-21
* Time: 下午1:48
*/
public class OschinaPageProcesser implements PageProcessor {
@Override
public void process(Page page) {
List<String> strings = page.getHtml().rs("<a[^<>]*href=[\"']{1}(http://www\\.oschina\\.net/question/[\\w]+)[\"']{1}").toStrings();
page.addTargetRequests(strings);
page.putField("title", page.getHtml().x("//div[@class='QTitle']/h1/a"));
page.putField("content", page.getHtml().xs("//div[@class='Question']//div[@class='Content']/div[@class='detail']"));
}
@Override
public Site getSite() {
return Site.me().setDomain("www.oschina.net").setStartUrl("http://www.oschina.net/").
setUserAgent("Mozilla/5.0 (Macintosh; Intel Mac OS X 10_7_2) AppleWebKit/537.31 (KHTML, like Gecko) Chrome/26.0.1410.65 Safari/537.31");
}
}
package us.codecraft.spider.samples;
import us.codecraft.spider.Site;
import us.codecraft.spider.Page;
import us.codecraft.spider.processor.PageProcessor;
/**
* User: cairne
* Date: 13-4-21
* Time: 下午1:48
*/
public class SinaBlogProcesser implements PageProcessor {
@Override
public void process(Page page) {
page.addTargetRequests(page.getHtml().rs("<a[^<>]*href=[\"']{1}(http://blog\\.sina\\.com\\.cn/s/blog_.*?)[\"']{1}").toStrings());
page.putField("title", page.getHtml().x("//div[@class='articalTitle']/h2"));
page.putField("body",page.getHtml().sc());
//x("//dd[@class='w133']")
page.putField("date",page.getHtml().x("//div[@id='articlebody']//span[@class='time SG_txtc']").r("\\((.*)\\)"));
page.putField("tags",page.getHtml().xs("//td[@class='blog_tag']/h3/a"));
}
@Override
public Site getSite() {
return Site.me().setDomain("blog.sina.com.cn").setStartUrl("http://blog.sina.com.cn/").
setUserAgent("Mozilla/5.0 (Macintosh; Intel Mac OS X 10_7_2) AppleWebKit/537.31 (KHTML, like Gecko) Chrome/26.0.1410.65 Safari/537.31");
}
}
package us.codecraft.spider.samples;
import us.codecraft.spider.Site;
import us.codecraft.spider.Page;
import us.codecraft.spider.processor.PageProcessor;
import java.util.List;
/**
* User: cairne
* Date: 13-4-21
* Time: 下午1:48
*/
public class TianyaPageProcesser implements PageProcessor {
@Override
public void process(Page page) {
List<String> strings = page.getHtml().rs("<a[^<>]*href=[\"']{1}(/post-free.*?\\.shtml)[\"']{1}").toStrings();
page.addTargetRequests(strings);
page.putField("title", page.getHtml().x("//div[@id='post_head']//span[@class='s_title']//b"));
page.putField("body",page.getHtml().sc());
}
@Override
public Site getSite() {
return Site.me().setDomain("http://bbs.tianya.cn/").setStartUrl("http://bbs.tianya.cn/"); //To change body of implemented methods use File | Settings | File Templates.
}
}
package us.codecraft.spider.selector;
import org.htmlcleaner.CleanerProperties;
import org.htmlcleaner.HtmlCleaner;
import org.htmlcleaner.TagNode;
import org.junit.Test;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
/**
* User: cairne
* Date: 13-4-21
* Time: 上午10:35
*/
public class HtmlCleanerTest {
@Test
public void test() throws IOException {
HtmlCleaner htmlCleaner = new HtmlCleaner();
CleanerProperties props = htmlCleaner.getProperties();
TagNode node = htmlCleaner.clean(new URL("http://www.huanqiu.com"),"UTF-8");
System.out.println(node.getAllElementsList(true));
System.out.println(node);
}
}
package us.codecraft.spider.selector;
import junit.framework.Assert;
import org.junit.Test;
/**
* User: cairne
* Date: 13-4-21
* Time: 上午7:13
*/
public class RegexSelectorTest {
@Test
public void testInvalidRegex() {
String regex = "\\d+(";
try {
new RegexSelector(regex);
Assert.assertNotNull(regex);
} catch (Exception e) {
}
}
}
This source diff could not be displayed because it is too large. You can view the blob instead.
This diff is collapsed.
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">
<log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/">
<appender name="stdout" class="org.apache.log4j.ConsoleAppender">
<layout class="org.apache.log4j.PatternLayout">
<param name="ConversionPattern" value="%d{yy-MM-dd HH:mm:ss,SSS} %-5p %c(%F:%L) ## %m%n" />
</layout>
</appender>
<logger name="org.springframework" additivity="false">
<level value="warn" />
<appender-ref ref="stdout" />
</logger>
<logger name="org.apache" additivity="false">
<level value="warn" />
<appender-ref ref="stdout" />
</logger>
<logger name="net.sf.ehcache" additivity="false">
<level value="warn" />
<appender-ref ref="stdout" />
</logger>
<root>
<level value="debug" />
<appender-ref ref="stdout" />
</root>
</log4j:configuration>
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment