parent
3be4cf4fa8
commit
fdea628154
Binary file not shown.
@ -1,212 +0,0 @@ |
|||||||
package xyz.fycz.myreader.entity; |
|
||||||
|
|
||||||
import java.io.Serializable; |
|
||||||
import java.util.ArrayList; |
|
||||||
|
|
||||||
/** |
|
||||||
* Created by zhao on 2016/11/9. |
|
||||||
* APP通迅录树结构 |
|
||||||
* |
|
||||||
*/ |
|
||||||
|
|
||||||
public class ContactsTree implements Serializable { |
|
||||||
|
|
||||||
private static final long serialVersionUID = 7184368467231587092L; |
|
||||||
|
|
||||||
//根节点赋值字段(部门节点)
|
|
||||||
private String DepartId;//部门id
|
|
||||||
private String DepartName;//部门名
|
|
||||||
private String orgCode; //部门编码
|
|
||||||
private String departOrder; //部门排序
|
|
||||||
private boolean select; |
|
||||||
|
|
||||||
//叶节点赋值字段(个人信息节点)
|
|
||||||
private String id; |
|
||||||
private String userDepartId;//用户所属部门ID
|
|
||||||
private String userDepartName;//用户所属部门名
|
|
||||||
private boolean moreDepartUser;// 用户是否多部门 true是 false不是
|
|
||||||
private boolean transpondPerson;//是否转发人员 true是 false不是
|
|
||||||
private String userName;//用户名
|
|
||||||
private String realName;//姓名
|
|
||||||
private String wholeSpellName;//姓名全拼
|
|
||||||
private String firstLetterName;//拼音首字母 eg:hzh
|
|
||||||
private String mobilePhone;//手机
|
|
||||||
private String sex;//性别
|
|
||||||
private String email;//邮箱
|
|
||||||
|
|
||||||
private ArrayList<ContactsTree> children;//孩子节点
|
|
||||||
|
|
||||||
private ContactsTree parent;//父节点
|
|
||||||
|
|
||||||
public boolean isTranspondPerson() { |
|
||||||
return transpondPerson; |
|
||||||
} |
|
||||||
|
|
||||||
public void setTranspondPerson(boolean transpondPerson) { |
|
||||||
this.transpondPerson = transpondPerson; |
|
||||||
} |
|
||||||
|
|
||||||
public String getId() { |
|
||||||
return id; |
|
||||||
} |
|
||||||
|
|
||||||
public void setId(String id) { |
|
||||||
this.id = id; |
|
||||||
} |
|
||||||
|
|
||||||
public String getDepartOrder() { |
|
||||||
return departOrder; |
|
||||||
} |
|
||||||
|
|
||||||
public String getOrgCode() { |
|
||||||
return orgCode; |
|
||||||
} |
|
||||||
|
|
||||||
public void setDepartOrder(String departOrder) { |
|
||||||
this.departOrder = departOrder; |
|
||||||
} |
|
||||||
|
|
||||||
public void setOrgCode(String orgCode) { |
|
||||||
this.orgCode = orgCode; |
|
||||||
} |
|
||||||
|
|
||||||
public boolean isMoreDepartUser() { |
|
||||||
return moreDepartUser; |
|
||||||
} |
|
||||||
|
|
||||||
public void setMoreDepartUser(boolean moreDepartUser) { |
|
||||||
this.moreDepartUser = moreDepartUser; |
|
||||||
} |
|
||||||
|
|
||||||
public String getUserDepartId() { |
|
||||||
return userDepartId; |
|
||||||
} |
|
||||||
|
|
||||||
public String getUserDepartName() { |
|
||||||
return userDepartName; |
|
||||||
} |
|
||||||
|
|
||||||
public void setUserDepartId(String userDepartId) { |
|
||||||
this.userDepartId = userDepartId; |
|
||||||
} |
|
||||||
|
|
||||||
public void setUserDepartName(String userDepartName) { |
|
||||||
this.userDepartName = userDepartName; |
|
||||||
} |
|
||||||
|
|
||||||
public boolean isSelect() { |
|
||||||
return select; |
|
||||||
} |
|
||||||
|
|
||||||
public void setSelect(boolean select) { |
|
||||||
this.select = select; |
|
||||||
} |
|
||||||
|
|
||||||
public ContactsTree getParent() { |
|
||||||
return parent; |
|
||||||
} |
|
||||||
|
|
||||||
public void setParent(ContactsTree parent) { |
|
||||||
this.parent = parent; |
|
||||||
} |
|
||||||
|
|
||||||
public ContactsTree(){ |
|
||||||
children = new ArrayList<>(); |
|
||||||
} |
|
||||||
|
|
||||||
public String getSex() { |
|
||||||
return sex; |
|
||||||
} |
|
||||||
|
|
||||||
public void setSex(String sex) { |
|
||||||
this.sex = sex; |
|
||||||
} |
|
||||||
|
|
||||||
public String getMobilePhone() { |
|
||||||
return mobilePhone; |
|
||||||
} |
|
||||||
|
|
||||||
public void setMobilePhone(String mobilePhone) { |
|
||||||
this.mobilePhone = mobilePhone; |
|
||||||
} |
|
||||||
|
|
||||||
public ArrayList<ContactsTree> getChildren() { |
|
||||||
return children; |
|
||||||
} |
|
||||||
|
|
||||||
public String getDepartId() { |
|
||||||
return DepartId; |
|
||||||
} |
|
||||||
|
|
||||||
public String getDepartName() { |
|
||||||
return DepartName; |
|
||||||
} |
|
||||||
|
|
||||||
public String getFirstLetterName() { |
|
||||||
return firstLetterName; |
|
||||||
} |
|
||||||
|
|
||||||
public String getRealName() { |
|
||||||
return realName; |
|
||||||
} |
|
||||||
|
|
||||||
public String getUserName() { |
|
||||||
return userName; |
|
||||||
} |
|
||||||
|
|
||||||
public String getWholeSpellName() { |
|
||||||
return wholeSpellName; |
|
||||||
} |
|
||||||
|
|
||||||
public void setChildren(ArrayList<ContactsTree> children) { |
|
||||||
this.children = children; |
|
||||||
} |
|
||||||
|
|
||||||
public void setDepartId(String departId) { |
|
||||||
DepartId = departId; |
|
||||||
} |
|
||||||
|
|
||||||
public void setDepartName(String departName) { |
|
||||||
DepartName = departName; |
|
||||||
} |
|
||||||
|
|
||||||
public void setFirstLetterName(String firstLetterName) { |
|
||||||
this.firstLetterName = firstLetterName; |
|
||||||
} |
|
||||||
|
|
||||||
public void setRealName(String realName) { |
|
||||||
this.realName = realName; |
|
||||||
} |
|
||||||
|
|
||||||
public void setUserName(String userName) { |
|
||||||
this.userName = userName; |
|
||||||
} |
|
||||||
|
|
||||||
public void setWholeSpellName(String wholeSpellName) { |
|
||||||
this.wholeSpellName = wholeSpellName; |
|
||||||
} |
|
||||||
|
|
||||||
public String getEmail() { |
|
||||||
return email; |
|
||||||
} |
|
||||||
|
|
||||||
public void setEmail(String email) { |
|
||||||
this.email = email; |
|
||||||
} |
|
||||||
|
|
||||||
@Override |
|
||||||
public String toString() { |
|
||||||
return "ContactsTree{" + |
|
||||||
"DepartId='" + DepartId + '\'' + |
|
||||||
", DepartName='" + DepartName + '\'' + |
|
||||||
", userName='" + userName + '\'' + |
|
||||||
", realName='" + realName + '\'' + |
|
||||||
", wholeSpellName='" + wholeSpellName + '\'' + |
|
||||||
", firstLetterName='" + firstLetterName + '\'' + |
|
||||||
", mobilePhone='" + mobilePhone + '\'' + |
|
||||||
", sex='" + sex + '\'' + |
|
||||||
", email='" + email + '\'' + |
|
||||||
", children=" + children + |
|
||||||
'}'; |
|
||||||
} |
|
||||||
} |
|
@ -1,36 +0,0 @@ |
|||||||
package xyz.fycz.myreader.entity; |
|
||||||
|
|
||||||
import java.io.Serializable; |
|
||||||
|
|
||||||
|
|
||||||
public class Custom implements Serializable { |
|
||||||
|
|
||||||
private static final long serialVersionUID = 5088810102696918656L; |
|
||||||
|
|
||||||
private String id; |
|
||||||
private String type;//类型
|
|
||||||
|
|
||||||
public String getId() { |
|
||||||
return id; |
|
||||||
} |
|
||||||
|
|
||||||
public String getType() { |
|
||||||
return type; |
|
||||||
} |
|
||||||
|
|
||||||
public void setId(String id) { |
|
||||||
this.id = id; |
|
||||||
} |
|
||||||
|
|
||||||
public void setType(String type) { |
|
||||||
this.type = type; |
|
||||||
} |
|
||||||
|
|
||||||
@Override |
|
||||||
public String toString() { |
|
||||||
return "Custom{" + |
|
||||||
"id='" + id + '\'' + |
|
||||||
", type='" + type + '\'' + |
|
||||||
'}'; |
|
||||||
} |
|
||||||
} |
|
@ -1,201 +0,0 @@ |
|||||||
package xyz.fycz.myreader.entity; |
|
||||||
|
|
||||||
import android.os.Parcel; |
|
||||||
import android.os.Parcelable; |
|
||||||
|
|
||||||
import java.text.ParseException; |
|
||||||
import java.text.SimpleDateFormat; |
|
||||||
import java.util.Date; |
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
public class Time implements Parcelable{ |
|
||||||
private int year; |
|
||||||
private int month; |
|
||||||
private int date; |
|
||||||
private int hour; |
|
||||||
private int minute; |
|
||||||
private int second; |
|
||||||
|
|
||||||
public long getLongTime(){ |
|
||||||
StringBuilder stringBuilder = new StringBuilder(); |
|
||||||
stringBuilder.append(year); |
|
||||||
if(month < 10){ |
|
||||||
stringBuilder.append("0"+month); |
|
||||||
}else { |
|
||||||
stringBuilder.append(month); |
|
||||||
} |
|
||||||
if(date < 10){ |
|
||||||
stringBuilder.append("0" + date); |
|
||||||
}else { |
|
||||||
stringBuilder.append(date); |
|
||||||
} |
|
||||||
if(hour < 10){ |
|
||||||
stringBuilder.append("0" + hour); |
|
||||||
}else { |
|
||||||
stringBuilder.append(hour); |
|
||||||
} |
|
||||||
if(minute < 10){ |
|
||||||
stringBuilder.append("0" + minute); |
|
||||||
}else { |
|
||||||
stringBuilder.append(minute); |
|
||||||
} |
|
||||||
if(second < 10){ |
|
||||||
stringBuilder.append("0" + second); |
|
||||||
}else { |
|
||||||
stringBuilder.append(second); |
|
||||||
} |
|
||||||
SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmss"); |
|
||||||
java.util.Date date = null; |
|
||||||
try { |
|
||||||
date = sdf.parse(stringBuilder.toString()); |
|
||||||
return date.getTime(); |
|
||||||
} catch (ParseException e) { |
|
||||||
e.printStackTrace(); |
|
||||||
return 0; |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
public void init(Date date){ |
|
||||||
year = date.getYear() + 1900; |
|
||||||
month = date.getMonth() + 1; |
|
||||||
this.date = date.getDate(); |
|
||||||
hour = date.getHours(); |
|
||||||
minute = date.getMinutes(); |
|
||||||
second = 0; |
|
||||||
} |
|
||||||
|
|
||||||
public void init(xyz.fycz.myreader.entity.Date date){ |
|
||||||
Date date1 = new Date(); |
|
||||||
year = date.getYear(); |
|
||||||
month = date.getMonth(); |
|
||||||
this.date = date.getDate(); |
|
||||||
hour = date1.getHours(); |
|
||||||
minute = date1.getMinutes(); |
|
||||||
second = 0; |
|
||||||
} |
|
||||||
|
|
||||||
public void setToDayZero(){ |
|
||||||
hour = 0; |
|
||||||
minute = 0; |
|
||||||
second = 0; |
|
||||||
} |
|
||||||
|
|
||||||
public void setToDayLast(){ |
|
||||||
hour = 23; |
|
||||||
minute = 59; |
|
||||||
second = 59; |
|
||||||
} |
|
||||||
|
|
||||||
public void lastMonth(){ |
|
||||||
if(month == 1){ |
|
||||||
month = 12; |
|
||||||
year = year - 1; |
|
||||||
}else { |
|
||||||
month = month - 1; |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
public void nextMonth(){ |
|
||||||
if(month == 12){ |
|
||||||
month = 1; |
|
||||||
year = year + 1; |
|
||||||
}else { |
|
||||||
month = month + 1; |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
public void init(long time){ |
|
||||||
Date date = new Date(time); |
|
||||||
init(date); |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
public int getDate() { |
|
||||||
return date; |
|
||||||
} |
|
||||||
|
|
||||||
public int getHour() { |
|
||||||
return hour; |
|
||||||
} |
|
||||||
|
|
||||||
public int getMinute() { |
|
||||||
return minute; |
|
||||||
} |
|
||||||
|
|
||||||
public int getMonth() { |
|
||||||
return month; |
|
||||||
} |
|
||||||
|
|
||||||
public int getSecond() { |
|
||||||
return second; |
|
||||||
} |
|
||||||
|
|
||||||
public int getYear() { |
|
||||||
return year; |
|
||||||
} |
|
||||||
|
|
||||||
public void setDate(int date) { |
|
||||||
this.date = date; |
|
||||||
} |
|
||||||
|
|
||||||
public void setHour(int hour) { |
|
||||||
this.hour = hour; |
|
||||||
} |
|
||||||
|
|
||||||
public void setMinute(int minute) { |
|
||||||
this.minute = minute; |
|
||||||
} |
|
||||||
|
|
||||||
public void setMonth(int month) { |
|
||||||
this.month = month; |
|
||||||
} |
|
||||||
|
|
||||||
public void setSecond(int second) { |
|
||||||
this.second = second; |
|
||||||
} |
|
||||||
|
|
||||||
public void setYear(int year) { |
|
||||||
this.year = year; |
|
||||||
} |
|
||||||
|
|
||||||
@Override |
|
||||||
public int describeContents() { |
|
||||||
return 0; |
|
||||||
} |
|
||||||
|
|
||||||
@Override |
|
||||||
public void writeToParcel(Parcel dest, int flags) { |
|
||||||
dest.writeInt(this.year); |
|
||||||
dest.writeInt(this.month); |
|
||||||
dest.writeInt(this.date); |
|
||||||
dest.writeInt(this.hour); |
|
||||||
dest.writeInt(this.minute); |
|
||||||
dest.writeInt(this.second); |
|
||||||
} |
|
||||||
|
|
||||||
public Time() { |
|
||||||
} |
|
||||||
|
|
||||||
protected Time(Parcel in) { |
|
||||||
this.year = in.readInt(); |
|
||||||
this.month = in.readInt(); |
|
||||||
this.date = in.readInt(); |
|
||||||
this.hour = in.readInt(); |
|
||||||
this.minute = in.readInt(); |
|
||||||
this.second = in.readInt(); |
|
||||||
} |
|
||||||
|
|
||||||
public static final Creator<Time> CREATOR = new Creator<Time>() { |
|
||||||
@Override |
|
||||||
public Time createFromParcel(Parcel source) { |
|
||||||
return new Time(source); |
|
||||||
} |
|
||||||
|
|
||||||
@Override |
|
||||||
public Time[] newArray(int size) { |
|
||||||
return new Time[size]; |
|
||||||
} |
|
||||||
}; |
|
||||||
} |
|
@ -1,37 +0,0 @@ |
|||||||
package xyz.fycz.myreader.entity; |
|
||||||
|
|
||||||
import java.io.Serializable; |
|
||||||
|
|
||||||
|
|
||||||
public class UpdateInfo implements Serializable{ |
|
||||||
|
|
||||||
private static final long serialVersionUID = 8136214121542689902L; |
|
||||||
|
|
||||||
private int newestVersionCode; |
|
||||||
private String newestVersionName; |
|
||||||
private String downLoadUrl; |
|
||||||
|
|
||||||
public int getNewestVersionCode() { |
|
||||||
return newestVersionCode; |
|
||||||
} |
|
||||||
|
|
||||||
public void setNewestVersionCode(int newestVersionCode) { |
|
||||||
this.newestVersionCode = newestVersionCode; |
|
||||||
} |
|
||||||
|
|
||||||
public String getNewestVersionName() { |
|
||||||
return newestVersionName; |
|
||||||
} |
|
||||||
|
|
||||||
public void setNewestVersionName(String newestVersionName) { |
|
||||||
this.newestVersionName = newestVersionName; |
|
||||||
} |
|
||||||
|
|
||||||
public String getDownLoadUrl() { |
|
||||||
return downLoadUrl; |
|
||||||
} |
|
||||||
|
|
||||||
public void setDownLoadUrl(String downLoadUrl) { |
|
||||||
this.downLoadUrl = downLoadUrl; |
|
||||||
} |
|
||||||
} |
|
@ -1,200 +0,0 @@ |
|||||||
package xyz.fycz.myreader.model.audio; |
|
||||||
|
|
||||||
import android.app.Service; |
|
||||||
import android.content.Context; |
|
||||||
import android.content.Intent; |
|
||||||
import android.os.Build; |
|
||||||
import android.os.IBinder; |
|
||||||
import android.speech.tts.TextToSpeech; |
|
||||||
import android.speech.tts.UtteranceProgressListener; |
|
||||||
import android.text.TextUtils; |
|
||||||
|
|
||||||
import androidx.annotation.Nullable; |
|
||||||
|
|
||||||
import java.util.ArrayList; |
|
||||||
import java.util.HashMap; |
|
||||||
import java.util.List; |
|
||||||
import java.util.Locale; |
|
||||||
|
|
||||||
import xyz.fycz.myreader.util.ToastUtils; |
|
||||||
|
|
||||||
import static android.text.TextUtils.isEmpty; |
|
||||||
|
|
||||||
public class ReadService extends Service { |
|
||||||
private static final String TAG = "ReadService"; |
|
||||||
public static Boolean running = false; |
|
||||||
public static final String ActionNewRead = "newRead"; |
|
||||||
private Boolean speak = true; |
|
||||||
private Boolean pause = false; |
|
||||||
private List<String> contentList = new ArrayList<>(); |
|
||||||
private int nowSpeak; |
|
||||||
private int speechRate; |
|
||||||
private String title; |
|
||||||
private String text; |
|
||||||
private int readAloudNumber; |
|
||||||
private int progress; |
|
||||||
private Boolean ttsInitSuccess = false; |
|
||||||
private TextToSpeech textToSpeech; |
|
||||||
private HashMap mParams; |
|
||||||
|
|
||||||
@Nullable |
|
||||||
@Override |
|
||||||
public IBinder onBind(Intent intent) { |
|
||||||
return null; |
|
||||||
} |
|
||||||
|
|
||||||
@Override |
|
||||||
public void onCreate() { |
|
||||||
super.onCreate(); |
|
||||||
} |
|
||||||
|
|
||||||
@Override |
|
||||||
public int onStartCommand(Intent intent, int flags, int startId) { |
|
||||||
if (intent != null) { |
|
||||||
String action = intent.getAction(); |
|
||||||
if (action != null) { |
|
||||||
switch (action) { |
|
||||||
case ActionNewRead: |
|
||||||
newReadAloud(intent.getStringExtra("content"), |
|
||||||
intent.getStringExtra("title"), |
|
||||||
intent.getStringExtra("text"), |
|
||||||
intent.getIntExtra("progress", 0)); |
|
||||||
break; |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
return super.onStartCommand(intent, flags, startId); |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@Override |
|
||||||
public void onDestroy() { |
|
||||||
super.onDestroy(); |
|
||||||
} |
|
||||||
|
|
||||||
private void initTTS() { |
|
||||||
if (textToSpeech == null) |
|
||||||
textToSpeech = new TextToSpeech(this, status -> { |
|
||||||
if (status == TextToSpeech.SUCCESS) { |
|
||||||
textToSpeech.setLanguage(Locale.CHINA); |
|
||||||
textToSpeech.setOnUtteranceProgressListener(new ttsUtteranceListener()); |
|
||||||
ttsInitSuccess = true; |
|
||||||
playTTS(); |
|
||||||
} else { |
|
||||||
ToastUtils.showError("TTS初始化失败!"); |
|
||||||
ReadService.this.stopSelf(); |
|
||||||
} |
|
||||||
}); |
|
||||||
if (mParams == null) { |
|
||||||
mParams = new HashMap(); |
|
||||||
mParams.put(TextToSpeech.Engine.KEY_PARAM_STREAM, "3"); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* 朗读监听 |
|
||||||
*/ |
|
||||||
private class ttsUtteranceListener extends UtteranceProgressListener { |
|
||||||
|
|
||||||
@Override |
|
||||||
public void onStart(String s) { |
|
||||||
//updateMediaSessionPlaybackState();
|
|
||||||
//RxBus.get().post(RxBusTag.READ_ALOUD_START, readAloudNumber + 1);
|
|
||||||
//RxBus.get().post(RxBusTag.READ_ALOUD_NUMBER, readAloudNumber + 1);
|
|
||||||
} |
|
||||||
|
|
||||||
@Override |
|
||||||
public void onDone(String s) { |
|
||||||
readAloudNumber = readAloudNumber + contentList.get(nowSpeak).length() + 1; |
|
||||||
nowSpeak = nowSpeak + 1; |
|
||||||
if (nowSpeak >= contentList.size()) { |
|
||||||
//RxBus.get().post(RxBusTag.ALOUD_STATE, Status.NEXT);
|
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
@Override |
|
||||||
public void onError(String s) { |
|
||||||
//pauseReadAloud(true);
|
|
||||||
//RxBus.get().post(RxBusTag.ALOUD_STATE, Status.PAUSE);
|
|
||||||
} |
|
||||||
|
|
||||||
@Override |
|
||||||
public void onRangeStart(String utteranceId, int start, int end, int frame) { |
|
||||||
super.onRangeStart(utteranceId, start, end, frame); |
|
||||||
//RxBus.get().post(RxBusTag.READ_ALOUD_NUMBER, readAloudNumber + start);
|
|
||||||
} |
|
||||||
} |
|
||||||
/** |
|
||||||
* 朗读 |
|
||||||
*/ |
|
||||||
public static void play(Context context, String content, String title, String text, int progress) { |
|
||||||
Intent readAloudIntent = new Intent(context, ReadService.class); |
|
||||||
readAloudIntent.setAction(ActionNewRead); |
|
||||||
readAloudIntent.putExtra("content", content); |
|
||||||
readAloudIntent.putExtra("title", title); |
|
||||||
readAloudIntent.putExtra("text", text); |
|
||||||
readAloudIntent.putExtra("progress", progress); |
|
||||||
context.startService(readAloudIntent); |
|
||||||
} |
|
||||||
|
|
||||||
private void newReadAloud(String content, String title, String text, int progress) { |
|
||||||
if (TextUtils.isEmpty(content)) { |
|
||||||
stopSelf(); |
|
||||||
return; |
|
||||||
} |
|
||||||
this.text = text; |
|
||||||
this.title = title; |
|
||||||
this.progress = progress; |
|
||||||
nowSpeak = 0; |
|
||||||
readAloudNumber = 0; |
|
||||||
contentList.clear(); |
|
||||||
initTTS(); |
|
||||||
String[] splitSpeech = content.split("\n"); |
|
||||||
for (String aSplitSpeech : splitSpeech) { |
|
||||||
if (!isEmpty(aSplitSpeech)) { |
|
||||||
contentList.add(aSplitSpeech); |
|
||||||
} |
|
||||||
} |
|
||||||
if (speak) { |
|
||||||
speak = false; |
|
||||||
pause = false; |
|
||||||
playTTS(); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
private void playTTS() { |
|
||||||
if (contentList.size() < 1) { |
|
||||||
//RxBus.get().post(RxBusTag.ALOUD_STATE, Status.NEXT);
|
|
||||||
return; |
|
||||||
} |
|
||||||
if (ttsInitSuccess && !speak) { |
|
||||||
speak = !speak; |
|
||||||
//RxBus.get().post(RxBusTag.ALOUD_STATE, Status.PLAY);
|
|
||||||
//updateNotification();
|
|
||||||
//initSpeechRate();
|
|
||||||
HashMap<String, String> map = new HashMap<>(); |
|
||||||
map.put(TextToSpeech.Engine.KEY_PARAM_UTTERANCE_ID, "content"); |
|
||||||
for (int i = nowSpeak; i < contentList.size(); i++) { |
|
||||||
if (i == 0) { |
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { |
|
||||||
textToSpeech.speak(contentList.get(i), TextToSpeech.QUEUE_FLUSH, null, "content"); |
|
||||||
} else { |
|
||||||
textToSpeech.speak(contentList.get(i), TextToSpeech.QUEUE_FLUSH, map); |
|
||||||
} |
|
||||||
} else { |
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { |
|
||||||
textToSpeech.speak(contentList.get(i), TextToSpeech.QUEUE_ADD, null, "content"); |
|
||||||
} else { |
|
||||||
textToSpeech.speak(contentList.get(i), TextToSpeech.QUEUE_ADD, map); |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
public enum Status { |
|
||||||
PLAY, STOP, PAUSE, NEXT |
|
||||||
} |
|
||||||
} |
|
@ -0,0 +1,158 @@ |
|||||||
|
package xyz.fycz.myreader.webapi.crawler.read; |
||||||
|
|
||||||
|
import android.text.Html; |
||||||
|
|
||||||
|
import org.jsoup.Jsoup; |
||||||
|
import org.jsoup.nodes.Document; |
||||||
|
import org.jsoup.nodes.Element; |
||||||
|
import org.jsoup.select.Elements; |
||||||
|
|
||||||
|
import java.util.ArrayList; |
||||||
|
import java.util.Collections; |
||||||
|
|
||||||
|
import xyz.fycz.myreader.entity.SearchBookBean; |
||||||
|
import xyz.fycz.myreader.enums.BookSource; |
||||||
|
import xyz.fycz.myreader.greendao.entity.Book; |
||||||
|
import xyz.fycz.myreader.greendao.entity.Chapter; |
||||||
|
import xyz.fycz.myreader.model.mulvalmap.ConcurrentMultiValueMap; |
||||||
|
import xyz.fycz.myreader.webapi.crawler.base.ReadCrawler; |
||||||
|
|
||||||
|
|
||||||
|
public class HongChenReadCrawler implements ReadCrawler { |
||||||
|
public static final String NAME_SPACE = "https://www.zuxs.net"; |
||||||
|
public static final String NOVEL_SEARCH = "https://www.zuxs.net/search.php?key={key}"; |
||||||
|
public static final String CHARSET = "gb2312"; |
||||||
|
public static final String SEARCH_CHARSET = "gbk"; |
||||||
|
|
||||||
|
@Override |
||||||
|
public String getSearchLink() { |
||||||
|
return NOVEL_SEARCH; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public String getCharset() { |
||||||
|
return CHARSET; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public String getNameSpace() { |
||||||
|
return NAME_SPACE; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public Boolean isPost() { |
||||||
|
return false; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public String getSearchCharset() { |
||||||
|
return SEARCH_CHARSET; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 从html中获取章节正文 |
||||||
|
* |
||||||
|
* @param html |
||||||
|
* @return |
||||||
|
*/ |
||||||
|
public String getContentFormHtml(String html) { |
||||||
|
Document doc = Jsoup.parse(html); |
||||||
|
Element divContent = doc.getElementById("txt"); |
||||||
|
if (divContent != null) { |
||||||
|
Elements aDiv = divContent.getElementsByTag("dd"); |
||||||
|
StringBuilder sb = new StringBuilder(); |
||||||
|
Collections.sort(aDiv, (o1, o2) -> Integer.parseInt(o1.attr("data-id")) - |
||||||
|
Integer.parseInt(o2.attr("data-id"))); |
||||||
|
for (int i = 0; i < aDiv.size(); i++) { |
||||||
|
Element dd = aDiv.get(i); |
||||||
|
if (i == aDiv.size() - 1) break; |
||||||
|
sb.append(Html.fromHtml(dd.html()).toString()); |
||||||
|
sb.append("\n"); |
||||||
|
} |
||||||
|
String content = sb.toString(); |
||||||
|
char c = 160; |
||||||
|
String spaec = "" + c; |
||||||
|
content = content.replace(spaec, " "); |
||||||
|
return content; |
||||||
|
} else { |
||||||
|
return ""; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 从html中获取章节列表 |
||||||
|
* |
||||||
|
* @param html |
||||||
|
* @return |
||||||
|
*/ |
||||||
|
public ArrayList<Chapter> getChaptersFromHtml(String html) { |
||||||
|
ArrayList<Chapter> chapters = new ArrayList<>(); |
||||||
|
Document doc = Jsoup.parse(html); |
||||||
|
String readUrl = doc.select("meta[property=og:novel:read_url]").attr("content"); |
||||||
|
Element divList = doc.getElementById("listsss"); |
||||||
|
Elements elementsByTag = divList.getElementsByTag("a"); |
||||||
|
int i = 0; |
||||||
|
for (int j = 0; j < elementsByTag.size(); j++) { |
||||||
|
Element a = elementsByTag.get(j); |
||||||
|
String title = a.text(); |
||||||
|
String url = a.attr("href"); |
||||||
|
Chapter chapter = new Chapter(); |
||||||
|
chapter.setNumber(i++); |
||||||
|
chapter.setTitle(title); |
||||||
|
chapter.setUrl(readUrl + url); |
||||||
|
chapters.add(chapter); |
||||||
|
} |
||||||
|
return chapters; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 从搜索html中得到书列表 |
||||||
|
* |
||||||
|
* @param html |
||||||
|
* @return |
||||||
|
*/ |
||||||
|
/* |
||||||
|
<dl><dt><a href="/zu/1140.html" target="_blank"><img class="lazyimg" data-original="https://www.zuxs.net/files/article/image/0/29/29s.jpg"></a></dt> |
||||||
|
<dd><a href="/zu/1140.html" class="bigpic-book-name" target="_blank"> |
||||||
|
<font style="font-weight:bold;color:#f00">大主宰</font> |
||||||
|
</a> |
||||||
|
<p><a href="/author/%CC%EC%B2%CF%CD%C1%B6%B9.html" target="_blank">天蚕土豆</a> | <a href="/top/8_1.html" |
||||||
|
target="_blank">其他类型</a> | 连载中</p> |
||||||
|
<p class="big-book-info"> 大千世界,位面交汇,万族林立,群雄荟萃,一位位来自下位面的天之至尊,在这无尽世界,演绎着令人向往的传奇,追求着那主宰之路。 |
||||||
|
无尽火域,炎帝执掌,万火焚苍穹。 |
||||||
|
武境之内,武祖之威……</p> |
||||||
|
<p><a href="/zu/1/1140/5284.html" target="_blank" class="red">最近更新 第1598章 邪神陨落(大结局)</a><span>| 09-06 |
||||||
|
05:54更新</span></p> |
||||||
|
</dd> |
||||||
|
</dl> |
||||||
|
*/ |
||||||
|
public ConcurrentMultiValueMap<SearchBookBean, Book> getBooksFromSearchHtml(String html) { |
||||||
|
ConcurrentMultiValueMap<SearchBookBean, Book> books = new ConcurrentMultiValueMap<>(); |
||||||
|
Document doc = Jsoup.parse(html); |
||||||
|
// try {
|
||||||
|
Element div = doc.getElementsByClass("s-b-list").first(); |
||||||
|
Elements dls = div.getElementsByTag("dl"); |
||||||
|
for (Element dl : dls){ |
||||||
|
Elements as = dl.getElementsByTag("a"); |
||||||
|
Book book = new Book(); |
||||||
|
book.setName(as.get(1).text()); |
||||||
|
book.setAuthor(as.get(2).text()); |
||||||
|
book.setType(as.get(3).text()); |
||||||
|
book.setNewestChapterTitle(as.get(4).text().replace("最近更新 ", "")); |
||||||
|
book.setDesc(dl.getElementsByClass("big-book-info").first().text()); |
||||||
|
String imgUrl = dl.getElementsByTag("img").attr("data-original"); |
||||||
|
book.setImgUrl(imgUrl); |
||||||
|
//https://www.zuxs.net/zu/1140.html -> https://www.zuxs.net/zu/1/1140/
|
||||||
|
book.setChapterUrl(NAME_SPACE + as.get(1).attr("href").replace("zu/", "zu/1/").replace(".html", "/")); |
||||||
|
book.setSource(BookSource.hongchen.toString()); |
||||||
|
SearchBookBean sbb = new SearchBookBean(book.getName(), book.getAuthor()); |
||||||
|
books.add(sbb, book); |
||||||
|
} |
||||||
|
// } catch (Exception e) {
|
||||||
|
// e.printStackTrace();
|
||||||
|
// }
|
||||||
|
return books; |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
} |
@ -0,0 +1,210 @@ |
|||||||
|
package xyz.fycz.myreader.webapi.crawler.read; |
||||||
|
|
||||||
|
import android.text.Html; |
||||||
|
|
||||||
|
import org.jsoup.Jsoup; |
||||||
|
import org.jsoup.nodes.Document; |
||||||
|
import org.jsoup.nodes.Element; |
||||||
|
import org.jsoup.select.Elements; |
||||||
|
|
||||||
|
import java.util.ArrayList; |
||||||
|
import java.util.Collections; |
||||||
|
import java.util.Comparator; |
||||||
|
import java.util.regex.Matcher; |
||||||
|
import java.util.regex.Pattern; |
||||||
|
|
||||||
|
import xyz.fycz.myreader.entity.SearchBookBean; |
||||||
|
import xyz.fycz.myreader.enums.BookSource; |
||||||
|
import xyz.fycz.myreader.greendao.entity.Book; |
||||||
|
import xyz.fycz.myreader.greendao.entity.Chapter; |
||||||
|
import xyz.fycz.myreader.model.mulvalmap.ConcurrentMultiValueMap; |
||||||
|
import xyz.fycz.myreader.webapi.crawler.base.ReadCrawler; |
||||||
|
|
||||||
|
|
||||||
|
public class LaoYaoReadCrawler implements ReadCrawler { |
||||||
|
public static final String NAME_SPACE = "https://www.laoyao.org"; |
||||||
|
public static final String NOVEL_SEARCH = "https://www.laoyao.org/search.php?key={key}"; |
||||||
|
public static final String CHARSET = "UTF-8"; |
||||||
|
public static final String SEARCH_CHARSET = "UTF-8"; |
||||||
|
|
||||||
|
@Override |
||||||
|
public String getSearchLink() { |
||||||
|
return NOVEL_SEARCH; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public String getCharset() { |
||||||
|
return CHARSET; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public String getNameSpace() { |
||||||
|
return NAME_SPACE; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public Boolean isPost() { |
||||||
|
return false; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public String getSearchCharset() { |
||||||
|
return SEARCH_CHARSET; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 从html中获取章节正文 |
||||||
|
* |
||||||
|
* @param html |
||||||
|
* @return |
||||||
|
*/ |
||||||
|
public String getContentFormHtml(String html) { |
||||||
|
Document doc = Jsoup.parse(html); |
||||||
|
Element divContent = doc.getElementById("txt"); |
||||||
|
if (divContent != null) { |
||||||
|
Elements aDiv = divContent.getElementsByTag("dd"); |
||||||
|
StringBuilder sb = new StringBuilder(); |
||||||
|
Collections.sort(aDiv, (o1, o2) -> Integer.parseInt(o1.attr("data-id")) - |
||||||
|
Integer.parseInt(o2.attr("data-id"))); |
||||||
|
for (int i = 0; i < aDiv.size(); i++) { |
||||||
|
Element dd = aDiv.get(i); |
||||||
|
if (i == aDiv.size() - 1) break; |
||||||
|
sb.append(Html.fromHtml(dd.html()).toString()); |
||||||
|
sb.append("\n"); |
||||||
|
} |
||||||
|
String content = sb.toString(); |
||||||
|
char c = 160; |
||||||
|
String spaec = "" + c; |
||||||
|
content = content.replace(spaec, " "); |
||||||
|
return content; |
||||||
|
} else { |
||||||
|
return ""; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 从html中获取章节列表 |
||||||
|
* |
||||||
|
* @param html |
||||||
|
* @return |
||||||
|
*/ |
||||||
|
public ArrayList<Chapter> getChaptersFromHtml(String html) { |
||||||
|
ArrayList<Chapter> chapters = new ArrayList<>(); |
||||||
|
Document doc = Jsoup.parse(html); |
||||||
|
String readUrl = doc.select("meta[property=og:novel:read_url]").attr("content"); |
||||||
|
Element divList = doc.getElementById("newlist"); |
||||||
|
Elements elementsByTag = divList.getElementsByTag("a"); |
||||||
|
int i = 0; |
||||||
|
for (int j = 0; j < elementsByTag.size(); j++) { |
||||||
|
Element a = elementsByTag.get(j); |
||||||
|
String title = a.text(); |
||||||
|
String url = a.attr("href"); |
||||||
|
Chapter chapter = new Chapter(); |
||||||
|
chapter.setNumber(i++); |
||||||
|
chapter.setTitle(title); |
||||||
|
chapter.setUrl(readUrl + url); |
||||||
|
chapters.add(chapter); |
||||||
|
} |
||||||
|
return chapters; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 从搜索html中得到书列表 |
||||||
|
* |
||||||
|
* @param html |
||||||
|
* @return |
||||||
|
*/ |
||||||
|
/* |
||||||
|
<li><a href="/info/6690.html" target="_blank" class="book_cov" title="大主宰"><img src="/public/images/default.jpg" |
||||||
|
data-original="//www.laoyao.org/files/article/image/0/24/24s.jpg" class="lazyload_book_cover" alt="大主宰" /></a> |
||||||
|
<div class="book_inf"> |
||||||
|
<h3><a href="/info/6690.html" title="大主宰" target="_blank" mod="data_book_name"> |
||||||
|
<font style="font-weight:bold;color:#f00">大主宰</font> |
||||||
|
</a></h3> |
||||||
|
<p class="tags"><span>作者:<a href="/creator/%E5%A4%A9%E8%9A%95%E5%9C%9F%E8%B1%86.html" title="天蚕土豆">天蚕土豆</a></span><span>分类:<a |
||||||
|
href="/library/8_0_0_0_0_1.html" target="_blank">名著经典</a></span><span>状态:连载中</span><span>总字数:2498万字+</span></p> |
||||||
|
<p><b>最近更新:</b><a href="/list/6690/21939.html" title="第1598章 邪神陨落(大结局)" target="_blank">第1598章 邪神陨落(大结局)</a></p> |
||||||
|
<p class="int"> 大千世界,位面交汇,万族林立,群雄荟萃,一位位来自下位面的天之至尊,在这无尽世界,演绎着令人向往的传奇,追求着那主宰之路。 |
||||||
|
无尽火域,炎帝执掌,万火焚苍穹。 |
||||||
|
武境之内,武祖之威,震慑乾坤。 |
||||||
|
西天之殿,百战之皇</p> |
||||||
|
</div> |
||||||
|
<div class="right"> |
||||||
|
<span>更新时间:2020-09-06 06:47</span> |
||||||
|
<a href="/info/6690.html" target="_blank" class="read_btn btn">立即阅读</a> |
||||||
|
<a href="javascript:BookCaseAdd('6690');" class="store_btn btn" btn="book_fav">加入书架</a> |
||||||
|
</div> |
||||||
|
</li> |
||||||
|
*/ |
||||||
|
public ConcurrentMultiValueMap<SearchBookBean, Book> getBooksFromSearchHtml(String html) { |
||||||
|
ConcurrentMultiValueMap<SearchBookBean, Book> books = new ConcurrentMultiValueMap<>(); |
||||||
|
Document doc = Jsoup.parse(html); |
||||||
|
// try {
|
||||||
|
String urlType = doc.select("meta[property=og:type]").attr("content"); |
||||||
|
if ("novel".equals(urlType)) { |
||||||
|
String readUrl = doc.select("meta[property=og:novel:read_url]").attr("content"); |
||||||
|
Book book = new Book(); |
||||||
|
book.setChapterUrl(readUrl); |
||||||
|
getBookInfo(doc, book); |
||||||
|
SearchBookBean sbb = new SearchBookBean(book.getName(), book.getAuthor()); |
||||||
|
books.add(sbb, book); |
||||||
|
} else { |
||||||
|
Element div = doc.getElementsByClass("result").first(); |
||||||
|
Elements lis = div.getElementsByTag("li"); |
||||||
|
for (Element li : lis) { |
||||||
|
Elements as = li.getElementsByTag("a"); |
||||||
|
Book book = new Book(); |
||||||
|
book.setName(as.get(1).text()); |
||||||
|
book.setAuthor(as.get(2).text()); |
||||||
|
book.setType(as.get(3).text()); |
||||||
|
book.setNewestChapterTitle(as.get(4).text().replace("最新章节:", "")); |
||||||
|
book.setDesc(li.getElementsByClass("int").first().text()); |
||||||
|
book.setUpdateDate(li.getElementsByClass("right").first().getElementsByTag("span").text()); |
||||||
|
String imgUrl = li.getElementsByTag("img").attr("data-original"); |
||||||
|
book.setImgUrl(!imgUrl.contains("http") ? "https:" + imgUrl : imgUrl); |
||||||
|
book.setChapterUrl(NAME_SPACE + as.get(1).attr("href").replace("info", "list").replace(".html", "/")); |
||||||
|
book.setSource(BookSource.laoyao.toString()); |
||||||
|
SearchBookBean sbb = new SearchBookBean(book.getName(), book.getAuthor()); |
||||||
|
books.add(sbb, book); |
||||||
|
} |
||||||
|
} |
||||||
|
// } catch (Exception e) {
|
||||||
|
// e.printStackTrace();
|
||||||
|
// }
|
||||||
|
return books; |
||||||
|
} |
||||||
|
|
||||||
|
public Book getBookInfo(Document doc, Book book) { |
||||||
|
//小说源
|
||||||
|
book.setSource(BookSource.laoyao.toString()); |
||||||
|
//图片url
|
||||||
|
String imgUrl = doc.select("meta[property=og:image]").attr("content"); |
||||||
|
book.setImgUrl(!imgUrl.contains("http") ? "https:" + imgUrl : imgUrl); |
||||||
|
|
||||||
|
//书名
|
||||||
|
String title = doc.select("meta[property=og:novel:book_name]").attr("content"); |
||||||
|
book.setName(title); |
||||||
|
|
||||||
|
//作者
|
||||||
|
String author = doc.select("meta[property=og:novel:author]").attr("content"); |
||||||
|
book.setAuthor(author); |
||||||
|
|
||||||
|
//更新时间
|
||||||
|
String updateDate = doc.select("meta[property=og:novel:update_time]").attr("content"); |
||||||
|
book.setUpdateDate(updateDate); |
||||||
|
|
||||||
|
//最新章节
|
||||||
|
String newestChapterTitle = doc.select("meta[property=og:novel:latest_chapter_name]").attr("content"); |
||||||
|
book.setNewestChapterTitle(newestChapterTitle); |
||||||
|
|
||||||
|
//类型
|
||||||
|
String type = doc.select("meta[property=og:novel:category]").attr("content"); |
||||||
|
book.setType(type); |
||||||
|
|
||||||
|
//简介
|
||||||
|
String desc = doc.select("meta[property=og:description]").attr("content"); |
||||||
|
book.setDesc(desc); |
||||||
|
return book; |
||||||
|
|
||||||
|
} |
||||||
|
} |
@ -0,0 +1,204 @@ |
|||||||
|
package xyz.fycz.myreader.webapi.crawler.read; |
||||||
|
|
||||||
|
import android.text.Html; |
||||||
|
|
||||||
|
import org.jsoup.Jsoup; |
||||||
|
import org.jsoup.nodes.Document; |
||||||
|
import org.jsoup.nodes.Element; |
||||||
|
import org.jsoup.select.Elements; |
||||||
|
|
||||||
|
import java.util.ArrayList; |
||||||
|
import java.util.Collections; |
||||||
|
|
||||||
|
import xyz.fycz.myreader.entity.SearchBookBean; |
||||||
|
import xyz.fycz.myreader.enums.BookSource; |
||||||
|
import xyz.fycz.myreader.greendao.entity.Book; |
||||||
|
import xyz.fycz.myreader.greendao.entity.Chapter; |
||||||
|
import xyz.fycz.myreader.model.mulvalmap.ConcurrentMultiValueMap; |
||||||
|
import xyz.fycz.myreader.webapi.crawler.base.ReadCrawler; |
||||||
|
|
||||||
|
|
||||||
|
public class ShiGuangReadCrawler implements ReadCrawler { |
||||||
|
public static final String NAME_SPACE = "https://www.youxs.org"; |
||||||
|
public static final String NOVEL_SEARCH = "https://www.youxs.org/search.php?key={key}"; |
||||||
|
public static final String CHARSET = "gbk"; |
||||||
|
public static final String SEARCH_CHARSET = "gbk"; |
||||||
|
|
||||||
|
@Override |
||||||
|
public String getSearchLink() { |
||||||
|
return NOVEL_SEARCH; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public String getCharset() { |
||||||
|
return CHARSET; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public String getNameSpace() { |
||||||
|
return NAME_SPACE; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public Boolean isPost() { |
||||||
|
return false; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public String getSearchCharset() { |
||||||
|
return SEARCH_CHARSET; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 从html中获取章节正文 |
||||||
|
* |
||||||
|
* @param html |
||||||
|
* @return |
||||||
|
*/ |
||||||
|
public String getContentFormHtml(String html) { |
||||||
|
Document doc = Jsoup.parse(html); |
||||||
|
Element divContent = doc.getElementById("txt"); |
||||||
|
if (divContent != null) { |
||||||
|
Elements aDiv = divContent.getElementsByTag("dd"); |
||||||
|
StringBuilder sb = new StringBuilder(); |
||||||
|
Collections.sort(aDiv, (o1, o2) -> Integer.parseInt(o1.attr("data-id")) - |
||||||
|
Integer.parseInt(o2.attr("data-id"))); |
||||||
|
for (int i = 0; i < aDiv.size(); i++) { |
||||||
|
Element dd = aDiv.get(i); |
||||||
|
if (i == aDiv.size() - 1) break; |
||||||
|
sb.append(Html.fromHtml(dd.html()).toString()); |
||||||
|
sb.append("\n"); |
||||||
|
} |
||||||
|
String content = sb.toString(); |
||||||
|
char c = 160; |
||||||
|
String spaec = "" + c; |
||||||
|
content = content.replace(spaec, " "); |
||||||
|
return content; |
||||||
|
} else { |
||||||
|
return ""; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 从html中获取章节列表 |
||||||
|
* |
||||||
|
* @param html |
||||||
|
* @return |
||||||
|
*/ |
||||||
|
public ArrayList<Chapter> getChaptersFromHtml(String html) { |
||||||
|
ArrayList<Chapter> chapters = new ArrayList<>(); |
||||||
|
Document doc = Jsoup.parse(html); |
||||||
|
Element divList = doc.getElementById("listsss"); |
||||||
|
Elements elementsByTag = divList.getElementsByTag("a"); |
||||||
|
int i = 0; |
||||||
|
for (int j = 0; j < elementsByTag.size(); j++) { |
||||||
|
Element a = elementsByTag.get(j); |
||||||
|
String title = a.text(); |
||||||
|
String url = a.attr("href"); |
||||||
|
Chapter chapter = new Chapter(); |
||||||
|
chapter.setNumber(i++); |
||||||
|
chapter.setTitle(title); |
||||||
|
chapter.setUrl(NAME_SPACE + url); |
||||||
|
chapters.add(chapter); |
||||||
|
} |
||||||
|
return chapters; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 从搜索html中得到书列表 |
||||||
|
* |
||||||
|
* @param html |
||||||
|
* @return |
||||||
|
*/ |
||||||
|
/* |
||||||
|
<li><a href="/wuxian/4/4473/" target="_blank" class="book_cov" title="大主宰"><img src="/public/images/default.jpg" |
||||||
|
data-original="https://www.youxs.org/files/article/image/0/29/29s.jpg" class="lazyload_book_cover" alt="大主宰" /></a> |
||||||
|
<div class="book_inf"> |
||||||
|
<h3><a href="/wuxian/4/4473/" title="大主宰" target="_blank" mod="data_book_name"> |
||||||
|
<font style="font-weight:bold;color:#f00">大主宰</font> |
||||||
|
</a></h3> |
||||||
|
<p class="tags"><span>作者:<a title="天蚕土豆">天蚕土豆</a></span><span>分类:<a href="/liebiao/8_0_0_0_0_1.html" target="_blank">网络文学</a></span><span>状态:连载中</span><span>总字数:2497万字+</span></p> |
||||||
|
<p><b>最近更新:</b><a href="/wuxian/4/4473/15283.html" title="第1598章 邪神陨落(大结局)" target="_blank">第1598章 邪神陨落(大结局)</a></p> |
||||||
|
<p class="int"> 大千世界,位面交汇,万族林立,群雄荟萃,一位位来自下位面的天之至尊,在这无尽世界,演绎着令人向往的传奇,追求着那主宰之路。 |
||||||
|
无尽火域,炎帝执掌,万火焚苍穹。 |
||||||
|
武境之内,武祖之威</p> |
||||||
|
</div> |
||||||
|
<div class="right"> |
||||||
|
<span>更新时间:09-06 05:25</span> |
||||||
|
<a href="/wuxian/4/4473/" target="_blank" class="read_btn btn">立即阅读</a> |
||||||
|
<a href="javascript:BookCaseAdd('4473');" class="store_btn btn" btn="book_fav">加入书架</a> |
||||||
|
</div> |
||||||
|
</li> |
||||||
|
*/ |
||||||
|
public ConcurrentMultiValueMap<SearchBookBean, Book> getBooksFromSearchHtml(String html) { |
||||||
|
ConcurrentMultiValueMap<SearchBookBean, Book> books = new ConcurrentMultiValueMap<>(); |
||||||
|
Document doc = Jsoup.parse(html); |
||||||
|
// try {
|
||||||
|
String urlType = doc.select("meta[property=og:type]").attr("content"); |
||||||
|
if ("novel".equals(urlType)) { |
||||||
|
String readUrl = doc.select("meta[property=og:novel:read_url]").attr("content"); |
||||||
|
Book book = new Book(); |
||||||
|
book.setChapterUrl(readUrl); |
||||||
|
getBookInfo(doc, book); |
||||||
|
SearchBookBean sbb = new SearchBookBean(book.getName(), book.getAuthor()); |
||||||
|
books.add(sbb, book); |
||||||
|
} else { |
||||||
|
Element div = doc.getElementsByClass("result").first(); |
||||||
|
Elements lis = div.getElementsByTag("li"); |
||||||
|
for (Element li : lis) { |
||||||
|
Elements as = li.getElementsByTag("a"); |
||||||
|
Book book = new Book(); |
||||||
|
book.setName(as.get(1).text()); |
||||||
|
book.setAuthor(as.get(2).text()); |
||||||
|
book.setType(as.get(3).text()); |
||||||
|
book.setNewestChapterTitle(as.get(4).text().replace("最新章节:", "")); |
||||||
|
book.setDesc(li.getElementsByClass("int").first().text()); |
||||||
|
book.setUpdateDate(li.getElementsByClass("right").first().getElementsByTag("span").text()); |
||||||
|
String imgUrl = li.getElementsByTag("img").attr("data-original"); |
||||||
|
book.setImgUrl(imgUrl); |
||||||
|
book.setChapterUrl(NAME_SPACE + as.get(1).attr("href")); |
||||||
|
book.setSource(BookSource.shiguang.toString()); |
||||||
|
SearchBookBean sbb = new SearchBookBean(book.getName(), book.getAuthor()); |
||||||
|
books.add(sbb, book); |
||||||
|
} |
||||||
|
} |
||||||
|
// } catch (Exception e) {
|
||||||
|
// e.printStackTrace();
|
||||||
|
// }
|
||||||
|
return books; |
||||||
|
} |
||||||
|
|
||||||
|
public Book getBookInfo(Document doc, Book book) { |
||||||
|
//小说源
|
||||||
|
book.setSource(BookSource.shiguang.toString()); |
||||||
|
//图片url
|
||||||
|
String imgUrl = doc.select("meta[property=og:image]").attr("content"); |
||||||
|
book.setImgUrl(imgUrl); |
||||||
|
|
||||||
|
//书名
|
||||||
|
String title = doc.select("meta[property=og:novel:book_name]").attr("content"); |
||||||
|
book.setName(title); |
||||||
|
|
||||||
|
//作者
|
||||||
|
String author = doc.select("meta[property=og:novel:author]").attr("content"); |
||||||
|
book.setAuthor(author); |
||||||
|
|
||||||
|
//更新时间
|
||||||
|
String updateDate = doc.select("meta[property=og:novel:update_time]").attr("content"); |
||||||
|
book.setUpdateDate(updateDate); |
||||||
|
|
||||||
|
//最新章节
|
||||||
|
String newestChapterTitle = doc.select("meta[property=og:novel:latest_chapter_name]").attr("content"); |
||||||
|
book.setNewestChapterTitle(newestChapterTitle); |
||||||
|
|
||||||
|
//类型
|
||||||
|
String type = doc.select("meta[property=og:novel:category]").attr("content"); |
||||||
|
book.setType(type); |
||||||
|
|
||||||
|
//简介
|
||||||
|
String desc = doc.select("meta[property=og:description]").attr("content"); |
||||||
|
book.setDesc(desc); |
||||||
|
return book; |
||||||
|
|
||||||
|
} |
||||||
|
} |
@ -0,0 +1,166 @@ |
|||||||
|
package xyz.fycz.myreader.webapi.crawler.read; |
||||||
|
|
||||||
|
import android.text.Html; |
||||||
|
|
||||||
|
import org.jsoup.Jsoup; |
||||||
|
import org.jsoup.nodes.Document; |
||||||
|
import org.jsoup.nodes.Element; |
||||||
|
import org.jsoup.select.Elements; |
||||||
|
|
||||||
|
import java.util.ArrayList; |
||||||
|
import java.util.Collections; |
||||||
|
|
||||||
|
import xyz.fycz.myreader.entity.SearchBookBean; |
||||||
|
import xyz.fycz.myreader.enums.BookSource; |
||||||
|
import xyz.fycz.myreader.greendao.entity.Book; |
||||||
|
import xyz.fycz.myreader.greendao.entity.Chapter; |
||||||
|
import xyz.fycz.myreader.model.mulvalmap.ConcurrentMultiValueMap; |
||||||
|
import xyz.fycz.myreader.webapi.crawler.base.ReadCrawler; |
||||||
|
|
||||||
|
|
||||||
|
public class XiaGuReadCrawler implements ReadCrawler { |
||||||
|
public static final String NAME_SPACE = "https://www.xiagu.org"; |
||||||
|
public static final String NOVEL_SEARCH = "https://www.xiagu.org/search/?keyword={key}&t=0"; |
||||||
|
public static final String CHARSET = "UTF-8"; |
||||||
|
public static final String SEARCH_CHARSET = "UTF-8"; |
||||||
|
|
||||||
|
@Override |
||||||
|
public String getSearchLink() { |
||||||
|
return NOVEL_SEARCH; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public String getCharset() { |
||||||
|
return CHARSET; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public String getNameSpace() { |
||||||
|
return NAME_SPACE; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public Boolean isPost() { |
||||||
|
return false; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public String getSearchCharset() { |
||||||
|
return SEARCH_CHARSET; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 从html中获取章节正文 |
||||||
|
* |
||||||
|
* @param html |
||||||
|
* @return |
||||||
|
*/ |
||||||
|
public String getContentFormHtml(String html) { |
||||||
|
Document doc = Jsoup.parse(html); |
||||||
|
Element divContent = doc.getElementById("txt"); |
||||||
|
if (divContent != null) { |
||||||
|
Elements aDiv = divContent.getElementsByTag("dd"); |
||||||
|
StringBuilder sb = new StringBuilder(); |
||||||
|
Collections.sort(aDiv, (o1, o2) -> Integer.parseInt(o1.attr("data-id")) - |
||||||
|
Integer.parseInt(o2.attr("data-id"))); |
||||||
|
for (int i = 0; i < aDiv.size(); i++) { |
||||||
|
Element dd = aDiv.get(i); |
||||||
|
if (i == aDiv.size() - 1) break; |
||||||
|
sb.append(Html.fromHtml(dd.html()).toString()); |
||||||
|
sb.append("\n"); |
||||||
|
} |
||||||
|
String content = sb.toString(); |
||||||
|
char c = 160; |
||||||
|
String spaec = "" + c; |
||||||
|
content = content.replace(spaec, " "); |
||||||
|
return content; |
||||||
|
} else { |
||||||
|
return ""; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 从html中获取章节列表 |
||||||
|
* |
||||||
|
* @param html |
||||||
|
* @return |
||||||
|
*/ |
||||||
|
public ArrayList<Chapter> getChaptersFromHtml(String html) { |
||||||
|
ArrayList<Chapter> chapters = new ArrayList<>(); |
||||||
|
Document doc = Jsoup.parse(html); |
||||||
|
String readUrl = doc.select("meta[property=og:novel:read_url]").attr("content"); |
||||||
|
Element divList = doc.getElementById("listsss"); |
||||||
|
Elements elementsByTag = divList.getElementsByTag("a"); |
||||||
|
int i = 0; |
||||||
|
for (int j = 0; j < elementsByTag.size(); j++) { |
||||||
|
Element a = elementsByTag.get(j); |
||||||
|
String title = a.text(); |
||||||
|
String url = a.attr("href"); |
||||||
|
Chapter chapter = new Chapter(); |
||||||
|
chapter.setNumber(i++); |
||||||
|
chapter.setTitle(title); |
||||||
|
chapter.setUrl(readUrl + url); |
||||||
|
chapters.add(chapter); |
||||||
|
} |
||||||
|
return chapters; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 从搜索html中得到书列表 |
||||||
|
* |
||||||
|
* @param html |
||||||
|
* @return |
||||||
|
*/ |
||||||
|
/* |
||||||
|
<li class="subject-item"> |
||||||
|
<div class="pic"> |
||||||
|
<a class="nbg" href="/xs/5584.html" ><img class="" data-original="//www.xiagu.org/files/article/image/0/29/29s.jpg" src="/statics/images/default.jpg" width="90"></a> |
||||||
|
</div> |
||||||
|
<div class="info"> |
||||||
|
<h2 class=""><a href="/xs/5584.html"><font style="font-weight:bold;color:#f00">大主宰</font></a></h2> |
||||||
|
<div class="pub">作者:<a target="_blank" href="/author/id/186.html">天蚕土豆</a> / 类型:<a target="_blank" href="/shuku/8_0_0_0_0_1.html">其他类型</a> / 2020-09-06 / 连载中 / 2497.0808万字</div> |
||||||
|
|
||||||
|
<p>【内容简介】 大千世界,位面交汇,万族林立,群雄荟萃,一位位来自下位面的天之至尊,在这无尽世界,演绎着令人向往的传奇,追求着那主宰之路。<br /> |
||||||
|
无尽火域,炎帝执掌,万火焚苍穹。<br /> |
||||||
|
武境之内,武祖之威... </p> |
||||||
|
<div class="ft"> |
||||||
|
|
||||||
|
<div class="pub">角色:牧尘,唐芊儿,红绫,牧哥,苏凌,刘彻,柳阳,牧锋,芊儿,柳慕白,薛东,童哥,柳眉,唐芊儿蹙,姬玄,牧哥比,那柳阳,乐乐,凌撇,杨柳,林修,牧尘沉,莫师,代柳阳</div> |
||||||
|
<div class="cart-actions"> |
||||||
|
<span class="market-info"><a href="/read/5/5584/" target="_blank">【最新章节】第1598章 邪神陨落(大结局)</a></span> |
||||||
|
</div> |
||||||
|
<div class="ebook-link"><a target="_blank" href="/xs/5584.html">详细介绍</a></div> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
</li> |
||||||
|
*/ |
||||||
|
public ConcurrentMultiValueMap<SearchBookBean, Book> getBooksFromSearchHtml(String html) { |
||||||
|
ConcurrentMultiValueMap<SearchBookBean, Book> books = new ConcurrentMultiValueMap<>(); |
||||||
|
Document doc = Jsoup.parse(html); |
||||||
|
// try {
|
||||||
|
Element div = doc.getElementsByClass("subject-list").first(); |
||||||
|
Elements lis = div.getElementsByTag("li"); |
||||||
|
for (Element li : lis){ |
||||||
|
Elements as = li.getElementsByTag("a"); |
||||||
|
Book book = new Book(); |
||||||
|
book.setName(as.get(1).text()); |
||||||
|
book.setAuthor(as.get(2).text()); |
||||||
|
book.setType(as.get(3).text()); |
||||||
|
book.setNewestChapterTitle(as.get(4).text().replace("【最新章节】", "")); |
||||||
|
book.setDesc(li.getElementsByTag("p").first().text()); |
||||||
|
String imgUrl = li.getElementsByTag("img").attr("data-original"); |
||||||
|
book.setImgUrl(!imgUrl.contains("http") ? "https:" + imgUrl : imgUrl); |
||||||
|
//https://www.xiagu.org/xs/5584.html -> https://www.xiagu.org/read/5/5584/
|
||||||
|
book.setChapterUrl(NAME_SPACE + as.get(1).attr("href").replace("xs", "read/1").replace(".html", "/")); |
||||||
|
book.setSource(BookSource.xiagu.toString()); |
||||||
|
SearchBookBean sbb = new SearchBookBean(book.getName(), book.getAuthor()); |
||||||
|
books.add(sbb, book); |
||||||
|
} |
||||||
|
// } catch (Exception e) {
|
||||||
|
// e.printStackTrace();
|
||||||
|
// }
|
||||||
|
return books; |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
} |
@ -0,0 +1,158 @@ |
|||||||
|
package xyz.fycz.myreader.webapi.crawler.read; |
||||||
|
|
||||||
|
import android.text.Html; |
||||||
|
|
||||||
|
import org.jsoup.Jsoup; |
||||||
|
import org.jsoup.nodes.Document; |
||||||
|
import org.jsoup.nodes.Element; |
||||||
|
import org.jsoup.select.Elements; |
||||||
|
|
||||||
|
import java.util.ArrayList; |
||||||
|
import java.util.Collections; |
||||||
|
|
||||||
|
import xyz.fycz.myreader.entity.SearchBookBean; |
||||||
|
import xyz.fycz.myreader.enums.BookSource; |
||||||
|
import xyz.fycz.myreader.greendao.entity.Book; |
||||||
|
import xyz.fycz.myreader.greendao.entity.Chapter; |
||||||
|
import xyz.fycz.myreader.model.mulvalmap.ConcurrentMultiValueMap; |
||||||
|
import xyz.fycz.myreader.webapi.crawler.base.ReadCrawler; |
||||||
|
|
||||||
|
|
||||||
|
public class XingXingReadCrawler implements ReadCrawler { |
||||||
|
public static final String NAME_SPACE = "https://www.hs918.com"; |
||||||
|
public static final String NOVEL_SEARCH = "https://www.hs918.com/search.php?key={key}"; |
||||||
|
public static final String CHARSET = "UTF-8"; |
||||||
|
public static final String SEARCH_CHARSET = "UTF-8"; |
||||||
|
|
||||||
|
@Override |
||||||
|
public String getSearchLink() { |
||||||
|
return NOVEL_SEARCH; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public String getCharset() { |
||||||
|
return CHARSET; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public String getNameSpace() { |
||||||
|
return NAME_SPACE; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public Boolean isPost() { |
||||||
|
return false; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public String getSearchCharset() { |
||||||
|
return SEARCH_CHARSET; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 从html中获取章节正文 |
||||||
|
* |
||||||
|
* @param html |
||||||
|
* @return |
||||||
|
*/ |
||||||
|
public String getContentFormHtml(String html) { |
||||||
|
Document doc = Jsoup.parse(html); |
||||||
|
Element divContent = doc.getElementById("txt"); |
||||||
|
if (divContent != null) { |
||||||
|
String content = Html.fromHtml(divContent.html()).toString(); |
||||||
|
char c = 160; |
||||||
|
String spaec = "" + c; |
||||||
|
content = content.replace(spaec, " "); |
||||||
|
return content; |
||||||
|
} else { |
||||||
|
return ""; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 从html中获取章节列表 |
||||||
|
* |
||||||
|
* @param html |
||||||
|
* @return |
||||||
|
*/ |
||||||
|
public ArrayList<Chapter> getChaptersFromHtml(String html) { |
||||||
|
ArrayList<Chapter> chapters = new ArrayList<>(); |
||||||
|
Document doc = Jsoup.parse(html); |
||||||
|
String readUrl = doc.select("meta[property=og:novel:read_url]").attr("content"); |
||||||
|
Element divList = doc.getElementById("newlist"); |
||||||
|
Elements elementsByTag = divList.getElementsByTag("a"); |
||||||
|
int i = 0; |
||||||
|
for (int j = 0; j < elementsByTag.size(); j++) { |
||||||
|
Element a = elementsByTag.get(j); |
||||||
|
String title = a.text(); |
||||||
|
String url = a.attr("href"); |
||||||
|
Chapter chapter = new Chapter(); |
||||||
|
chapter.setNumber(i++); |
||||||
|
chapter.setTitle(title); |
||||||
|
chapter.setUrl(readUrl + url); |
||||||
|
chapters.add(chapter); |
||||||
|
} |
||||||
|
return chapters; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 从搜索html中得到书列表 |
||||||
|
* |
||||||
|
* @param html |
||||||
|
* @return |
||||||
|
*/ |
||||||
|
/* |
||||||
|
<li> |
||||||
|
<div class="sCboxBookParL left"><a href="/xiaoshuo/21351.html"><img data-original="https://www.hs918.com/files/article/image/20/20240/20240s.jpg" /></a></div> |
||||||
|
<div class="sCboxBookParR left"> |
||||||
|
<div class="top clearfix"> |
||||||
|
<h1><a href="/xiaoshuo/21351.html"><font style="font-weight:bold;color:#f00">大主宰</font>之剑仙</a></h1> |
||||||
|
<span class="s2">遗弃的梦 </span> |
||||||
|
<span class="s4">95万字</span> |
||||||
|
<span class="s6">474人气值</span> |
||||||
|
</div> |
||||||
|
<div class="tips clearfix"><a href="/fenlei/3_0_0_0_0_1.html" title="浪漫青春" class="tipsa">浪漫青春</a></div> |
||||||
|
<div class="c"><strong>内容介绍:</strong> 一位少年意外穿越大主宰,结识了牧尘…………(新人作家,写得不好还请多多包涵) |
||||||
|
...</div> |
||||||
|
<div class="bottom clearfix"> |
||||||
|
<span class="redTps">最近更新</span> |
||||||
|
<a href="/xiaoshuo/21351/43873.html">第57章:陷阱</a> |
||||||
|
|
||||||
|
<span class="time2">更新时间:2020-12-05 01:45</span> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
<div class="sCboxBookParS right"> |
||||||
|
<a href="/xiaoshuo/21351/" class="b1">开始阅读</a> |
||||||
|
<a href="javascript:;" onclick="BookCaseAdd('21351');" class="b2 apdBshelf">加入书架</a> |
||||||
|
</div> |
||||||
|
</li> |
||||||
|
*/ |
||||||
|
public ConcurrentMultiValueMap<SearchBookBean, Book> getBooksFromSearchHtml(String html) { |
||||||
|
ConcurrentMultiValueMap<SearchBookBean, Book> books = new ConcurrentMultiValueMap<>(); |
||||||
|
Document doc = Jsoup.parse(html); |
||||||
|
// try {
|
||||||
|
Element div = doc.getElementsByClass("leftBox").first(); |
||||||
|
Elements lis = div.getElementsByTag("li"); |
||||||
|
for (Element li : lis){ |
||||||
|
Elements as = li.getElementsByTag("a"); |
||||||
|
Book book = new Book(); |
||||||
|
book.setName(as.get(1).text()); |
||||||
|
book.setAuthor(li.getElementsByTag("span").first().text()); |
||||||
|
book.setType(as.get(2).text()); |
||||||
|
book.setNewestChapterTitle(as.get(3).text()); |
||||||
|
book.setDesc(li.getElementsByClass("c").first().text().replace("内容介绍:", "")); |
||||||
|
book.setUpdateDate(li.getElementsByClass("time2").first().text().replace("更新时间:", "")); |
||||||
|
book.setImgUrl(li.getElementsByTag("img").attr("data-original")); |
||||||
|
book.setChapterUrl(NAME_SPACE + as.get(1).attr("href").replace(".html", "/")); |
||||||
|
book.setSource(BookSource.xingxing.toString()); |
||||||
|
SearchBookBean sbb = new SearchBookBean(book.getName(), book.getAuthor()); |
||||||
|
books.add(sbb, book); |
||||||
|
} |
||||||
|
// } catch (Exception e) {
|
||||||
|
// e.printStackTrace();
|
||||||
|
// }
|
||||||
|
return books; |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
} |
@ -1,2 +1,2 @@ |
|||||||
#Mon Nov 30 10:23:34 CST 2020 |
#Sun Dec 06 12:06:58 CST 2020 |
||||||
VERSION_CODE=174 |
VERSION_CODE=175 |
||||||
|
Loading…
Reference in new issue