用過(guò)老版本UC看小說(shuō)的同學(xué)都知道,當(dāng)年版權(quán)問(wèn)題比較松懈,我們可以再UC搜索不同來(lái)源的小說(shuō),并且閱讀,那么它是怎么做的呢?下面讓我們自己實(shí)現(xiàn)一個(gè)小說(shuō)線(xiàn)上采集閱讀。(說(shuō)明:僅用于技術(shù)學(xué)習(xí)、研究)
看小說(shuō)時(shí),最煩的就是有各種廣告,這些廣告有些是站長(zhǎng)放上去的盈利手段,有些是被人惡意注入。在我的上一篇博客中實(shí)現(xiàn)了小說(shuō)采集并保存到本地TXT文件 HttpClients+Jsoup抓取筆趣閣小說(shuō),并保存到本地TXT文件,這樣我們就可以導(dǎo)入手機(jī)用手機(jī)閱讀軟件看小說(shuō);那么我們這里實(shí)現(xiàn)一個(gè)可以在線(xiàn)看小說(shuō)。
首頁(yè):
頁(yè)面很純凈,目前有三種來(lái)源
搜索結(jié)果頁(yè):
三個(gè)不同的來(lái)源,分頁(yè)用的是layui的laypage,邏輯分頁(yè)。(筆趣閣的搜索結(jié)果界面沒(méi)有書(shū)本的圖片)
翻頁(yè)效果:
縱橫網(wǎng)連簡(jiǎn)介等都幫我們分詞,搞得數(shù)據(jù)量太大,速度太慢:books.size() < 888
書(shū)本詳情頁(yè):
小說(shuō)閱讀頁(yè):
上、下一章:
項(xiàng)目是springboot項(xiàng)目,原理非常簡(jiǎn)單,就是用httpclient構(gòu)造一個(gè)請(qǐng)求頭去請(qǐng)求對(duì)應(yīng)的來(lái)源鏈接,用jsoup去解析響應(yīng)回來(lái)的response,
通過(guò)jsoup的選擇器去找到我們想要的數(shù)據(jù),存入實(shí)體,放到ModelAndView里面,前端頁(yè)面用thymeleaf去取值、遍歷數(shù)據(jù)。
但是有一些書(shū)是要會(huì)員才能看,這種情況下我們需要做模擬登陸才能繼續(xù)采集,這里只是一個(gè)簡(jiǎn)單的采集,就不做模擬登陸了。
采集過(guò)程中碰到的問(wèn)題:
1、起點(diǎn)中文網(wǎng)采集書(shū)本集合時(shí),想要的數(shù)據(jù)不在頁(yè)面源碼里面
起點(diǎn)中文網(wǎng)很機(jī)智,他在html代碼了沒(méi)有直接展示page分頁(yè)信息的鏈接
可以看到,httpClient請(qǐng)求回來(lái)的response里分頁(yè)信息標(biāo)簽里面是空的,但用瀏覽器去請(qǐng)求里面有信息
這是因?yàn)閔ttpClient去模擬我們的瀏覽器訪(fǎng)問(wèn)某個(gè)鏈接,直接響應(yīng)回這個(gè)鏈接對(duì)應(yīng)的內(nèi)容,并不會(huì)去幫我們觸發(fā)其他的ajax,而瀏覽器回去解析響應(yīng)回來(lái)的html,當(dāng)碰到img、script、link等標(biāo)簽它會(huì)幫我們?nèi)jax請(qǐng)求對(duì)應(yīng)的資源。
由此推測(cè),page相關(guān)的信息,起點(diǎn)中文網(wǎng)是在js代碼里面去獲取并追加,最后通過(guò)network找到它的一些蛛絲馬跡
既然他沒(méi)有寫(xiě)在html里,那我們就自己去創(chuàng)建連接,可以看到html上有當(dāng)前頁(yè)跟最大頁(yè)數(shù)
完美
2、筆趣閣查看書(shū)本詳情,圖片防盜鏈
筆趣閣有一個(gè)圖片防盜,我們?cè)谧约旱膆tml引入圖片路徑時(shí),但當(dāng)我們把鏈接用瀏覽器訪(fǎng)問(wèn)時(shí)是可以的
對(duì)比一下兩邊的請(qǐng)求頭
首先我們要知道什么事圖片防盜鏈,猛戳這里 -->:圖片防盜鏈原理及應(yīng)對(duì)方法 ;我們直接用大佬的反防盜鏈方法,并且針對(duì)我們的項(xiàng)目改造一下:
<div id="bookImg"></div>
/**
* 反防盜鏈
*/
function showImg(parentObj, url) {
//來(lái)一個(gè)隨機(jī)數(shù)
var frameid='frameimg' + Math.random();
//放在(父頁(yè)面)window里面 iframe的script標(biāo)簽里面綁定了window.onload,作用:設(shè)置iframe的高度、寬度 <script>window.onload=function() { parent.document.getElementById(\'' + frameid + '\').height=document.getElementById(\'img\').height+\'px\'; }<' + '/script>
window.img='<img src=\'' + url + '?' + Math.random() + '\'/>';
//iframe調(diào)用parent.img
$(parentObj).append('<iframe id="' + frameid + '" src="javascript:parent.img;" frameBorder="0" scrolling="no"></iframe>');
}
showImg($("#bookImg"), book.img);
效果最終:
3、采集書(shū)本詳情時(shí),起點(diǎn)網(wǎng)的目錄并沒(méi)有在html里
起點(diǎn)網(wǎng)的目錄并沒(méi)有在html里,也不是在另一個(gè)鏈接里
通過(guò)瀏覽器頁(yè)面Elements的Break on打斷點(diǎn)
查看調(diào)用棧發(fā)現(xiàn),它在js ajax請(qǐng)求數(shù)據(jù),進(jìn)行tab切換,就連總共有多少章,它都是頁(yè)面加載出來(lái)之后ajax請(qǐng)求回來(lái)的
看一下他的請(qǐng)求頭跟參數(shù)
只要我們弄懂_csrfToken參數(shù)就可以構(gòu)造一個(gè)get請(qǐng)求
https://book.qidian.com/ajax/book/category?_csrfToken=LosgUIe29G7LV04gdutbSqzKRb9XxoPyqtWBQ3hU&bookId=1209977
通過(guò)瀏覽器查看可知,第一章對(duì)應(yīng)的鏈接:https://read.qidian.com/chapter/2R9G_ziBVg41/MyEcwtk5i8Iex0RJOkJclQ2
這個(gè)就是我們想要的
https://read.qidian.com/chapter/ + cU章節(jié)鏈接
cN章節(jié)名稱(chēng)
_csrfToken是cookie,而且多次刷新都不變,大膽猜測(cè):起點(diǎn)為我們生成cookie并且攜帶請(qǐng)求ajax,攜帶與起點(diǎn)給我們的cookie不一致的時(shí)候返回失敗,
我們每次調(diào)用gather,都是一次新的httpclient對(duì)象,每次既然如此,那我們就先獲取cookie,在用同一個(gè)httpclient去請(qǐng)求數(shù)據(jù)即可 (詳情代碼已經(jīng)貼出來(lái),在BookHandler_qidian.book_details_qidian里面)
最終我們獲得了返回值,是一個(gè)json
同樣的,大部分邏輯都寫(xiě)在注釋里面,相信大家都看得懂:
maven引包:
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
<version>4.5.4</version>
</dependency>
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpcore</artifactId>
<version>4.4.9</version>
</dependency>
<dependency>
<groupId>org.jsoup</groupId>
<artifactId>jsoup</artifactId>
<version>1.11.3</version>
</dependency>
<dependency>
<groupId>net.sf.json-lib</groupId>
<artifactId>json-lib</artifactId>
<version>2.4</version>
<classifier>jdk15</classifier>
</dependency>
書(shū)實(shí)體類(lèi):
/**
* 書(shū)對(duì)象
*/
@Data
public class Book {
/**
* 鏈接
*/
private String bookUrl;
/**
* 書(shū)名
*/
private String bookName;
/**
* 作者
*/
private String author;
/**
* 簡(jiǎn)介
*/
private String synopsis;
/**
* 圖片
*/
private String img;
/**
* 章節(jié)目錄 chapterName、url
*/
private List<Map<String,String>> chapters;
/**
* 狀態(tài)
*/
private String status;
/**
* 類(lèi)型
*/
private String type;
/**
* 更新時(shí)間
*/
private String updateDate;
/**
* 第一章
*/
private String firstChapter;
/**
* 第一章鏈接
*/
private String firstChapterUrl;
/**
* 上一章節(jié)
*/
private String prevChapter;
/**
* 上一章節(jié)鏈接
*/
private String prevChapterUrl;
/**
* 當(dāng)前章節(jié)名稱(chēng)
*/
private String nowChapter;
/**
* 當(dāng)前章節(jié)內(nèi)容
*/
private String nowChapterValue;
/**
* 當(dāng)前章節(jié)鏈接
*/
private String nowChapterUrl;
/**
* 下一章節(jié)
*/
private String nextChapter;
/**
* 下一章節(jié)鏈接
*/
private String nextChapterUrl;
/**
* 最新章節(jié)
*/
private String latestChapter;
/**
* 最新章節(jié)鏈接
*/
private String latestChapterUrl;
/**
* 大小
*/
private String magnitude;
/**
* 來(lái)源
*/
private Map<String,String> source;
private String sourceKey;
}
小工具類(lèi):
/**
* 小工具類(lèi)
*/
public class BookUtil {
/**
* 自動(dòng)注入?yún)?shù)
* 例如:
*
* @param src http://search.zongheng.com/s?keyword=#1&pageNo=#2&sort=* @param params "斗破蒼穹","1"
* @return http://search.zongheng.com/s?keyword=斗破蒼穹&pageNo=1&sort=*/
public static String insertParams(String src, String... params) {
int i=1;
for (String param : params) {
src=src.replaceAll("#" + i, param);
i++;
}
return src;
}
/**
* 采集當(dāng)前url完整response實(shí)體.toString()
*
* @param url url
* @return response實(shí)體.toString()
*/
public static String gather(String url, String refererUrl) {
String result=null;
try {
//創(chuàng)建httpclient對(duì)象 (這里設(shè)置成全局變量,相對(duì)于同一個(gè)請(qǐng)求session、cookie會(huì)跟著攜帶過(guò)去)
CloseableHttpClient httpClient=HttpClients.createDefault();
//創(chuàng)建get方式請(qǐng)求對(duì)象
HttpGet httpGet=new HttpGet(url);
httpGet.addHeader("Content-type", "application/json");
//包裝一下
httpGet.addHeader("User-Agent", "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.100 Safari/537.36");
httpGet.addHeader("Referer", refererUrl);
httpGet.addHeader("Connection", "keep-alive");
//通過(guò)請(qǐng)求對(duì)象獲取響應(yīng)對(duì)象
CloseableHttpResponse response=httpClient.execute(httpGet);
//獲取結(jié)果實(shí)體
if (response.getStatusLine().getStatusCode()==HttpStatus.SC_OK) {
result=EntityUtils.toString(response.getEntity(), "GBK");
}
//釋放鏈接
response.close();
}
//這里還可以捕獲超時(shí)異常,重新連接抓取
catch (Exception e) {
result=null;
System.err.println("采集操作出錯(cuò)");
e.printStackTrace();
}
return result;
}
}
Controller層:
/**
* Book Controller層
*/
@RestController
@RequestMapping("book")
public class BookContrller {
/**
* 來(lái)源集合
*/
private static Map<String, Map<String, String>> source=new HashMap<>();
static {
//筆趣閣
source.put("biquge", BookHandler_biquge.biquge);
//縱橫中文網(wǎng)
source.put("zongheng", BookHandler_zongheng.zongheng);
//起點(diǎn)中文網(wǎng)
source.put("qidian", BookHandler_qidian.qidian);
}
/**
* 訪(fǎng)問(wèn)首頁(yè)
*/
@GetMapping("/index")
public ModelAndView index() {
return new ModelAndView("book_index.html");
}
/**
* 搜索書(shū)名
*/
@GetMapping("/search")
public ModelAndView search(Book book) {
//結(jié)果集
ArrayList<Book> books=new ArrayList<>();
//關(guān)鍵字
String keyWord=book.getBookName();
//來(lái)源
String sourceKey=book.getSourceKey();
//獲取來(lái)源詳情
Map<String, String> src=source.get(sourceKey);
// 編碼
try {
keyWord=URLEncoder.encode(keyWord, src.get("UrlEncode"));
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
//searchUrl
src.put("searchUrl", BookUtil.insertParams(src.get("searchUrl"), keyWord, "1"));
//調(diào)用不同的方法
switch (sourceKey) {
case "biquge":
BookHandler_biquge.book_search_biquge(books, src, keyWord);
break;
case "zongheng":
BookHandler_zongheng.book_search_zongheng(books, src, keyWord);
break;
case "qidian":
BookHandler_qidian.book_search_qidian(books, src, keyWord);
break;
default:
//默認(rèn)所有都查
BookHandler_biquge.book_search_biquge(books, src, keyWord);
BookHandler_zongheng.book_search_zongheng(books, src, keyWord);
BookHandler_qidian.book_search_qidian(books, src, keyWord);
break;
}
System.out.println(books.size());
ModelAndView modelAndView=new ModelAndView("book_list.html", "books", books);
try {
modelAndView.addObject("keyWord", URLDecoder.decode(keyWord, src.get("UrlEncode")));
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
modelAndView.addObject("sourceKey", sourceKey);
return modelAndView;
}
/**
* 訪(fǎng)問(wèn)書(shū)本詳情
*/
@GetMapping("/details")
public ModelAndView details(String sourceKey,String bookUrl,String searchUrl) {
Map<String, String> src=source.get(sourceKey);
src.put("searchUrl",searchUrl);
Book book=new Book();
//調(diào)用不同的方法
switch (sourceKey) {
case "biquge":
book=BookHandler_biquge.book_details_biquge(src, bookUrl);
break;
case "zongheng":
book=BookHandler_zongheng.book_details_zongheng(src, bookUrl);
break;
case "qidian":
book=BookHandler_qidian.book_details_qidian(src, bookUrl);
break;
default:
break;
}
return new ModelAndView("book_details.html", "book", book);
}
/**
* 訪(fǎng)問(wèn)書(shū)本章節(jié)
*/
@GetMapping("/read")
public ModelAndView read(String sourceKey,String chapterUrl,String refererUrl) {
Map<String, String> src=source.get(sourceKey);
Book book=new Book();
//調(diào)用不同的方法
switch (sourceKey) {
case "biquge":
book=BookHandler_biquge.book_read_biquge(src, chapterUrl,refererUrl);
break;
case "zongheng":
book=BookHandler_zongheng.book_read_zongheng(src, chapterUrl,refererUrl);
break;
case "qidian":
book=BookHandler_qidian.book_read_qidian(src, chapterUrl,refererUrl);
break;
default:
break;
}
return new ModelAndView("book_read.html", "book", book);
}
}
三個(gè)不同來(lái)源的Handler處理器,每個(gè)來(lái)源都有不同的采集規(guī)則:
BookHandler_biquge
/**
* 筆趣閣采集規(guī)則
*/
public class BookHandler_biquge {
/**
* 來(lái)源信息
*/
public static HashMap<String, String> biquge=new HashMap<>();
static {
//筆趣閣
biquge.put("name", "筆趣閣");
biquge.put("key", "biquge");
biquge.put("baseUrl", "http://www.biquge.com.tw");
biquge.put("baseSearchUrl", "http://www.biquge.com.tw/modules/article/soshu.php");
biquge.put("UrlEncode", "GB2312");
biquge.put("searchUrl", "http://www.biquge.com.tw/modules/article/soshu.php?searchkey=+#1&page=#2");
}
/**
* 獲取search list 筆趣閣采集規(guī)則
*
* @param books 結(jié)果集合
* @param src 源目標(biāo)
* @param keyWord 關(guān)鍵字
*/
public static void book_search_biquge(ArrayList<Book> books, Map<String, String> src, String keyWord) {
//采集術(shù)
String html=BookUtil.gather(src.get("searchUrl"), src.get("baseUrl"));
try {
//解析html格式的字符串成一個(gè)Document
Document doc=Jsoup.parse(html);
//當(dāng)前頁(yè)集合
Elements resultList=doc.select("table.grid tr#nr");
for (Element result : resultList) {
Book book=new Book();
//書(shū)本鏈接
book.setBookUrl(result.child(0).select("a").attr("href"));
//書(shū)名
book.setBookName(result.child(0).select("a").text());
//作者
book.setAuthor(result.child(2).text());
//更新時(shí)間
book.setUpdateDate(result.child(4).text());
//最新章節(jié)
book.setLatestChapter(result.child(1).select("a").text());
book.setLatestChapterUrl(result.child(1).select("a").attr("href"));
//狀態(tài)
book.setStatus(result.child(5).text());
//大小
book.setMagnitude(result.child(3).text());
//來(lái)源
book.setSource(src);
books.add(book);
}
//下一頁(yè)
Elements searchNext=doc.select("div.pages > a.ngroup");
String href=searchNext.attr("href");
if (!StringUtils.isEmpty(href)) {
src.put("baseUrl", src.get("searchUrl"));
src.put("searchUrl", href.contains("http") ? href : (src.get("baseSearchUrl") + href));
book_search_biquge(books, src, keyWord);
}
} catch (Exception e) {
System.err.println("采集數(shù)據(jù)操作出錯(cuò)");
e.printStackTrace();
}
}
/**
* 獲取書(shū)本詳情 筆趣閣采集規(guī)則
* @param src 源目標(biāo)
* @param bookUrl 書(shū)本鏈接
* @return Book對(duì)象
*/
public static Book book_details_biquge(Map<String, String> src, String bookUrl) {
Book book=new Book();
//采集術(shù)
String html=BookUtil.gather(bookUrl, src.get("searchUrl"));
try {
//解析html格式的字符串成一個(gè)Document
Document doc=Jsoup.parse(html);
//書(shū)本鏈接
book.setBookUrl(doc.select("meta[property=og:url]").attr("content"));
//圖片
book.setImg(doc.select("meta[property=og:image]").attr("content"));
//書(shū)名
book.setBookName(doc.select("div#info > h1").text());
//作者
book.setAuthor(doc.select("meta[property=og:novel:author]").attr("content"));
//更新時(shí)間
book.setUpdateDate(doc.select("meta[property=og:novel:update_time]").attr("content"));
//最新章節(jié)
book.setLatestChapter(doc.select("meta[property=og:novel:latest_chapter_name]").attr("content"));
book.setLatestChapterUrl(doc.select("meta[property=og:novel:latest_chapter_url]").attr("content"));
//類(lèi)型
book.setType(doc.select("meta[property=og:novel:category]").attr("content"));
//簡(jiǎn)介
book.setSynopsis(doc.select("meta[property=og:description]").attr("content"));
//狀態(tài)
book.setStatus(doc.select("meta[property=og:novel:status]").attr("content"));
//章節(jié)目錄
ArrayList<Map<String, String>> chapters=new ArrayList<>();
for (Element result : doc.select("div#list dd")) {
HashMap<String, String> map=new HashMap<>();
map.put("chapterName", result.select("a").text());
map.put("url", result.select("a").attr("href"));
chapters.add(map);
}
book.setChapters(chapters);
//來(lái)源
book.setSource(src);
} catch (Exception e) {
System.err.println("采集數(shù)據(jù)操作出錯(cuò)");
e.printStackTrace();
}
return book;
}
/**
* 得到當(dāng)前章節(jié)名以及完整內(nèi)容跟上、下一章的鏈接地址 筆趣閣采集規(guī)則
* @param src 源目標(biāo)
* @param chapterUrl 當(dāng)前章節(jié)鏈接
* @param refererUrl 來(lái)源鏈接
* @return Book對(duì)象
*/
public static Book book_read_biquge(Map<String, String> src,String chapterUrl,String refererUrl) {
Book book=new Book();
//當(dāng)前章節(jié)鏈接
book.setNowChapterUrl(chapterUrl.contains("http") ? chapterUrl : (src.get("baseUrl") + chapterUrl));
//采集術(shù)
String html=BookUtil.gather(book.getNowChapterUrl(), refererUrl);
try {
//解析html格式的字符串成一個(gè)Document
Document doc=Jsoup.parse(html);
//當(dāng)前章節(jié)名稱(chēng)
book.setNowChapter(doc.select("div.box_con > div.bookname > h1").text());
//刪除圖片廣告
doc.select("div.box_con > div#content img").remove();
//當(dāng)前章節(jié)內(nèi)容
book.setNowChapterValue(doc.select("div.box_con > div#content").outerHtml());
//上、下一章
book.setPrevChapter(doc.select("div.bottem2 a:matches((?i)下一章)").text());
book.setPrevChapterUrl(doc.select("div.bottem2 a:matches((?i)下一章)").attr("href"));
book.setNextChapter(doc.select("div.bottem2 a:matches((?i)上一章)").text());
book.setNextChapterUrl(doc.select("div.bottem2 a:matches((?i)上一章)").attr("href"));
//來(lái)源
book.setSource(src);
} catch (Exception e) {
System.err.println("采集數(shù)據(jù)操作出錯(cuò)");
e.printStackTrace();
}
return book;
}
}
BookHandler_zongheng
/**
* 縱橫中文網(wǎng)采集規(guī)則
*/
public class BookHandler_zongheng {
/**
* 來(lái)源信息
*/
public static HashMap<String, String> zongheng=new HashMap<>();
static {
//縱橫中文網(wǎng)
zongheng.put("name", "縱橫中文網(wǎng)");
zongheng.put("key", "zongheng");
zongheng.put("baseUrl", "http://www.zongheng.com");
zongheng.put("baseSearchUrl", "http://search.zongheng.com/s");
zongheng.put("UrlEncode", "UTF-8");
zongheng.put("searchUrl", "http://search.zongheng.com/s?keyword=#1&pageNo=#2&sort=");
}
/**
* 獲取search list 縱橫中文網(wǎng)采集規(guī)則
*
* @param books 結(jié)果集合
* @param src 源目標(biāo)
* @param keyWord 關(guān)鍵字
*/
public static void book_search_zongheng(ArrayList<Book> books, Map<String, String> src, String keyWord) {
//采集術(shù)
String html=BookUtil.gather(src.get("searchUrl"), src.get("baseUrl"));
try {
//解析html格式的字符串成一個(gè)Document
Document doc=Jsoup.parse(html);
//當(dāng)前頁(yè)集合
Elements resultList=doc.select("div.search-tab > div.search-result-list");
for (Element result : resultList) {
Book book=new Book();
//書(shū)本鏈接
book.setBookUrl(result.select("div.imgbox a").attr("href"));
//圖片
book.setImg(result.select("div.imgbox img").attr("src"));
//書(shū)名
book.setBookName(result.select("h2.tit").text());
//作者
book.setAuthor(result.select("div.bookinfo > a").first().text());
//類(lèi)型
book.setType(result.select("div.bookinfo > a").last().text());
//簡(jiǎn)介
book.setSynopsis(result.select("p").text());
//狀態(tài)
book.setStatus(result.select("div.bookinfo > span").first().text());
//大小
book.setMagnitude(result.select("div.bookinfo > span").last().text());
//來(lái)源
book.setSource(src);
books.add(book);
}
//下一頁(yè)
Elements searchNext=doc.select("div.search_d_pagesize > a.search_d_next");
String href=searchNext.attr("href");
//最多只要888本,不然太慢了
if (books.size() < 888 && !StringUtils.isEmpty(href)) {
src.put("baseUrl", src.get("searchUrl"));
src.put("searchUrl", href.contains("http") ? href : (src.get("baseSearchUrl") + href));
book_search_zongheng(books, src, keyWord);
}
} catch (Exception e) {
System.err.println("采集數(shù)據(jù)操作出錯(cuò)");
e.printStackTrace();
}
}
/**
* 獲取書(shū)本詳情 縱橫中文網(wǎng)采集規(guī)則
* @param src 源目標(biāo)
* @param bookUrl 書(shū)本鏈接
* @return Book對(duì)象
*/
public static Book book_details_zongheng(Map<String, String> src, String bookUrl) {
Book book=new Book();
//采集術(shù)
String html=BookUtil.gather(bookUrl, src.get("searchUrl"));
try {
//解析html格式的字符串成一個(gè)Document
Document doc=Jsoup.parse(html);
//書(shū)本鏈接
book.setBookUrl(bookUrl);
//圖片
book.setImg(doc.select("div.book-img > img").attr("src"));
//書(shū)名
book.setBookName(doc.select("div.book-info > div.book-name").text());
//作者
book.setAuthor(doc.select("div.book-author div.au-name").text());
//更新時(shí)間
book.setUpdateDate(doc.select("div.book-new-chapter div.time").text());
//最新章節(jié)
book.setLatestChapter(doc.select("div.book-new-chapter div.tit a").text());
book.setLatestChapterUrl(doc.select("div.book-new-chapter div.tit a").attr("href"));
//類(lèi)型
book.setType(doc.select("div.book-label > a").last().text());
//簡(jiǎn)介
book.setSynopsis(doc.select("div.book-dec > p").text());
//狀態(tài)
book.setStatus(doc.select("div.book-label > a").first().text());
//章節(jié)目錄
String chaptersUrl=doc.select("a.all-catalog").attr("href");
ArrayList<Map<String, String>> chapters=new ArrayList<>();
//采集術(shù)
for (Element result : Jsoup.parse(BookUtil.gather(chaptersUrl, bookUrl)).select("ul.chapter-list li")) {
HashMap<String, String> map=new HashMap<>();
map.put("chapterName", result.select("a").text());
map.put("url", result.select("a").attr("href"));
chapters.add(map);
}
book.setChapters(chapters);
//來(lái)源
book.setSource(src);
} catch (Exception e) {
System.err.println("采集數(shù)據(jù)操作出錯(cuò)");
e.printStackTrace();
}
return book;
}
/**
* 得到當(dāng)前章節(jié)名以及完整內(nèi)容跟上、下一章的鏈接地址 縱橫中文網(wǎng)采集規(guī)則
* @param src 源目標(biāo)
* @param chapterUrl 當(dāng)前章節(jié)鏈接
* @param refererUrl 來(lái)源鏈接
* @return Book對(duì)象
*/
public static Book book_read_zongheng(Map<String, String> src,String chapterUrl,String refererUrl) {
Book book=new Book();
//當(dāng)前章節(jié)鏈接
book.setNowChapterUrl(chapterUrl.contains("http") ? chapterUrl : (src.get("baseUrl") + chapterUrl));
//采集術(shù)
String html=BookUtil.gather(book.getNowChapterUrl(), refererUrl);
try {
//解析html格式的字符串成一個(gè)Document
Document doc=Jsoup.parse(html);
//當(dāng)前章節(jié)名稱(chēng)
book.setNowChapter(doc.select("div.title_txtbox").text());
//刪除圖片廣告
doc.select("div.content img").remove();
//當(dāng)前章節(jié)內(nèi)容
book.setNowChapterValue(doc.select("div.content").outerHtml());
//上、下一章
book.setPrevChapter(doc.select("div.chap_btnbox a:matches((?i)下一章)").text());
book.setPrevChapterUrl(doc.select("div.chap_btnbox a:matches((?i)下一章)").attr("href"));
book.setNextChapter(doc.select("div.chap_btnbox a:matches((?i)上一章)").text());
book.setNextChapterUrl(doc.select("div.chap_btnbox a:matches((?i)上一章)").attr("href"));
//來(lái)源
book.setSource(src);
} catch (Exception e) {
System.err.println("采集數(shù)據(jù)操作出錯(cuò)");
e.printStackTrace();
}
return book;
}
}
BookHandler_qidian
/**
* 起點(diǎn)中文網(wǎng)采集規(guī)則
*/
public class BookHandler_qidian {
/**
* 來(lái)源信息
*/
public static HashMap<String, String> qidian=new HashMap<>();
static {
//起點(diǎn)中文網(wǎng)
qidian.put("name", "起點(diǎn)中文網(wǎng)");
qidian.put("key", "qidian");
qidian.put("baseUrl", "http://www.qidian.com");
qidian.put("baseSearchUrl", "https://www.qidian.com/search");
qidian.put("UrlEncode", "UTF-8");
qidian.put("searchUrl", "https://www.qidian.com/search?kw=#1&page=#2");
}
/**
* 獲取search list 起點(diǎn)中文網(wǎng)采集規(guī)則
*
* @param books 結(jié)果集合
* @param src 源目標(biāo)
* @param keyWord 關(guān)鍵字
*/
public static void book_search_qidian(ArrayList<Book> books, Map<String, String> src, String keyWord) {
//采集術(shù)
String html=BookUtil.gather(src.get("searchUrl"), src.get("baseUrl"));
try {
//解析html格式的字符串成一個(gè)Document
Document doc=Jsoup.parse(html);
//當(dāng)前頁(yè)集合
Elements resultList=doc.select("li.res-book-item");
for (Element result : resultList) {
Book book=new Book();
/*
如果大家打斷點(diǎn)在這里的話(huà)就會(huì)發(fā)現(xiàn),起點(diǎn)的鏈接是這樣的
//book.qidian.com/info/1012786368
以?xún)蓚€(gè)斜杠開(kāi)頭,不過(guò)無(wú)所謂,httpClient照樣可以請(qǐng)求
*/
//書(shū)本鏈接
book.setBookUrl(result.select("div.book-img-box a").attr("href"));
//圖片
book.setImg(result.select("div.book-img-box img").attr("src"));
//書(shū)名
book.setBookName(result.select("div.book-mid-info > h4").text());
//作者
book.setAuthor(result.select("div.book-mid-info > p.author > a").first().text());
//類(lèi)型
book.setType(result.select("div.book-mid-info > p.author > a").last().text());
//簡(jiǎn)介
book.setSynopsis(result.select("div.book-mid-info > p.intro").text());
//狀態(tài)
book.setStatus(result.select("div.book-mid-info > p.author > span").first().text());
//更新時(shí)間
book.setUpdateDate(result.select("div.book-mid-info > p.update > span").text());
//最新章節(jié)
book.setLatestChapter(result.select("div.book-mid-info > p.update > a").text());
book.setLatestChapterUrl(result.select("div.book-mid-info > p.update > a").attr("href"));
//來(lái)源
book.setSource(src);
books.add(book);
}
//當(dāng)前頁(yè)
String page=doc.select("div#page-container").attr("data-page");
//最大頁(yè)數(shù)
String pageMax=doc.select("div#page-container").attr("data-pageMax");
//當(dāng)前頁(yè) < 最大頁(yè)數(shù)
if (Integer.valueOf(page) < Integer.valueOf(pageMax)) {
src.put("baseUrl", src.get("searchUrl"));
//自己拼接下一頁(yè)鏈接
src.put("searchUrl", src.get("searchUrl").replaceAll("page=" + Integer.valueOf(page), "page=" + (Integer.valueOf(page) + 1)));
book_search_qidian(books, src, keyWord);
}
} catch (Exception e) {
System.err.println("采集數(shù)據(jù)操作出錯(cuò)");
e.printStackTrace();
}
}
/**
* 獲取書(shū)本詳情 起點(diǎn)中文網(wǎng)采集規(guī)則
* @param src 源目標(biāo)
* @param bookUrl 書(shū)本鏈接
* @return Book對(duì)象
*/
public static Book book_details_qidian(Map<String, String> src, String bookUrl) {
Book book=new Book();
//https
bookUrl="https:" + bookUrl;
//采集術(shù)
String html=BookUtil.gather(bookUrl, src.get("searchUrl"));
try {
//解析html格式的字符串成一個(gè)Document
Document doc=Jsoup.parse(html);
//書(shū)本鏈接
book.setBookUrl(bookUrl);
//圖片
String img=doc.select("div.book-img > a#bookImg > img").attr("src");
img="https:" + img;
book.setImg(img);
//書(shū)名
book.setBookName(doc.select("div.book-info > h1 > em").text());
//作者
book.setAuthor(doc.select("div.book-info > h1 a.writer").text());
//更新時(shí)間
book.setUpdateDate(doc.select("li.update em.time").text());
//最新章節(jié)
book.setLatestChapter(doc.select("li.update a").text());
book.setLatestChapterUrl(doc.select("li.update a").attr("href"));
//類(lèi)型
book.setType(doc.select("p.tag > span").first().text());
//簡(jiǎn)介
book.setSynopsis(doc.select("div.book-intro > p").text());
//狀態(tài)
book.setStatus(doc.select("p.tag > a").first().text());
//章節(jié)目錄
//創(chuàng)建httpclient對(duì)象 (這里設(shè)置成全局變量,相對(duì)于同一個(gè)請(qǐng)求session、cookie會(huì)跟著攜帶過(guò)去)
BasicCookieStore cookieStore=new BasicCookieStore();
CloseableHttpClient httpClient=HttpClients.custom().setDefaultCookieStore(cookieStore).build();
//創(chuàng)建get方式請(qǐng)求對(duì)象
HttpGet httpGet=new HttpGet("https://book.qidian.com/");
httpGet.addHeader("Content-type", "application/json");
//包裝一下
httpGet.addHeader("User-Agent", "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.100 Safari/537.36");
httpGet.addHeader("Connection", "keep-alive");
//通過(guò)請(qǐng)求對(duì)象獲取響應(yīng)對(duì)象
CloseableHttpResponse response=httpClient.execute(httpGet);
//獲得Cookies
String _csrfToken="";
List<Cookie> cookies=cookieStore.getCookies();
for (int i=0; i < cookies.size(); i++) {
if("_csrfToken".equals(cookies.get(i).getName())){
_csrfToken=cookies.get(i).getValue();
}
}
//構(gòu)造post
String bookId=doc.select("div.book-img a#bookImg").attr("data-bid");
HttpPost httpPost=new HttpPost(BookUtil.insertParams("https://book.qidian.com/ajax/book/category?_csrfToken=#1&bookId=#2",_csrfToken,bookId));
httpPost.addHeader("User-Agent", "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.100 Safari/537.36");
httpPost.addHeader("Connection", "keep-alive");
//通過(guò)請(qǐng)求對(duì)象獲取響應(yīng)對(duì)象
CloseableHttpResponse response1=httpClient.execute(httpPost);
//獲取結(jié)果實(shí)體(json格式字符串)
String chaptersJson="";
if (response1.getStatusLine().getStatusCode()==HttpStatus.SC_OK) {
chaptersJson=EntityUtils.toString(response1.getEntity(), "UTF-8");
}
//java處理json
ArrayList<Map<String, String>> chapters=new ArrayList<>();
JSONObject jsonArray=JSONObject.fromObject(chaptersJson);
Map<String,Object> objectMap=(Map<String, Object>) jsonArray;
Map<String, Object> objectMap_data=(Map<String, Object>) objectMap.get("data");
List<Map<String, Object>> objectMap_data_vs=(List<Map<String, Object>>) objectMap_data.get("vs");
for(Map<String, Object> vs : objectMap_data_vs){
List<Map<String, Object>> cs=(List<Map<String, Object>>) vs.get("cs");
for(Map<String, Object> chapter : cs){
Map<String, String> map=new HashMap<>();
map.put("chapterName", (String) chapter.get("cN"));
map.put("url", "https://read.qidian.com/chapter/"+(String) chapter.get("cU"));
chapters.add(map);
}
}
book.setChapters(chapters);
//來(lái)源
book.setSource(src);
//釋放鏈接
response.close();
} catch (Exception e) {
System.err.println("采集數(shù)據(jù)操作出錯(cuò)");
e.printStackTrace();
}
return book;
}
/**
* 得到當(dāng)前章節(jié)名以及完整內(nèi)容跟上、下一章的鏈接地址 起點(diǎn)中文網(wǎng)采集規(guī)則
* @param src 源目標(biāo)
* @param chapterUrl 當(dāng)前章節(jié)鏈接
* @param refererUrl 來(lái)源鏈接
* @return Book對(duì)象
*/
public static Book book_read_qidian(Map<String, String> src,String chapterUrl,String refererUrl) {
Book book=new Book();
//當(dāng)前章節(jié)鏈接
book.setNowChapterUrl(chapterUrl.contains("http") ? chapterUrl : (src.get("baseUrl") + chapterUrl));
//采集術(shù)
String html=BookUtil.gather(book.getNowChapterUrl(), refererUrl);
try {
//解析html格式的字符串成一個(gè)Document
Document doc=Jsoup.parse(html);
System.out.println(html);
//當(dāng)前章節(jié)名稱(chēng)
book.setNowChapter(doc.select("h3.j_chapterName").text());
//刪除圖片廣告
doc.select("div.read-content img").remove();
//當(dāng)前章節(jié)內(nèi)容
book.setNowChapterValue(doc.select("div.read-content").outerHtml());
//上、下一章
book.setPrevChapter(doc.select("div.chapter-control a:matches((?i)下一章)").text());
String prev=doc.select("div.chapter-control a:matches((?i)下一章)").attr("href");
prev="https:"+prev;
book.setPrevChapterUrl(prev);
book.setNextChapter(doc.select("div.chapter-control a:matches((?i)上一章)").text());
String next=doc.select("div.chapter-control a:matches((?i)上一章)").attr("href");
next="https:"+next;
book.setNextChapterUrl(next);
//來(lái)源
book.setSource(src);
} catch (Exception e) {
System.err.println("采集數(shù)據(jù)操作出錯(cuò)");
e.printStackTrace();
}
return book;
}
}
四個(gè)html頁(yè)面:
book_index
<!DOCTYPE html>
<!--解決idea thymeleaf 表達(dá)式模板報(bào)紅波浪線(xiàn)-->
<!--suppress ALL -->
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>MY BOOK</title>
<!-- 新 Bootstrap 核心 CSS 文件 -->
<link rel="stylesheet" href="http://cdn.static.runoob.com/libs/bootstrap/3.3.7/css/bootstrap.min.css">
<style>
body{
background-color: antiquewhite;
}
.main{
margin: auto;
width: 500px;
margin-top: 150px;
}
#bookName{
width: 300px;
}
#title{
text-align: center;
}
</style>
</head>
<body>
<div class="main">
<h2 id="title">MY BOOK</h2>
<form class="form-inline" method="get" th:action="@{/book/search}">
來(lái)源
<select class="form-control" id="source" name="sourceKey">
<option value="">所有</option>
<option value="biquge">筆趣閣</option>
<option value="zongheng">縱橫網(wǎng)</option>
<option value="qidian">起點(diǎn)網(wǎng)</option>
</select>
<input type="text" id="bookName" name="bookName" class="form-control" placeholder="請(qǐng)輸入..."/>
<button class="btn btn-info" type="submit">搜索</button>
</form>
</div>
</body>
</html>
<!DOCTYPE html>
<!--解決idea thymeleaf 表達(dá)式模板報(bào)紅波浪線(xiàn)-->
<!--suppress ALL -->
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>BOOK LIST</title>
<!-- 新 Bootstrap 核心 CSS 文件 -->
<link rel="stylesheet" href="http://cdn.static.runoob.com/libs/bootstrap/3.3.7/css/bootstrap.min.css">
<link rel="stylesheet" href="http://hanlei.online/Onlineaddress/layui/css/layui.css"/>
<style>
body {
background-color: antiquewhite;
}
.main {
margin: auto;
width: 500px;
margin-top: 50px;
}
.book {
border-bottom: solid #428bca 1px;
}
.click-book-detail, .click-book-read {
cursor: pointer;
color: #428bca;
}
.click-book-detail:hover {
color: rgba(150, 149, 162, 0.47);
}
.click-book-read:hover {
color: rgba(150, 149, 162, 0.47);
}
</style>
</head>
<body>
<div class="main">
<form class="form-inline" method="get" th:action="@{/book/search}">
來(lái)源
<select class="form-control" id="source" name="sourceKey">
<option value="">所有</option>
<option value="biquge" th:selected="${sourceKey}=='biquge'">筆趣閣</option>
<option value="zongheng" th:selected="${sourceKey}=='zongheng'">縱橫網(wǎng)</option>
<option value="qidian" th:selected="${sourceKey}=='qidian'">起點(diǎn)網(wǎng)</option>
</select>
<input type="text" id="bookName" name="bookName" class="form-control" placeholder="請(qǐng)輸入..."
th:value="${keyWord}"/>
<button class="btn btn-info" type="submit">搜索</button>
</form>
<br/>
<div id="books"></div>
<div id="page"></div>
</div>
</body>
<!-- jquery在線(xiàn)版本 -->
<script src="http://libs.baidu.com/jquery/2.1.4/jquery.min.js"></script>
<script src="http://hanlei.online/Onlineaddress/layui/layui.js"></script>
<script th:inline="javascript">
var ctx=/*[[@{/}]]*/'';
var books=[[${books}]];//取出后臺(tái)數(shù)據(jù)
var nums=10; //每頁(yè)出現(xiàn)的數(shù)量
var pages=books.length; //總數(shù)
/**
* 傳入當(dāng)前頁(yè),根據(jù)nums去計(jì)算,從books集合截取對(duì)應(yīng)數(shù)據(jù)做展示
*/
var thisDate=function (curr) {
var str="",//當(dāng)前頁(yè)需要展示的html
first=(curr * nums - nums),//展示的第一條數(shù)據(jù)的下標(biāo)
last=curr * nums - 1;//展示的最后一條數(shù)據(jù)的下標(biāo)
last=last >=books.length ? (books.length - 1) : last;
for (var i=first; i <=last; i++) {
var book=books[i];
str +="<div class='book'>" +
"<img class='click-book-detail' data-bookurl='" + book.bookUrl + "' data-sourcekey='" + book.source.key + "' data-searchurl='" + book.source.searchUrl + "' src='" + book.img + "'></img>" +
"<p class='click-book-detail' data-bookurl='" + book.bookUrl + "' data-sourcekey='" + book.source.key + "' data-searchurl='" + book.source.searchUrl + "'>書(shū)名:" + book.bookName + "</p>" +
"<p>作者:" + book.author + "</p>" +
"<p>簡(jiǎn)介:" + book.synopsis + "</p>" +
"<p class='click-book-read' data-chapterurl='" + book.latestChapterUrl + "' data-sourcekey='" + book.source.key + "' data-refererurl='" + book.source.refererurl + "'>最新章節(jié):" + book.latestChapter + "</p>" +
"<p>更新時(shí)間:" + book.updateDate + "</p>" +
"<p>大小:" + book.magnitude + "</p>" +
"<p>狀態(tài):" + book.status + "</p>" +
"<p>類(lèi)型:" + book.type + "</p>" +
"<p>來(lái)源:" + book.source.name + "</p>" +
"</div><br/>";
}
return str;
};
//獲取一個(gè)laypage實(shí)例
layui.use('laypage', function () {
var laypage=layui.laypage;
//調(diào)用laypage 邏輯分頁(yè)
laypage.render({
elem: 'page',
count: pages,
limit: nums,
jump: function (obj) {
//obj包含了當(dāng)前分頁(yè)的所有參數(shù),比如:
// console.log(obj.curr); //得到當(dāng)前頁(yè),以便向服務(wù)端請(qǐng)求對(duì)應(yīng)頁(yè)的數(shù)據(jù)。
// console.log(obj.limit); //得到每頁(yè)顯示的條數(shù)
document.getElementById('books').innerHTML=thisDate(obj.curr);
},
prev: '<',
next: '>',
theme: '#f9c357',
})
});
$("body").on("click", ".click-book-detail", function (even) {
var bookUrl=$(this).data("bookurl");
var searchUrl=$(this).data("searchurl");
var sourceKey=$(this).data("sourcekey");
window.location.href=ctx + "/book/details?sourceKey=" + sourceKey + "&searchUrl=" + searchUrl + "&bookUrl=" + bookUrl;
});
$("body").on("click", ".click-book-read", function (even) {
var chapterUrl=$(this).data("chapterurl");
var refererUrl=$(this).data("refererurl");
var sourceKey=$(this).data("sourcekey");
window.location.href=ctx + "/book/read?sourceKey=" + sourceKey + "&refererUrl=" + refererUrl + "&chapterUrl=" + chapterUrl;
});
</script>
</html>
book_details
<!DOCTYPE html>
<!--解決idea thymeleaf 表達(dá)式模板報(bào)紅波浪線(xiàn)-->
<!--suppress ALL -->
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>BOOK DETAILS</title>
<!-- 新 Bootstrap 核心 CSS 文件 -->
<link rel="stylesheet" href="http://cdn.static.runoob.com/libs/bootstrap/3.3.7/css/bootstrap.min.css">
<link rel="stylesheet" href="http://hanlei.online/Onlineaddress/layui/css/layui.css"/>
<style>
body {
background-color: antiquewhite;
}
.main {
margin: auto;
width: 500px;
margin-top: 150px;
}
.book {
border-bottom: solid #428bca 1px;
}
.click-book-detail, .click-book-read {
cursor: pointer;
color: #428bca;
}
.click-book-detail:hover {
color: rgba(150, 149, 162, 0.47);
}
.click-book-read:hover {
color: rgba(150, 149, 162, 0.47);
}
a {
color: #428bca;
}
</style>
</head>
<body>
<div class="main">
<div class='book'>
<div id="bookImg"></div>
<p>書(shū)名:<span th:text="${book.bookName}"></span></p>
<p>作者:<span th:text="${book.author}"></span></p>
<p>簡(jiǎn)介:<span th:text="${book.synopsis}"></span></p>
<p>最新章節(jié):<a th:href="${book.latestChapterUrl}" th:text="${book.latestChapter}"></a></p>
<p>更新時(shí)間:<span th:text="${book.updateDate}"></span></p>
<p>大小:<span th:text="${book.magnitude}"></span></p>
<p>狀態(tài):<span th:text="${book.status}"></span></p>
<p>類(lèi)型:<span th:text="${book.type}"></span></p>
<p>來(lái)源:<span th:text="${book.source.name}"></span></p>
</div>
<br/>
<div class="chapters" th:each="chapter,iterStat:${book.chapters}">
<p class="click-book-read" th:attr="data-chapterurl=${chapter.url},data-sourcekey=${book.source.key},data-refererurl=${book.bookUrl}" th:text="${chapter.chapterName}"></p>
</div>
</div>
</body>
<!-- jquery在線(xiàn)版本 -->
<script src="http://libs.baidu.com/jquery/2.1.4/jquery.min.js"></script>
<script th:inline="javascript">
var ctx=/*[[@{/}]]*/'';
var book=[[${book}]];//取出后臺(tái)數(shù)據(jù)
/**
* 反防盜鏈
*/
function showImg(parentObj, url) {
//來(lái)一個(gè)隨機(jī)數(shù)
var frameid='frameimg' + Math.random();
//放在(父頁(yè)面)window里面 iframe的script標(biāo)簽里面綁定了window.onload,作用:設(shè)置iframe的高度、寬度 <script>window.onload=function() { parent.document.getElementById(\'' + frameid + '\').height=document.getElementById(\'img\').height+\'px\'; }<' + '/script>
window.img='<img src=\'' + url + '?' + Math.random() + '\'/>';
//iframe調(diào)用parent.img
$(parentObj).append('<iframe id="' + frameid + '" src="javascript:parent.img;" frameBorder="0" scrolling="no"></iframe>');
}
showImg($("#bookImg"), book.img);
$("body").on("click", ".click-book-read", function (even) {
var chapterUrl=$(this).data("chapterurl");
var refererUrl=$(this).data("refererurl");
var sourceKey=$(this).data("sourcekey");
window.location.href=ctx + "/book/read?sourceKey=" + sourceKey + "&refererUrl=" + refererUrl + "&chapterUrl=" + chapterUrl;
});
</script>
</html>
book_read
<!DOCTYPE html>
<!--解決idea thymeleaf 表達(dá)式模板報(bào)紅波浪線(xiàn)-->
<!--suppress ALL -->
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>BOOK READ</title>
<style>
body {
background-color: antiquewhite;
}
.main {
padding: 10px 20px;
}
.click-book-detail, .click-book-read {
cursor: pointer;
color: #428bca;
}
.click-book-detail:hover {
color: rgba(150, 149, 162, 0.47);
}
.click-book-read:hover {
color: rgba(150, 149, 162, 0.47);
}
.float-left{
float: left;
margin-left: 70px;
}
</style>
</head>
<body>
<div class="main">
<!-- 章節(jié)名稱(chēng) -->
<h3 th:text="${book.nowChapter}"></h3>
<!-- 章節(jié)內(nèi)容 -->
<p th:utext="${book.nowChapterValue}"></p>
<!-- 上、下章 -->
<p class="click-book-read float-left"
th:attr="data-chapterurl=${book.nextChapterUrl},data-sourcekey=${book.source.key},data-refererurl=${book.nowChapterUrl}"
th:text="${book.nextChapter}"></p>
<p class="click-book-read float-left"
th:attr="data-chapterurl=${book.prevChapterUrl},data-sourcekey=${book.source.key},data-refererurl=${book.nowChapterUrl}"
th:text="${book.prevChapter}"></p>
</div>
</body>
<!-- jquery在線(xiàn)版本 -->
<script src="http://libs.baidu.com/jquery/2.1.4/jquery.min.js"></script>
<script th:inline="javascript">
var ctx=/*[[@{/}]]*/'';
$("body").on("click", ".click-book-read", function (even) {
var chapterUrl=$(this).data("chapterurl");
var refererUrl=$(this).data("refererurl");
var sourceKey=$(this).data("sourcekey");
window.location.href=ctx + "/book/read?sourceKey=" + sourceKey + "&refererUrl=" + refererUrl + "&chapterUrl=" + chapterUrl;
});
</script>
</html>
2019-07-17補(bǔ)充:我們之前三個(gè)來(lái)源網(wǎng)站的baseUrl都是用http,但網(wǎng)站后面都升級(jí)成了https,例如筆趣閣:
導(dǎo)致抓取數(shù)據(jù)時(shí)報(bào)錯(cuò)
<!DOCTYPE html>
<!--解決idea thymeleaf 表達(dá)式模板報(bào)紅波浪線(xiàn)-->
<!--suppress ALL -->
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>BOOK LIST</title>
<!-- 新 Bootstrap 核心 CSS 文件 -->
<link rel="stylesheet" href="http://cdn.static.runoob.com/libs/bootstrap/3.3.7/css/bootstrap.min.css">
<link rel="stylesheet" href="http://hanlei.online/Onlineaddress/layui/css/layui.css"/>
<style>
body {
background-color: antiquewhite;
}
.main {
margin: auto;
width: 500px;
margin-top: 50px;
}
.book {
border-bottom: solid #428bca 1px;
}
.click-book-detail, .click-book-read {
cursor: pointer;
color: #428bca;
}
.click-book-detail:hover {
color: rgba(150, 149, 162, 0.47);
}
.click-book-read:hover {
color: rgba(150, 149, 162, 0.47);
}
</style>
</head>
<body>
<div class="main">
<form class="form-inline" method="get" th:action="@{/book/search}">
來(lái)源
<select class="form-control" id="source" name="sourceKey">
<option value="">所有</option>
<option value="biquge" th:selected="${sourceKey}=='biquge'">筆趣閣</option>
<option value="zongheng" th:selected="${sourceKey}=='zongheng'">縱橫網(wǎng)</option>
<option value="qidian" th:selected="${sourceKey}=='qidian'">起點(diǎn)網(wǎng)</option>
</select>
<input type="text" id="bookName" name="bookName" class="form-control" placeholder="請(qǐng)輸入..."
th:value="${keyWord}"/>
<button class="btn btn-info" type="submit">搜索</button>
</form>
<br/>
<div id="books"></div>
<div id="page"></div>
</div>
</body>
<!-- jquery在線(xiàn)版本 -->
<script src="http://libs.baidu.com/jquery/2.1.4/jquery.min.js"></script>
<script src="http://hanlei.online/Onlineaddress/layui/layui.js"></script>
<script th:inline="javascript">
var ctx=/*[[@{/}]]*/'';
var books=[[${books}]];//取出后臺(tái)數(shù)據(jù)
var nums=10; //每頁(yè)出現(xiàn)的數(shù)量
var pages=books.length; //總數(shù)
/**
* 傳入當(dāng)前頁(yè),根據(jù)nums去計(jì)算,從books集合截取對(duì)應(yīng)數(shù)據(jù)做展示
*/
var thisDate=function (curr) {
var str="",//當(dāng)前頁(yè)需要展示的html
first=(curr * nums - nums),//展示的第一條數(shù)據(jù)的下標(biāo)
last=curr * nums - 1;//展示的最后一條數(shù)據(jù)的下標(biāo)
last=last >=books.length ? (books.length - 1) : last;
for (var i=first; i <=last; i++) {
var book=books[i];
str +="<div class='book'>" +
"<img class='click-book-detail' data-bookurl='" + book.bookUrl + "' data-sourcekey='" + book.source.key + "' data-searchurl='" + book.source.searchUrl + "' src='" + book.img + "'></img>" +
"<p class='click-book-detail' data-bookurl='" + book.bookUrl + "' data-sourcekey='" + book.source.key + "' data-searchurl='" + book.source.searchUrl + "'>書(shū)名:" + book.bookName + "</p>" +
"<p>作者:" + book.author + "</p>" +
"<p>簡(jiǎn)介:" + book.synopsis + "</p>" +
"<p class='click-book-read' data-chapterurl='" + book.latestChapterUrl + "' data-sourcekey='" + book.source.key + "' data-refererurl='" + book.source.refererurl + "'>最新章節(jié):" + book.latestChapter + "</p>" +
"<p>更新時(shí)間:" + book.updateDate + "</p>" +
"<p>大小:" + book.magnitude + "</p>" +
"<p>狀態(tài):" + book.status + "</p>" +
"<p>類(lèi)型:" + book.type + "</p>" +
"<p>來(lái)源:" + book.source.name + "</p>" +
"</div><br/>";
}
return str;
};
//獲取一個(gè)laypage實(shí)例
layui.use('laypage', function () {
var laypage=layui.laypage;
//調(diào)用laypage 邏輯分頁(yè)
laypage.render({
elem: 'page',
count: pages,
limit: nums,
jump: function (obj) {
//obj包含了當(dāng)前分頁(yè)的所有參數(shù),比如:
// console.log(obj.curr); //得到當(dāng)前頁(yè),以便向服務(wù)端請(qǐng)求對(duì)應(yīng)頁(yè)的數(shù)據(jù)。
// console.log(obj.limit); //得到每頁(yè)顯示的條數(shù)
document.getElementById('books').innerHTML=thisDate(obj.curr);
},
prev: '<',
next: '>',
theme: '#f9c357',
})
});
$("body").on("click", ".click-book-detail", function (even) {
var bookUrl=$(this).data("bookurl");
var searchUrl=$(this).data("searchurl");
var sourceKey=$(this).data("sourcekey");
window.location.href=ctx + "/book/details?sourceKey=" + sourceKey + "&searchUrl=" + searchUrl + "&bookUrl=" + bookUrl;
});
$("body").on("click", ".click-book-read", function (even) {
var chapterUrl=$(this).data("chapterurl");
var refererUrl=$(this).data("refererurl");
var sourceKey=$(this).data("sourcekey");
window.location.href=ctx + "/book/read?sourceKey=" + sourceKey + "&refererUrl=" + refererUrl + "&chapterUrl=" + chapterUrl;
});
</script>
</html>
解決辦法:參考https://blog.csdn.net/xiaoxian8023/article/details/49865335,繞過(guò)證書(shū)驗(yàn)證
在BookUtil.java中新增方法
/**
* 繞過(guò)SSL驗(yàn)證
*/
private static SSLContext createIgnoreVerifySSL() throws NoSuchAlgorithmException, KeyManagementException {
SSLContext sc=SSLContext.getInstance("SSLv3");
// 實(shí)現(xiàn)一個(gè)X509TrustManager接口,用于繞過(guò)驗(yàn)證,不用修改里面的方法
X509TrustManager trustManager=new X509TrustManager() {
@Override
public void checkClientTrusted(
java.security.cert.X509Certificate[] paramArrayOfX509Certificate,
String paramString) throws CertificateException {
}
@Override
public void checkServerTrusted(
java.security.cert.X509Certificate[] paramArrayOfX509Certificate,
String paramString) throws CertificateException {
}
@Override
public java.security.cert.X509Certificate[] getAcceptedIssuers() {
return null;
}
};
sc.init(null, new TrustManager[]{trustManager}, null);
return sc;
}
然后在gather方法中改成這樣獲取httpClient
/**
* 采集當(dāng)前url完整response實(shí)體.toString()
*
* @param url url
* @return response實(shí)體.toString()
*/
public static String gather(String url, String refererUrl) {
String result=null;
try {
//采用繞過(guò)驗(yàn)證的方式處理https請(qǐng)求
SSLContext sslcontext=createIgnoreVerifySSL();
// 設(shè)置協(xié)議http和https對(duì)應(yīng)的處理socket鏈接工廠(chǎng)的對(duì)象
Registry<ConnectionSocketFactory> socketFactoryRegistry=RegistryBuilder.<ConnectionSocketFactory>create()
.register("http", PlainConnectionSocketFactory.INSTANCE)
.register("https", new SSLConnectionSocketFactory(sslcontext))
.build();
PoolingHttpClientConnectionManager connManager=new PoolingHttpClientConnectionManager(socketFactoryRegistry);
HttpClients.custom().setConnectionManager(connManager);
//創(chuàng)建自定義的httpclient對(duì)象
CloseableHttpClient httpClient=HttpClients.custom().setConnectionManager(connManager).build();
//創(chuàng)建httpclient對(duì)象 (這里設(shè)置成全局變量,相對(duì)于同一個(gè)請(qǐng)求session、cookie會(huì)跟著攜帶過(guò)去)
// CloseableHttpClient httpClient=HttpClients.createDefault();
//創(chuàng)建get方式請(qǐng)求對(duì)象
HttpGet httpGet=new HttpGet(url);
httpGet.addHeader("Content-type", "application/json");
//包裝一下
httpGet.addHeader("User-Agent", "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.100 Safari/537.36");
httpGet.addHeader("Referer", refererUrl);
httpGet.addHeader("Connection", "keep-alive");
//通過(guò)請(qǐng)求對(duì)象獲取響應(yīng)對(duì)象
CloseableHttpResponse response=httpClient.execute(httpGet);
//獲取結(jié)果實(shí)體
if (response.getStatusLine().getStatusCode()==HttpStatus.SC_OK) {
result=EntityUtils.toString(response.getEntity(), "GBK");
}
//釋放鏈接
response.close();
}
//這里還可以捕獲超時(shí)異常,重新連接抓取
catch (Exception e) {
result=null;
System.err.println("采集操作出錯(cuò)");
e.printStackTrace();
}
return result;
}
這樣就可以正常抓取了
我們之前獲取項(xiàng)目路徑用的是
var ctx=/*[[@{/}]]*/'';
突然發(fā)現(xiàn)不行了,跳轉(zhuǎn)的路徑直接是/開(kāi)頭,現(xiàn)在改成這樣獲取
//項(xiàng)目路徑
var ctx=[[${#request.getContextPath()}]];
2019-08-01補(bǔ)充:大家如果看到有這個(gè)報(bào)錯(cuò),連接被重置,不要慌張,有可能是網(wǎng)站換域名了比如現(xiàn)在我們程序請(qǐng)求的是http://www.biquge.com.tw,但這個(gè)網(wǎng)址已經(jīng)不能訪(fǎng)問(wèn)了,筆趣閣已經(jīng)改成https://www.biqudu.net/,我們改一下代碼就可以解決問(wèn)題,要注意檢查各個(gè)源路徑是否能正常訪(fǎng)問(wèn),同時(shí)對(duì)方也可能改頁(yè)面格式,導(dǎo)致我們之前的規(guī)則無(wú)法匹配獲取數(shù)據(jù),這種情況只能重新編寫(xiě)爬取規(guī)則了
2019-08-02補(bǔ)充:發(fā)現(xiàn)了個(gè)bug,我們的BookUtil.insertParams方法原理是替換#字符串
/**
* 自動(dòng)注入?yún)?shù)
* 例如:
*
* @param src http://search.zongheng.com/s?keyword=#1&pageNo=#2&sort=* @param params "斗破蒼穹","1"
* @return http://search.zongheng.com/s?keyword=斗破蒼穹&pageNo=1&sort=*/
public static String insertParams(String src, String... params) {
int i=1;
for (String param : params) {
src=src.replaceAll("#" + i, param);
i++;
}
return src;
}
但是我們?cè)谒阉鞯臅r(shí)候,調(diào)用參數(shù)自動(dòng)注入,形參src的值是來(lái)自靜態(tài)屬性Map,初始化的時(shí)候有兩個(gè)#字符串,在進(jìn)行第一次搜索之后,#字符串被替換了,后面再進(jìn)行搜索注入?yún)?shù)已經(jīng)沒(méi)有#字符串了,因此后面的搜索結(jié)果都是第一次的結(jié)果...
解決:獲取來(lái)源時(shí)不是用=賦值,而是復(fù)制一份,三個(gè)方法都要改
修改前:
//獲取來(lái)源詳情
Map<String, String> src=source.get(sourceKey);
修改后:
//獲取來(lái)源詳情,復(fù)制一份
Map<String, String> src=new HashMap<>();
src.putAll(source.get(sourceKey));
公司最近打算做手機(jī)端,學(xué)習(xí)了DCloud公司的uni-app,開(kāi)發(fā)工具是HBuilderX,并用我們的小說(shuō)爬蟲(chóng)學(xué)習(xí)、練手,做了個(gè)H5手機(jī)端的頁(yè)面
DCloud公司官網(wǎng):https://www.dcloud.io/
uni-app官網(wǎng):https://uniapp.dcloud.io/
uni-app 是一個(gè)使用 Vue.js 開(kāi)發(fā)所有前端應(yīng)用的框架,開(kāi)發(fā)者編寫(xiě)一套代碼,可編譯到iOS、Android、H5、以及各種小程序等多個(gè)平臺(tái)。
效果圖:
代碼已經(jīng)開(kāi)源、托管到我的GitHub、碼云:
GitHub:https://github.com/huanzi-qch/spider
碼云:https://gitee.com/huanzi-qch/spider
作者:huanzi-qch
出處:https://www.cnblogs.com/huanzi-qch
若標(biāo)題中有“轉(zhuǎn)載”字樣,則本文版權(quán)歸原作者所有。若無(wú)轉(zhuǎn)載字樣,本文版權(quán)歸作者所有,歡迎轉(zhuǎn)載,但未經(jīng)作者同意必須保留此段聲明,且在文章頁(yè)面明顯位置給出原文鏈接,否則保留追究法律責(zé)任的權(quán)利.
百度搜索引擎優(yōu)化全過(guò)程中,大家一直注重頁(yè)面內(nèi)容的品質(zhì)和外鏈的相關(guān)性.
除開(kāi)這種,大家更關(guān)心的是網(wǎng)址的合理布局,但大家非常少花時(shí)間關(guān)心網(wǎng)站源代碼優(yōu)化的相關(guān)性.
實(shí)際上,大家覺(jué)得簡(jiǎn)約的編碼也十分有益于百度搜索引擎優(yōu)化.
那麼,網(wǎng)址前端工程師,DIVCSS怎樣有益于SEO?
1、頁(yè)數(shù)盡可能簡(jiǎn)單化,刪掉冗馀編碼,盡量避免注解,降低頁(yè)面尺寸.
2、合理使用JS,高品質(zhì)的相片,盡可能保證 百度搜索引擎蜘蛛的爬取和剖析工作壓力不容易過(guò)高.
3、在圖象中加上alt和title屬性,2個(gè)屬性值同樣,title的權(quán)重比alt的權(quán)重高,再再加上這兩個(gè)屬性,百度就能鑒別這一圖象,在屬性值中融進(jìn)關(guān)鍵詞.
4、網(wǎng)頁(yè)鏈接標(biāo)簽還能夠加上title屬性,提升 相關(guān)性和連接文字的表明,能夠更好地傳送權(quán)重.
5、JS、css代碼最好是獨(dú)立寫(xiě)在文檔中,啟用頁(yè)面就可以.
6、最好是不能用table合理布局,如今百度搜索引擎早已不太喜愛(ài)他了.
7、導(dǎo)航欄、導(dǎo)航對(duì)頁(yè)面很重要,最好是不必應(yīng)用JS.
8、不應(yīng)用iframe架構(gòu),其內(nèi)容百度爬不上來(lái).
9、h標(biāo)簽,從h1到h6這一標(biāo)簽也很重要,其權(quán)重降低了.
h1一頁(yè)只有應(yīng)用一次,他的權(quán)重最大,越上臺(tái)越好,搜索引擎蜘蛛越快跳上來(lái)給與權(quán)重,h1中融進(jìn)關(guān)鍵詞,但很少,能夠 大幅度提高頁(yè)面的關(guān)聯(lián)性.
h2一般用以小標(biāo)題,h3用以側(cè)題目,但不必亂用.
對(duì)于后邊三個(gè)標(biāo)簽的權(quán)重也慢慢減少,估計(jì)你也應(yīng)當(dāng)了解怎么使用他們.
可是不能用過(guò)多.
這會(huì)危害搜索引擎蜘蛛的分辨.
b和strong2個(gè)標(biāo)簽都太粗,可是不一樣,后面一種有強(qiáng)調(diào)的意思,頁(yè)面的關(guān)鍵詞可以用strong注重,團(tuán)隊(duì)排名也很好,可是不必過(guò)多.四五個(gè)吧.網(wǎng)址前臺(tái)接待編碼的SEO優(yōu)化很有可能這么多,打好基礎(chǔ)比全都強(qiáng).
JS代碼: /* * 分頁(yè)方法 * author:Mr.X * time:2017/12/27 */ Request=GetRequest(); var searchType=$("#search_type").val(); var key=Request[searchType]; var keyIndex=key.lastIndexOf('.'); if(keyIndex !=-1){ key=key.substring(0, keyIndex) } var IFRAME_SRC="http://"+window.location.host+"/search/"+searchType+"/"+key;//初始url var page=Request['p'];//獲取url中的地址參數(shù) if(page==null||page==""){ page=1; } var limit=12;//每頁(yè)限制條數(shù) var page_all="";//總頁(yè)數(shù) $(document).ready(function (){ page_list(); }); function page_list(){ var count=$("#page_count").html();//新聞總數(shù) var remainder=count%limit;//判斷是否有余數(shù),有余數(shù)的話(huà),整除后,余數(shù)+1,就是總頁(yè)數(shù);如果余數(shù)為0,即為整除,則整除后的的數(shù)即為總頁(yè)數(shù) if(count<=limit){ //總數(shù)達(dá)不到每頁(yè)顯示的條數(shù),則不顯示頁(yè)碼 }else{ //總數(shù)超過(guò)一頁(yè),即總數(shù)超過(guò)limit規(guī)定的條數(shù),顯示分頁(yè) //先判斷余數(shù)為0的情況:如果余數(shù)為0,即為整除,則整除后的的數(shù)即為總頁(yè)數(shù) if(remainder==0){ var page_number=count/limit;//總頁(yè)碼數(shù) page_number=parseInt(page_number);//將頁(yè)碼數(shù)由字符串類(lèi)型轉(zhuǎn)換為整形 page_all=page_number; //如果頁(yè)碼數(shù)不超過(guò)5,則顯示全部分頁(yè)總數(shù) if(page_number<6){ page=parseInt(page);//將獲取到的頁(yè)碼數(shù)轉(zhuǎn)換成整數(shù) var page_pre=page-1; var url_pre=IFRAME_SRC+'/p/'+page_pre;//上一頁(yè) var url_index=IFRAME_SRC+'/p/'+1;//首頁(yè) var url_last=IFRAME_SRC+'/p/'+page_number;//尾頁(yè) if(page==1){ //如果頁(yè)碼page=1,則隱藏上一頁(yè) //$("#page_list").append("<li class='paginate_button previous disabled' aria-controls='example' tabindex='0' id='example_previous'><a>上一頁(yè)</a></li>"); }else{ //如果頁(yè)碼page不是1,則顯示首頁(yè)和上一頁(yè) $("#page_list").append("<li class='paginate_button' aria-controls='example' tabindex='0' id='example_previous'><a href='"+url_index+"'>首頁(yè)</a></li>"); $("#page_list").append("<li class='paginate_button' aria-controls='example' tabindex='0' id='example_previous'><a href='"+url_pre+"'>上一頁(yè)</a></li>"); } //對(duì)頁(yè)碼進(jìn)行賦值 for(var i=0; i<page_number; i++){ var j=i+1; var url=IFRAME_SRC+'/p/'+j; if(page==j){ //如果是當(dāng)前頁(yè),則給當(dāng)前頁(yè)加上active $("#page_list").append("<li class='paginate_button active' aria-controls='example' tabindex='0'><a href='"+url+"'>"+j+"</a></li>"); }else{ //如果不是當(dāng)前頁(yè),則去掉active $("#page_list").append("<li class='paginate_button' aria-controls='example' tabindex='0'><a href='"+url+"'>"+j+"</a></li>"); } } //page=parseInt(page); var page_next=page+1; var url_next=IFRAME_SRC+'/p/'+page_next;//下一頁(yè) if(page==page_number){ //如果是最后一頁(yè),則隱藏下一頁(yè)功能 //$("#page_list").append("<li class='paginate_button next disabled' aria-controls='example' tabindex='0' id='example_next'><a>下一頁(yè)</a></li>"); }else{ //如果不是最后一頁(yè),則顯示最后一頁(yè)和尾頁(yè) $("#page_list").append("<li class='paginate_button' aria-controls='example' tabindex='0' id='example_next'><a href='"+url_next+"'>下一頁(yè)</a></li>"); $("#page_list").append("<li class='paginate_button' aria-controls='example' tabindex='0' id='example_next'><a href='"+url_last+"'>尾頁(yè)</a></li>"); } } //如果頁(yè)碼超過(guò)5,則分塊顯示:點(diǎn)擊第一頁(yè),顯示:1/2/3/4/5/..page_number,點(diǎn)擊第二頁(yè),顯示:1/2/3/4/5/..page_number,點(diǎn)擊第三頁(yè),顯示:1/2/3/4/5/..page_number,點(diǎn)擊第四頁(yè):顯示:1/2/3/4/5/..page_number,點(diǎn)擊第五頁(yè),顯示:1...3/4/5/6/7/..page_number;點(diǎn)擊page_number,顯示:1../page_number-4/page_number-3/page_number-2/page_number-1/page_number else{ if(page==1||page==2||page==3||page==4){ page=parseInt(page);//將字符串轉(zhuǎn)換為整形 var page_pre=page-1; var url_pre=IFRAME_SRC+'/p/'+page_pre;//上一頁(yè) var url_index=IFRAME_SRC+'/p/'+1;//首頁(yè) var url_last=IFRAME_SRC+'/p/'+page_number;//最后一頁(yè) if(page==1){ //$("#page_list").append("<li class='paginate_button previous disabled' aria-controls='example' tabindex='0' id='example_previous'><a>上一頁(yè)</a></li>"); }else{ $("#page_list").append("<li class='paginate_button' aria-controls='example' tabindex='0' id='example_previous'><a href='"+url_index+"'>首頁(yè)</a></li>"); $("#page_list").append("<li class='paginate_button' aria-controls='example' tabindex='0' id='example_previous'><a href='"+url_pre+"'>上一頁(yè)</a></li>"); } for(var i=0; i<page_number; i++){ if(i>4){ $("#page_list").append("<li class='paginate_button' aria-controls='example' tabindex='0' id='example_next'><a href='"+url_last+"'>..."+page_number+"</a></li>"); break; } var j=i+1; var url=IFRAME_SRC+'/p/'+j; //$(window.parent.document).find("#tab_13 iframe").attr("src",url); //url=$(window.parent.document).find("#tab_13 iframe").attr("src"); if(page==j){ $("#page_list").append("<li class='paginate_button active' aria-controls='example' tabindex='0'><a href='"+url+"'>"+j+"</a></li>"); }else{ $("#page_list").append("<li class='paginate_button' aria-controls='example' tabindex='0'><a href='"+url+"'>"+j+"</a></li>"); } } page=parseInt(page); var page_next=page+1; var url_next=IFRAME_SRC+'/p/'+page_next; if(page==page_number){ //$("#page_list").append("<li class='paginate_button next disabled' aria-controls='example' tabindex='0' id='example_next'><a>下一頁(yè)</a></li>"); }else{ $("#page_list").append("<li class='paginate_button' aria-controls='example' tabindex='0' id='example_next'><a href='"+url_next+"'>下一頁(yè)</a></li>"); $("#page_list").append("<li class='paginate_button' aria-controls='example' tabindex='0' id='example_next'><a href='"+url_last+"'>尾頁(yè)</a></li>"); } }else if(page==page_number-3||page==page_number-2||page==page_number-1||page==page_number){ page=parseInt(page);//將字符串轉(zhuǎn)換為整形 var page_pre=page-1; var url_pre=IFRAME_SRC+'/p/'+page_pre;//上一頁(yè) var url_index=IFRAME_SRC+'/p/'+1;//首頁(yè) var url_last=IFRAME_SRC+'/p/'+page_number;//最后一頁(yè) if(page==1){ //$("#page_list").append("<li class='paginate_button previous disabled' aria-controls='example' tabindex='0' id='example_previous'><a>上一頁(yè)</a></li>"); }else{ $("#page_list").append("<li class='paginate_button' aria-controls='example' tabindex='0' id='example_previous'><a href='"+url_index+"'>首頁(yè)</a></li>"); $("#page_list").append("<li class='paginate_button' aria-controls='example' tabindex='0' id='example_previous'><a href='"+url_pre+"'>上一頁(yè)</a></li>"); } $("#page_list").append("<li class='paginate_button' aria-controls='example' tabindex='0' id='example_next'><a href='"+url_index+"'>"+1+"...</a></li>"); for(var i=page_number-4; i<page_number+1; i++){ var j=i; var url=IFRAME_SRC+'/p/'+j; if(page==j){ $("#page_list").append("<li class='paginate_button active' aria-controls='example' tabindex='0'><a href='"+url+"'>"+j+"</a></li>"); }else{ $("#page_list").append("<li class='paginate_button' aria-controls='example' tabindex='0'><a href='"+url+"'>"+j+"</a></li>"); } } page=parseInt(page); var page_next=page+1; var url_next=IFRAME_SRC+'/p/'+page_next; if(page==page_number){ //$("#page_list").append("<li class='paginate_button next disabled' aria-controls='example' tabindex='0' id='example_next'><a>下一頁(yè)</a></li>"); }else{ $("#page_list").append("<li class='paginate_button' aria-controls='example' tabindex='0' id='example_next'><a href='"+url_next+"'>下一頁(yè)</a></li>"); $("#page_list").append("<li class='paginate_button' aria-controls='example' tabindex='0' id='example_next'><a href='"+url_last+"'>尾頁(yè)</a></li>"); } }else{ page=parseInt(page);//將字符串轉(zhuǎn)換為整形 var page_pre=page-1; var url_pre=IFRAME_SRC+'/p/'+page_pre;//上一頁(yè) var url_index=IFRAME_SRC+'/p/'+1;//首頁(yè) var url_last=IFRAME_SRC+'/p/'+page_number;//最后一頁(yè) if(page==1){ //$("#page_list").append("<li class='paginate_button previous disabled' aria-controls='example' tabindex='0' id='example_previous'><a>上一頁(yè)</a></li>"); }else{ $("#page_list").append("<li class='paginate_button' aria-controls='example' tabindex='0' id='example_previous'><a href='"+url_index+"'>首頁(yè)</a></li>"); $("#page_list").append("<li class='paginate_button' aria-controls='example' tabindex='0' id='example_previous'><a href='"+url_pre+"'>上一頁(yè)</a></li>"); } $("#page_list").append("<li class='paginate_button' aria-controls='example' tabindex='0' id='example_next'><a href='"+url_index+"'>"+1+"...</a></li>"); for(var i=page-3; i<page+2; i++){ var j=i+1; var url=IFRAME_SRC+'/p/'+j; if(page==j){ $("#page_list").append("<li class='paginate_button active' aria-controls='example' tabindex='0'><a href='"+url+"'>"+j+"</a></li>"); }else{ $("#page_list").append("<li class='paginate_button' aria-controls='example' tabindex='0'><a href='"+url+"'>"+j+"</a></li>"); } } $("#page_list").append("<li class='paginate_button' aria-controls='example' tabindex='0' id='example_next'><a href='"+url_last+"'>..."+page_number+"</a></li>"); page=parseInt(page); var page_next=page+1; var url_next=IFRAME_SRC+'/p/'+page_next; if(page==page_number){ //$("#page_list").append("<li class='paginate_button next disabled' aria-controls='example' tabindex='0' id='example_next'><a>下一頁(yè)</a></li>"); }else{ $("#page_list").append("<li class='paginate_button' aria-controls='example' tabindex='0' id='example_next'><a href='"+url_next+"'>下一頁(yè)</a></li>"); $("#page_list").append("<li class='paginate_button' aria-controls='example' tabindex='0' id='example_next'><a href='"+url_last+"'>尾頁(yè)</a></li>"); } } } $("#page_list").append("<span id='goto-page'>到第</span><input id='selcet_page' value='"+page+"'/><span id='go-page'>頁(yè)</span>"); $("#page_list").append("<button type='button' id='change_page'>確定</button>"); } //如果余數(shù)不為0,則將整除后的整數(shù)+1,即為總頁(yè)碼 else{ var page_number=count/limit; page_number=parseInt(page_number); page_number=page_number+1; page_all=page_number; //如果頁(yè)碼數(shù)不超過(guò)5,則顯示全部分頁(yè)總數(shù) if(page_number<6){ page=parseInt(page);//將獲取到的頁(yè)碼數(shù)轉(zhuǎn)換成整數(shù) var page_pre=page-1; var url_pre=IFRAME_SRC+'/p/'+page_pre;//上一頁(yè) var url_index=IFRAME_SRC+'/p/'+1;//首頁(yè) var url_last=IFRAME_SRC+'/p/'+page_number;//尾頁(yè) if(page==1){ //如果頁(yè)碼page=1,則隱藏上一頁(yè) //$("#page_list").append("<li class='paginate_button previous disabled' aria-controls='example' tabindex='0' id='example_previous'><a>上一頁(yè)</a></li>"); }else{ //如果頁(yè)碼page不是1,則顯示首頁(yè)和上一頁(yè) $("#page_list").append("<li class='paginate_button' aria-controls='example' tabindex='0' id='example_previous'><a href='"+url_index+"'>首頁(yè)</a></li>"); $("#page_list").append("<li class='paginate_button' aria-controls='example' tabindex='0' id='example_previous'><a href='"+url_pre+"'>上一頁(yè)</a></li>"); } //對(duì)頁(yè)碼進(jìn)行賦值 for(var i=0; i<page_number; i++){ var j=i+1; var url=IFRAME_SRC+'/p/'+j; if(page==j){ //如果是當(dāng)前頁(yè),則給當(dāng)前頁(yè)加上active $("#page_list").append("<li class='paginate_button active' aria-controls='example' tabindex='0'><a href='"+url+"'>"+j+"</a></li>"); }else{ //如果不是當(dāng)前頁(yè),則去掉active $("#page_list").append("<li class='paginate_button' aria-controls='example' tabindex='0'><a href='"+url+"'>"+j+"</a></li>"); } } //page=parseInt(page); var page_next=page+1; var url_next=IFRAME_SRC+'/p/'+page_next;//下一頁(yè) if(page==page_number){ //如果是最后一頁(yè),則隱藏下一頁(yè)功能 //$("#page_list").append("<li class='paginate_button next disabled' aria-controls='example' tabindex='0' id='example_next'><a>下一頁(yè)</a></li>"); }else{ //如果不是最后一頁(yè),則顯示最后一頁(yè)和尾頁(yè) $("#page_list").append("<li class='paginate_button' aria-controls='example' tabindex='0' id='example_next'><a href='"+url_next+"'>下一頁(yè)</a></li>"); $("#page_list").append("<li class='paginate_button' aria-controls='example' tabindex='0' id='example_next'><a href='"+url_last+"'>尾頁(yè)</a></li>"); } } //如果頁(yè)碼超過(guò)5,則分塊顯示:點(diǎn)擊第一頁(yè),顯示:1/2/3/4/5/..page_number,點(diǎn)擊第二頁(yè),顯示:1/2/3/4/5/..page_number,點(diǎn)擊第三頁(yè),顯示:1/2/3/4/5/..page_number,點(diǎn)擊第四頁(yè):顯示:1/2/3/4/5/..page_number,點(diǎn)擊第五頁(yè),顯示:1...3/4/5/6/7/..page_number;點(diǎn)擊page_number,顯示:1../page_number-4/page_number-3/page_number-2/page_number-1/page_number else{ if(page==1||page==2||page==3||page==4){ page=parseInt(page);//將字符串轉(zhuǎn)換為整形 var page_pre=page-1; var url_pre=IFRAME_SRC+'/p/'+page_pre;//上一頁(yè) var url_index=IFRAME_SRC+'/p/'+1;//首頁(yè) var url_last=IFRAME_SRC+'/p/'+page_number;//最后一頁(yè) if(page==1){ //$("#page_list").append("<li class='paginate_button previous disabled' aria-controls='example' tabindex='0' id='example_previous'><a>上一頁(yè)</a></li>"); }else{ $("#page_list").append("<li class='paginate_button' aria-controls='example' tabindex='0' id='example_previous'><a href='"+url_index+"'>首頁(yè)</a></li>"); $("#page_list").append("<li class='paginate_button' aria-controls='example' tabindex='0' id='example_previous'><a href='"+url_pre+"'>上一頁(yè)</a></li>"); } for(var i=0; i<page_number; i++){ if(i>4){ $("#page_list").append("<li class='paginate_button' aria-controls='example' tabindex='0' id='example_next'><a href='"+url_last+"'>..."+page_number+"</a></li>"); break; } var j=i+1; var url=IFRAME_SRC+'/p/'+j; if(page==j){ $("#page_list").append("<li class='paginate_button active' aria-controls='example' tabindex='0'><a href='"+url+"'>"+j+"</a></li>"); }else{ $("#page_list").append("<li class='paginate_button' aria-controls='example' tabindex='0'><a href='"+url+"'>"+j+"</a></li>"); } } page=parseInt(page); var page_next=page+1; var url_next=IFRAME_SRC+'/p/'+page_next; if(page==page_number){ //$("#page_list").append("<li class='paginate_button next disabled' aria-controls='example' tabindex='0' id='example_next'><a>下一頁(yè)</a></li>"); }else{ $("#page_list").append("<li class='paginate_button' aria-controls='example' tabindex='0' id='example_next'><a href='"+url_next+"'>下一頁(yè)</a></li>"); $("#page_list").append("<li class='paginate_button' aria-controls='example' tabindex='0' id='example_next'><a href='"+url_last+"'>尾頁(yè)</a></li>"); } }else if(page==page_number-3||page==page_number-2||page==page_number-1||page==page_number){ page=parseInt(page);//將字符串轉(zhuǎn)換為整形 var page_pre=page-1; var url_pre=IFRAME_SRC+'/p/'+page_pre;//上一頁(yè) var url_index=IFRAME_SRC+'/p/'+1;//首頁(yè) var url_last=IFRAME_SRC+'/p/'+page_number;//最后一頁(yè) if(page==1){ //$("#page_list").append("<li class='paginate_button previous disabled' aria-controls='example' tabindex='0' id='example_previous'><a>上一頁(yè)</a></li>"); }else{ $("#page_list").append("<li class='paginate_button' aria-controls='example' tabindex='0' id='example_previous'><a href='"+url_index+"'>首頁(yè)</a></li>"); $("#page_list").append("<li class='paginate_button' aria-controls='example' tabindex='0' id='example_previous'><a href='"+url_pre+"'>上一頁(yè)</a></li>"); } $("#page_list").append("<li class='paginate_button' aria-controls='example' tabindex='0' id='example_next'><a href='"+url_index+"'>"+1+"...</a></li>"); for(var i=page_number-4; i<page_number+1; i++){ var j=i; var url=IFRAME_SRC+'/p/'+j; if(page==j){ $("#page_list").append("<li class='paginate_button active' aria-controls='example' tabindex='0'><a href='"+url+"'>"+j+"</a></li>"); }else{ $("#page_list").append("<li class='paginate_button' aria-controls='example' tabindex='0'><a href='"+url+"'>"+j+"</a></li>"); } } page=parseInt(page); var page_next=page+1; var url_next=IFRAME_SRC+'/p/'+page_next; if(page==page_number){ //$("#page_list").append("<li class='paginate_button next disabled' aria-controls='example' tabindex='0' id='example_next'><a>下一頁(yè)</a></li>"); }else{ $("#page_list").append("<li class='paginate_button' aria-controls='example' tabindex='0' id='example_next'><a href='"+url_next+"'>下一頁(yè)</a></li>"); $("#page_list").append("<li class='paginate_button' aria-controls='example' tabindex='0' id='example_next'><a href='"+url_last+"'>尾頁(yè)</a></li>"); } }else{ page=parseInt(page);//將字符串轉(zhuǎn)換為整形 var page_pre=page-1; var url_pre=IFRAME_SRC+'/p/'+page_pre;//上一頁(yè) var url_index=IFRAME_SRC+'/p/'+1;//首頁(yè) var url_last=IFRAME_SRC+'/p/'+page_number;//最后一頁(yè) if(page==1){ //$("#page_list").append("<li class='paginate_button previous disabled' aria-controls='example' tabindex='0' id='example_previous'><a>上一頁(yè)</a></li>"); }else{ $("#page_list").append("<li class='paginate_button' aria-controls='example' tabindex='0' id='example_previous'><a href='"+url_index+"'>首頁(yè)</a></li>"); $("#page_list").append("<li class='paginate_button' aria-controls='example' tabindex='0' id='example_previous'><a href='"+url_pre+"'>上一頁(yè)</a></li>"); } $("#page_list").append("<li class='paginate_button' aria-controls='example' tabindex='0' id='example_next'><a href='"+url_index+"'>"+1+"...</a></li>"); for(var i=page-3; i<page+2; i++){ var j=i+1; var url=IFRAME_SRC+'/p/'+j; if(page==j){ $("#page_list").append("<li class='paginate_button active' aria-controls='example' tabindex='0'><a href='"+url+"'>"+j+"</a></li>"); }else{ $("#page_list").append("<li class='paginate_button' aria-controls='example' tabindex='0'><a href='"+url+"'>"+j+"</a></li>"); } } $("#page_list").append("<li class='paginate_button' aria-controls='example' tabindex='0' id='example_next'><a href='"+url_last+"'>..."+page_number+"</a></li>"); page=parseInt(page); var page_next=page+1; var url_next=IFRAME_SRC+'/p/'+page_next; if(page==page_number){ //$("#page_list").append("<li class='paginate_button next disabled' aria-controls='example' tabindex='0' id='example_next'><a>下一頁(yè)</a></li>"); }else{ $("#page_list").append("<li class='paginate_button' aria-controls='example' tabindex='0' id='example_next'><a href='"+url_next+"'>下一頁(yè)</a></li>"); $("#page_list").append("<li class='paginate_button' aria-controls='example' tabindex='0' id='example_next'><a href='"+url_last+"'>尾頁(yè)</a></li>"); } } } $("#page_list").append("<span id='goto-page'>到第</span><input id='selcet_page' value='"+page+"'/><span id='go-page'>頁(yè)</span>"); $("#page_list").append("<button type='button' id='change_page'>確定</button>"); } } } //跳轉(zhuǎn)的到某一頁(yè) $(document).on("click","#change_page",function(){ var page_num=$("#selcet_page").val(); page_num=parseInt(page_num);//將字符串轉(zhuǎn)換為整形 //go_text=page_num; //alert(page_num); if(page_num>page_all){ /*$('.success_message').show(); $("#message_info").html('頁(yè)碼超出范圍,請(qǐng)輸入正確頁(yè)碼'); */ alert('頁(yè)碼超出范圍,請(qǐng)輸入正確頁(yè)碼'); return false; } if((/^(\+|-)?\d+$/.test( page_num ))&&page_num>0){ location.href=IFRAME_SRC+"/p/"+page_num; }else{ /* $('.success_message').show(); $("#message_info").html('非法頁(yè)碼,請(qǐng)輸入正確頁(yè)碼');*/ /*alert('非法頁(yè)碼,請(qǐng)輸入正確頁(yè)碼');*/ layer.msg("非法頁(yè)碼,請(qǐng)重新輸入",{time: 2000}); return false; } //$("#selcet_page").html(go_text); }); //獲取url參數(shù) function GetRequest() { var url=location.href; //獲取整個(gè)url var theRequest=new Object(); if (url.indexOf("/") !=-1) { var str=url.substr(7); strs=str.split("/"); for(var i=0; i < strs.length; i ++) { if(i==0){ }else{ theRequest[strs[i]]=decodeURIComponent(strs[i+1]); i=i+1; } } } return theRequest; } //輸入框只能輸入數(shù)字 $(function(){ var bind_name='input'; if (navigator.userAgent.indexOf("MSIE") !=-1) { //ie情況下特殊處理 bind_name='propertychange'; } $('#selcet_page').bind(bind_name,function(){ var value=$("#selcet_page").val(); if((/^(\+|-)?\d+$/.test( value ))&&value>0&&value<(page_all+1)) { } else{ $("#selcet_page").val(""); return false; } }); })HTML代碼:<section class="page mt30 mb30">{php}if(isset($count)){{/php}<div id="page_count" style="display:none;">{$count}</div> <div class="dataTables_paginate paging_simple_numbers col-xs-12 marbtm10" id="example_paginate"> <ul class="pagination" id="page_list"> </ul> </div>{php}}{/php}</section>CSS代碼:#example_paginate{display: inline-block}.pagination>li{ display: inline-block;margin-right: 10px;padding: 5px 10px;cursor: pointer}.pagination>li>a{color: #fff}.pagination>li.active,.pagination>li:hover,#example_next:hover,#example_previous:hover{ background: #fdc74a;}#change_page:hover{background-color:#f26c1d;cursor: pointer}#selcet_page{ background: #fff;padding: 4px 10px;width: 4em;text-align: center;}#example_next,#example_previous{background: #fff}#example_next>a,#example_previous>a{color: #ff9530}#example_next:hover>a,#change_page:hover>a{color: #fff}#change_page{ background-color: #fdc74a;padding: 4px 10px;color: #fff;height: 29px;display: inline-block;margin-left: 10px;}#goto-page{padding-right: 5px;color: #fff;}#go-page{padding-left: 5px;color: #fff;}.shownum{color: #fff;margin-right: 20px;}.shownum>a{padding: 4px 10px;margin-right: 5px}
*請(qǐng)認(rèn)真填寫(xiě)需求信息,我們會(huì)在24小時(shí)內(nèi)與您取得聯(lián)系。