完善
This commit is contained in:
parent
ab97f5c624
commit
eceeae2444
61
main.go
61
main.go
|
@ -36,21 +36,24 @@ type dataChan struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
type fetchHandler struct {
|
type fetchHandler struct {
|
||||||
fetchUrl string
|
|
||||||
hadFetchData []data.FetchData
|
hadFetchData []data.FetchData
|
||||||
cronTime mapXS[time.Duration]
|
cronTime mapXS[time.Duration]
|
||||||
keyword mapXS[string]
|
keyword mapXS[string]
|
||||||
|
searchSource mapXS[[]string]
|
||||||
hadFetchedMap mapXS[int]
|
hadFetchedMap mapXS[int]
|
||||||
reloadCron mapXS[chan int]
|
reloadCron mapXS[chan int]
|
||||||
isOff chan int
|
isOff chan int
|
||||||
rMsgChan chan connChan
|
rMsgChan chan connChan
|
||||||
newFetchItem chan dataChan
|
newFetchItem chan dataChan
|
||||||
connMap mapXS[*websocket.Conn]
|
connMap mapXS[*websocket.Conn]
|
||||||
|
sourceMap map[string]newsource.Source
|
||||||
|
sourceArr []string
|
||||||
}
|
}
|
||||||
|
|
||||||
type setting struct {
|
type setting struct {
|
||||||
Keyword string `json:"keyword"`
|
Keyword string `json:"keyword"`
|
||||||
TimeStep int `json:"timeStep"`
|
TimeStep int `json:"timeStep"`
|
||||||
|
SearchSource []string `json:"searchSource"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type message struct {
|
type message struct {
|
||||||
|
@ -86,6 +89,15 @@ func (r dist) Open(name string) (fs.File, error) {
|
||||||
return file, err
|
return file, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func isContain[T comparable](i T, arr []T) bool {
|
||||||
|
for _, t := range arr {
|
||||||
|
if i == t {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
func setMap[T mapT](obj *mapXS[T], key string, v T) {
|
func setMap[T mapT](obj *mapXS[T], key string, v T) {
|
||||||
obj.Lock()
|
obj.Lock()
|
||||||
(*obj.mapX)[key] = v
|
(*obj.mapX)[key] = v
|
||||||
|
@ -99,7 +111,7 @@ func delMap[T mapT](obj *mapXS[T], key string) {
|
||||||
}
|
}
|
||||||
|
|
||||||
type mapT interface {
|
type mapT interface {
|
||||||
string | int | time.Duration | *websocket.Conn | chan int
|
string | []string | int | time.Duration | *websocket.Conn | chan int
|
||||||
}
|
}
|
||||||
type mapX[T mapT] map[string]T
|
type mapX[T mapT] map[string]T
|
||||||
|
|
||||||
|
@ -108,9 +120,16 @@ type mapXS[T mapT] struct {
|
||||||
*sync.Mutex
|
*sync.Mutex
|
||||||
}
|
}
|
||||||
|
|
||||||
func newFetchHandler(fetchUrl string) *fetchHandler {
|
func newFetchHandler() *fetchHandler {
|
||||||
|
var arr = make(map[string]newsource.Source)
|
||||||
|
var x []string
|
||||||
|
for _, source := range newsource.GetSource() {
|
||||||
|
arr[source.Name] = source
|
||||||
|
x = append(x, source.Name)
|
||||||
|
}
|
||||||
return &fetchHandler{
|
return &fetchHandler{
|
||||||
fetchUrl: fetchUrl,
|
sourceMap: arr,
|
||||||
|
sourceArr: x,
|
||||||
keyword: mapXS[string]{
|
keyword: mapXS[string]{
|
||||||
&mapX[string]{},
|
&mapX[string]{},
|
||||||
&sync.Mutex{},
|
&sync.Mutex{},
|
||||||
|
@ -123,6 +142,10 @@ func newFetchHandler(fetchUrl string) *fetchHandler {
|
||||||
&mapX[time.Duration]{},
|
&mapX[time.Duration]{},
|
||||||
&sync.Mutex{},
|
&sync.Mutex{},
|
||||||
},
|
},
|
||||||
|
searchSource: mapXS[[]string]{
|
||||||
|
&mapX[[]string]{},
|
||||||
|
&sync.Mutex{},
|
||||||
|
},
|
||||||
reloadCron: mapXS[chan int]{
|
reloadCron: mapXS[chan int]{
|
||||||
&mapX[chan int]{},
|
&mapX[chan int]{},
|
||||||
&sync.Mutex{},
|
&sync.Mutex{},
|
||||||
|
@ -142,7 +165,8 @@ func (f *fetchHandler) handle(conn string) {
|
||||||
if kk, ok := (*f.keyword.mapX)[conn]; ok && kk != "" {
|
if kk, ok := (*f.keyword.mapX)[conn]; ok && kk != "" {
|
||||||
key = kk
|
key = kk
|
||||||
}
|
}
|
||||||
for _, source := range newsource.GetSource() {
|
for _, sourceName := range (*f.searchSource.mapX)[conn] {
|
||||||
|
source := f.sourceMap[sourceName]
|
||||||
r := f.fetch2(source, key)
|
r := f.fetch2(source, key)
|
||||||
if r != nil {
|
if r != nil {
|
||||||
if strings.ToUpper(source.Type) == "HTML" {
|
if strings.ToUpper(source.Type) == "HTML" {
|
||||||
|
@ -160,9 +184,10 @@ func (f *fetchHandler) receiveMsg() {
|
||||||
switch r.msg.Action {
|
switch r.msg.Action {
|
||||||
case "search":
|
case "search":
|
||||||
if t, ok := r.msg.Data.(*setting); ok {
|
if t, ok := r.msg.Data.(*setting); ok {
|
||||||
(*f.reloadCron.mapX)[r.conn] <- t.TimeStep
|
|
||||||
setMap[string](&f.keyword, r.conn, t.Keyword)
|
setMap[string](&f.keyword, r.conn, t.Keyword)
|
||||||
|
setMap[[]string](&f.searchSource, r.conn, t.SearchSource)
|
||||||
f.handle(r.conn)
|
f.handle(r.conn)
|
||||||
|
(*f.reloadCron.mapX)[r.conn] <- t.TimeStep
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -283,6 +308,7 @@ func (f *fetchHandler) parseAjax(response *http.Response, source newsource.Sourc
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(newFetch) > 0 {
|
if len(newFetch) > 0 {
|
||||||
|
var newF []data.FetchData
|
||||||
for i := 0; i < len(newFetch); i++ {
|
for i := 0; i < len(newFetch); i++ {
|
||||||
fetchData := newFetch[i]
|
fetchData := newFetch[i]
|
||||||
k := conn + "_" + fetchData.Url + "_" + fetchData.Title
|
k := conn + "_" + fetchData.Url + "_" + fetchData.Title
|
||||||
|
@ -295,13 +321,12 @@ func (f *fetchHandler) parseAjax(response *http.Response, source newsource.Sourc
|
||||||
if _, ok := (*f.hadFetchedMap.mapX)[k]; !ok {
|
if _, ok := (*f.hadFetchedMap.mapX)[k]; !ok {
|
||||||
f.hadFetchData = append(f.hadFetchData, fetchData)
|
f.hadFetchData = append(f.hadFetchData, fetchData)
|
||||||
setMap(&f.hadFetchedMap, k, 1)
|
setMap(&f.hadFetchedMap, k, 1)
|
||||||
} else {
|
newF = append(newF, newFetch[i])
|
||||||
newFetch = newFetch[:i+copy(newFetch[i:], newFetch[i+1:])] // 删除中间1个元素
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
f.newFetchItem <- dataChan{
|
f.newFetchItem <- dataChan{
|
||||||
conn: conn,
|
conn: conn,
|
||||||
item: newFetch,
|
item: newF,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
err := response.Body.Close()
|
err := response.Body.Close()
|
||||||
|
@ -389,7 +414,7 @@ func (f *fetchHandler) cronFetch(conn string, c chan int) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
h := newFetchHandler("https://www.baidu.com/s?rtt=1&bsst=1&cl=2&tn=news&rsv_dl=ns_pc&word=")
|
h := newFetchHandler()
|
||||||
router := gin.Default()
|
router := gin.Default()
|
||||||
static := dist{
|
static := dist{
|
||||||
FS: st,
|
FS: st,
|
||||||
|
@ -430,6 +455,12 @@ func main() {
|
||||||
log.Println(err)
|
log.Println(err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
_ = conn.WriteJSON(message{
|
||||||
|
Status: true,
|
||||||
|
Action: "sourceList",
|
||||||
|
Message: "",
|
||||||
|
Data: h.sourceArr,
|
||||||
|
})
|
||||||
remote := conn.RemoteAddr().String()
|
remote := conn.RemoteAddr().String()
|
||||||
if _, ok := (*h.connMap.mapX)[remote]; !ok {
|
if _, ok := (*h.connMap.mapX)[remote]; !ok {
|
||||||
setMap(&h.connMap, remote, conn)
|
setMap(&h.connMap, remote, conn)
|
||||||
|
@ -460,12 +491,12 @@ func main() {
|
||||||
})
|
})
|
||||||
go func() {
|
go func() {
|
||||||
time.Sleep(2 * time.Second)
|
time.Sleep(2 * time.Second)
|
||||||
url := "http://127.0.0.1:8080"
|
u := "http://127.0.0.1:8080"
|
||||||
switch runtime.GOOS {
|
switch runtime.GOOS {
|
||||||
case "linux":
|
case "linux":
|
||||||
exec.Command(`xdg-open`, url).Start()
|
exec.Command(`xdg-open`, u).Start()
|
||||||
case "windows":
|
case "windows":
|
||||||
exec.Command(`cmd`, `/c`, `start`, url).Start()
|
exec.Command(`cmd`, `/c`, `start`, u).Start()
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -8,12 +8,29 @@
|
||||||
<el-form-item prop="password" label="搜索间隔时间,单位为秒">
|
<el-form-item prop="password" label="搜索间隔时间,单位为秒">
|
||||||
<el-input v-model="form.timeStep" type="number" step="1" ></el-input>
|
<el-input v-model="form.timeStep" type="number" step="1" ></el-input>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
<el-form-item prop="searchSource" label="要抓取的新闻源">
|
||||||
|
<el-select
|
||||||
|
v-model="form.searchSource"
|
||||||
|
multiple
|
||||||
|
clearable filterable
|
||||||
|
placeholder="可多选"
|
||||||
|
style="width: 240px"
|
||||||
|
>
|
||||||
|
<el-option
|
||||||
|
v-for="item in allSource"
|
||||||
|
:key="item.k"
|
||||||
|
:label="item.k"
|
||||||
|
:value="item.v"
|
||||||
|
/>
|
||||||
|
</el-select>
|
||||||
|
</el-form-item>
|
||||||
|
|
||||||
<el-form-item class="btns">
|
<el-form-item class="btns">
|
||||||
<el-button @click="submit" type="primary">查询</el-button>
|
<el-button @click="submit" type="primary">查询</el-button>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-form>
|
</el-form>
|
||||||
<el-card class="box-card">
|
<el-card class="box-card">
|
||||||
<el-table
|
<el-table :table-layout="tableLayout"
|
||||||
:data="rowss" border stripe
|
:data="rowss" border stripe
|
||||||
style="width: 100%">
|
style="width: 100%">
|
||||||
<el-table-column
|
<el-table-column
|
||||||
|
@ -32,12 +49,14 @@
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column
|
<el-table-column
|
||||||
|
align="center"
|
||||||
prop="source"
|
prop="source"
|
||||||
label="来源">
|
label="来源">
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column
|
<el-table-column
|
||||||
prop="desc"
|
prop="desc"
|
||||||
label="描述"
|
label="描述"
|
||||||
|
:show-overflow-tooltip="true"
|
||||||
>
|
>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column
|
<el-table-column
|
||||||
|
@ -64,14 +83,20 @@
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
|
import {ref} from 'vue'
|
||||||
|
|
||||||
|
const tableLayout = ref('auto')
|
||||||
export default {
|
export default {
|
||||||
name: 'WelCome',
|
name: 'WelCome',
|
||||||
data () {
|
data () {
|
||||||
return {
|
return {
|
||||||
|
tableLayout: tableLayout,
|
||||||
form: {
|
form: {
|
||||||
keyword: '纪检',
|
keyword: '纪检',
|
||||||
timeStep: 60
|
timeStep: 60,
|
||||||
|
searchSource: [],
|
||||||
},
|
},
|
||||||
|
allSource: [],
|
||||||
ws: null,
|
ws: null,
|
||||||
formRules: {
|
formRules: {
|
||||||
keyword: [
|
keyword: [
|
||||||
|
@ -81,6 +106,9 @@ export default {
|
||||||
timeStep: [
|
timeStep: [
|
||||||
{ required: true, message: '请输入时间间隔,单位为秒', trigger: 'blur' },
|
{ required: true, message: '请输入时间间隔,单位为秒', trigger: 'blur' },
|
||||||
{ min: 1, max: 10000000, message: '长度在 1 到 10000000 秒', trigger: 'blur' }
|
{ min: 1, max: 10000000, message: '长度在 1 到 10000000 秒', trigger: 'blur' }
|
||||||
|
],
|
||||||
|
searchSource: [
|
||||||
|
{ required: true, message: '请选择新闻源', trigger: 'change' },
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
rows: [],
|
rows: [],
|
||||||
|
@ -135,14 +163,24 @@ export default {
|
||||||
this.ws = new WebSocket('ws://127.0.0.1:8080/ws')
|
this.ws = new WebSocket('ws://127.0.0.1:8080/ws')
|
||||||
this.ws.addEventListener('message', e => {
|
this.ws.addEventListener('message', e => {
|
||||||
const msg = JSON.parse(e.data)
|
const msg = JSON.parse(e.data)
|
||||||
msg.Data.forEach(v => {
|
if(msg.Action==='sourceList'){
|
||||||
v.isNew = true
|
this.allSource = msg.Data.map(value => {
|
||||||
})
|
return {
|
||||||
this.rows.unshift(...msg.Data)
|
k:value,
|
||||||
Notification.requestPermission(function () {
|
v:value
|
||||||
// eslint-disable-next-line no-unused-vars
|
}
|
||||||
const n = new Notification('有新抓取文章', { body: msg.Data[0].title + '等总共' + msg.Data.length + '条' })
|
})
|
||||||
})
|
}else if (msg.Action==='newData'){
|
||||||
|
msg.Data.forEach(v => {
|
||||||
|
v.isNew = true
|
||||||
|
})
|
||||||
|
this.rows.unshift(...msg.Data)
|
||||||
|
Notification.requestPermission(function () {
|
||||||
|
// eslint-disable-next-line no-unused-vars
|
||||||
|
const n = new Notification('有新抓取文章', { body: msg.Data[0].title + '等总共' + msg.Data.length + '条' })
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
})
|
})
|
||||||
this.ws.onclose = () => {
|
this.ws.onclose = () => {
|
||||||
const a = setInterval(() => {
|
const a = setInterval(() => {
|
||||||
|
|
Loading…
Reference in New Issue
Block a user