

$Seo={};
$Seo.baidu={}
$Seo.spider360={}
$Seo.spider360.key='31c120dc07dd8f49b79e7c2cc7221321'

$Seo.iframe=function(src,time,time1)
{
    //src,数组的url,time页面加载多久后运行框架，
    //time1页面停留多久进入下一个url
    var _src;
    while(_src=src.shift())
    {
        var dom=document.createElement('iframe')
        dom.src=_src;
        dom.setAttribute('$splider','splider') 
        dom.style.display='none';
        dom.onload=function()
        {
            if(!src.length)return
            setTimeout
            (
                function()
                {
                    $Seo.iframe(src,time)
                },time1?time1:1000
            )
        }
        setTimeout
        (
            function()
            {
                document.getElementsByTagName("body")[0].appendChild(dom);
            }, time?time:3000
        );
    }
}

$Seo.hideLink=function(dom)
{
    dom.style.display='none';
}

$Seo.pushAll=function()
{
    $Seo.spider360.push();
    $Seo.baidu.push();
}

$Seo.append=function(src)
{
    var dom = document.createElement('script').src=src;
    document.getElementsByTagName("body")[0].appendChild(dom);
}

$Seo.baidu.push=function()
{
    var src = (document.location.protocol == "http:") ? 
    "http://push.zhanzhang.baidu.com/push.js":
    "https://zz.bdstatic.com/linksubmit/push.js";
    $Seo.append(src)
}

$Seo.spider360.push=function()
{
    var src = (document.location.protocol == "http:") ? 
    "http://js.passport.qihucdn.com/11.0.1.js?"+key:
    "https://jspassport.ssl.qhimg.com/11.0.1.js?"+key;
    $Seo.append(src);
}


$Seo.getSelect=function(elm)
{
    var stack = [];
    if(typeof elm == 'string')
    {
        stack=this.split(stack)
    }
    else
    {
        for (; elm.parentNode; elm = elm.parentNode) 
        {
            let tag=elm.tagName
            if (tag && tag != "HTML") 
            {
                let index = this.getIndex(elm.parentNode.children,elm)
                stack.unshift(tag + `:nth-of-type(${index+1})`)
            }
        }           
    }

    this.stack=stack       
    this.querys=this.toString(stack)
}

$Seo.getSelect.prototype.getIndex=function(list,target)
{
    list=Array.from(list)
    list=list.filter
    (
        (val)=>
        {
            return val.tagName==target.tagName
        }
    )
    for (let index = 0; index < list.length; index++) 
    {
        const element = list[index];
        if(element==target)return index
    }
}


$Seo.getSelect.prototype.compare=function(seo)
{
    let sour=this.stack
    let dist=seo.stack
    let back=[]
    let tag
    if(!dist.length)return false
    else if(sour.length>dist.length)return false
    for (let index = 0; index < dist.length; index++) 
    {
        let cur=dist[index]
        if(tag || sour[index]!=cur)
        {
            tag=true
            back.push(dist[index])
        }
    }
    
    return this.toString(back)
}

$Seo.getSelect.prototype.comp=function(seo)
{
    let sour=this.stack
    let dist=seo.stack
    let back=[]

    if(!sour.length || !dist.length)return false
    for (let index = 0; index < sour.length; index++) 
    {
        let cur=sour[index]
        back.push(cur)
        if(dist[index]!=cur)break
    }
    this.stack=back       
    this.querys=this.toString(back)
}


$Seo.getSelect.prototype.toString=function(list)
{
    return list.join(' > ')
}
$Seo.getSelect.prototype.split=function(str)
{
    return str.split(' > ')
}

$Seo.getList=function({select,text,attr,detail})
{
    select=select.replace(/\([0-9]*?\)$/,'(@)')
    let parent=select.replace(':nth-of-type(@)','')
    
    
    let list=$M.find(parent,true)
    for (let index = 0; index < list.length; index++) 
    {
        let val
        let curParent=list[index]
        let pathSelect=select.replace('(@)',`(${index+1})`)
        let dom=$M.find(pathSelect)
        if(text)val=dom.innerText
        else val=dom.innerHTML

        curParent={value:val}
        if(Array.isArray(attr))
        {
            for (let ind = 0; ind < attr.length; ind++) 
            {
                let cur=attr[ind]
                let val=dom.getAttribute(cur)
                if(curParent.attr)curParent.attr[cur]=val
                else curParent.attr={[cur]:val}  
            }
        }
        if(detail)
        {
            let param={}
            for (const key in detail) 
            {
                param[key]={...detail[key]}
                let cur=param[key]
                cur.select=$Seo.getSelect.prototype.toString([pathSelect,cur.select])
            }
            curParent.detail=$Seo.getObj(param)
        }

        list[index]=curParent
    }
    return list
}

$Seo.getObj=function(obj)
{
    function gen({select,text,attr})
    {
        let dom=$M.find(select)
        let val
        if(text)val=dom.innerText
        else val=dom.innerHTML
    
        let curParent={value:val}
    
        if(Array.isArray(attr))
        {
            for (let ind = 0; ind < attr.length; ind++) 
            {
                let cur=attr[ind]
                let val=dom.getAttribute(cur)
                if(curParent.attr)curParent.attr[cur]=val
                else curParent.attr={[cur]:val}  
            }
        }
        return curParent
    }

    let back={}
    for (const name in obj) 
    {
        back[name]=gen(obj[name])
    }

    return back
}

$Seo.getAll=function(text=true)
{
    let obj=$Seo.setListenerType
    let back={data:{},list:{}}

    if(obj.list)
    {
        let curl=obj.list['list']
        let curc=obj.listCom
        let listNew=new $Seo.getSelect(curl.dom)
        if(curc)
        {
            curc=cur['listCom']
            let curcNew=new $Seo.getSelect(curc.dom)
            listNew.comp(curcNew);
        }
        let params={select:listNew.querys,attr:curl.attr,text}
        if(obj.detail)
        {
            let param={}
            for (const name in obj.detail) 
            {
                let cur=obj.detail[name]
                let subNew=new $Seo.getSelect(cur.dom)
                let select=listNew.compare(subNew)
                param[name]={select,attr:cur.attr,text}
            }
            params.detail=param
        }
        back.list=$Seo.getList(params)
    }
    else if(obj.data)
    {
        let param={}
        for (const name in obj.data) 
        {
            let cur=obj.data[name]
            let dataNew=new $Seo.getSelect(cur.dom)
            let select=dataNew.querys
            param[name]={select,attr:cur.attr,text}
        }
        back.data=$Seo.getObj(param)
    }
    console.log(back)
    return back
}

$Seo.listener=function(fun,time=3000)
{
    let tmp=`
    <button onclick="$Seo.setListenerType('list')">列表元素</button>
    <button onclick="$Seo.setListenerType('listCom')">列表比对元素</button>
    <button onclick="$Seo.setListenerType('detail')">子元素</button>
    <button onclick="$Seo.setListenerType('data')">元素</button>
    <button onclick="$Seo.getAll()">获取</button>
    `
    let div=document.createElement('div')
    div.id='$spider'
    div.style.position='fixed'
    div.style.top='0'
    div.style.zIndex='9999999999'
    div.innerHTML=tmp
    document.body.appendChild(div)
    document.documentElement.style.marginTop='2rem'
    function back(dom)
    {
        if(dom)
        {
            if(dom.id=='$spider')return true
            return back(dom.parentNode)
        }
    }
    function setObj(type,dom)
    {
        let obj=$Seo.setListenerType
        if(!obj.alis)
        {
            alert('请设置字段名')
            return
        }
        if(!obj[type])obj[type]={}
        obj[type][obj.alis]={dom,attr:obj.alisAttr}
    }
    window.addEventListener
	(
		'click',
		(event)=>
		{
            let dom=event.target
            let bool
            
            $M.stop(event)
            if(!$Seo.setListenerType.type)
            {
                alert('请选择数据类型')
                return
            }

            if(back(dom) || dom.tagName=='HTML')return

            if(fun)bool=fun(dom)
            if(bool!==undefined)return

            $Seo.temp(dom,time)

            switch ($Seo.setListenerType.type) 
            {
                case 'list':
                    $Seo.setListenerTypeName('list')
                    setObj('list',dom)
                break;
                case 'listCom':
                        $Seo.setListenerTypeName('listCom')
                        setObj('listCom',dom)
                break;
                case 'detail':
                    $Seo.setListenerTypeName()
                    setObj('detail',dom)
                break;
                case 'data':
                    $Seo.setListenerTypeName()
                    setObj('data',dom)
                break;
            }

            
		}
	)
}

$Seo.temp=function(dom,time=1000)
{
    if(dom.$spliderColorTag)return
    dom=$M.find(dom)
    let attr=dom.style
    let color=attr.background
    dom.$spliderColor=color 
    dom.$spliderColorTag=true
    attr.background='rgba(255,0,50,0.65)'
    setTimeout
    (
        ()=>
        {
            attr.background=color
            dom.$spliderColorTag=false
        },time
    )
}

$Seo.setListenerType=function(type)
{
    $Seo.setListenerType.type=type
}
//字段名-属性节点1-属性节点n
$Seo.setListenerTypeName=function(type)
{
    if(type==='listCom')
    {
        $Seo.setListenerType.alis='listCom'
        return
    }
    let name=prompt('请输入字段名','field')
    let arr=name.split('-')
    if(type==='list')$Seo.setListenerType.alis='list'
    else $Seo.setListenerType.alis=arr[0]
    $Seo.setListenerType.alisAttr=arr.slice(1)
}




