基礎篇(6) splash應用

     selenium是瀏覽器測試自動化工具,很容易完成鼠標點擊,翻頁等動作,確定是一次只能加載一個頁面,無法異步渲染頁面,也就限制了selenium爬蟲的抓取效率。

    splash可以實現異步渲染頁面,可以同時渲染幾個頁面。缺點是在頁面點擊,,模擬登陸方面沒有selenium靈活。

1、docker安裝splash

docker安裝splash鏡像
[ywadmin@wzy_woyun ~]$docker pull scrapinghub/splash
#後臺運行
[ywadmin@wzy_woyun ~]$ docker run -d -p 8050:8050 --name=splash scrapinghub/splash
#root用戶開放8050端口
[root@wzy_woyun ~]# firewall-cmd --permanent --add-port=8050/tcp
success
[root@wzy_woyun ~]# firewall-cmd --reload
Success

2、splash中的對象

2.1、args屬性

該屬性可以獲取加載時配置的參數,比如url。

function main(splash, args)

      local url = args.url

end

上面的代碼等同於下面

function main(splash, args)

      local url = splash.args.url

end

3.2、js_enabled屬性

接着我們重新代用eval()方法執行JavaScript代碼,運行時發現報錯。這個屬性是splash的JavaScript執行開關,可以將其配置爲true或者false來控制是否執行JavaScript代碼,默認爲true

function main(splash, args)
  splash:go("https://www.baidu.com")
  splash:js_enabled = false -- 禁止加載JavaScript代碼
  splash:wait(0.5)
  local title = splash:evaljs("document.title") --獲取網頁標題
  return {
    html = splash:html(),
    title = title,   
  }
end

接着我們重新代用eval()方法執行JavaScript代碼,運行時發現報錯。

一般不用設置次屬性,默認是開啓的。

2.3、resource_timeout屬性

屬性可以設置加載的超時時間,單位是秒。如果設置爲0或者nil(類似py中的None),表示不進行超時檢測。

function main(splash, args)
  splash.resource_timeout = 5
  splash:go("https://www.taobao.com")
  return splash:html()
end

2.4、images_enabled屬性

    images_enabled屬性表示可以設置圖片是否加載,默認情況下是加載的,默認爲true。如果設置圖片不加載,那麼加載網頁速度會快。

function main(splash, args)
  splash.images_enabled = false
  splash:go("https://www.taobao.com")
  return {splash:html(),
  				splash.png
  }
end

2.5、plugins_enabled屬性

該屬性表示是否開啓瀏覽器插件。默認情況是開啓,默認值爲true。

function main(splash, args)
  splash.plugins_enabled = false
  splash:go("https://www.taobao.com")
  return {splash:html(),
  				splash.png(),
  }
end

2.6、scroll_position屬性

控制瀏覽頁面上下或者左右滾動,這個屬性是比較常用的屬性。

function main(splash, args) 
  splash:go("https://www.taobao.com")
  splash.scroll_postion={x=300,y=500}
  return {splash:html(),
  				splash.png()
  }
end

其中x=300表示向右移動300像素,y=500表示向下移動500像素。

3、splash中的方法

3.1、go()方法

go方法用來請求某個鏈接,而且它可以模擬get和post請求,同時支持傳入請求頭、表單等數據。

function main(splash)
    splash:go{"http://www.sxt.cn", http_method="POST", body="name=17703181473"}
    splash:wait(2)
    return {html=splash:html()}
end

3.2、wait()方法

wait()方法控制頁面的等待時間:

splash:wait{time, cancel_on_redirect=false, cancel_on_error=true}

function main(splash)
    splash:go("https://www.taobao.com")
    splash:wait(2)
    return {html=splash:html()}
end

3.3、jsfunc()方法

直接調用JavaScript定義的方法,但是所調用的方法需要用雙中括號包圍,這相當於實現了JavaScript方法到Lua腳本的轉換。

function main(splash, args)
  splash:go("http://www.baidu.cn")
  local scroll_to = splash:jsfunc("window.scrollTo")
  scroll_to(0, 300)
  return {
    png = splash:png(),
    html = splash:html()
  }
end

3.4、evaljs()方法和runjs()方法

function main(splash, args)
  splash:go("https://www.baidu.com")
  splash:runjs("foo = function() { return 'sxt' }")
  local result = splash:evaljs("foo()")
  return result
end

3.5、send_text()

send_text()方法是填寫文本的功能

function main(splash)
  splash:go("https://www.baidu.com/")
  input = splash:select("#kw")
  input:send_text('Splash')
  splash:wait(3)
  return splash:png()
end

3.6、url()方法

獲取當前在訪問的URL

function main(splash, args)
  splash:go("https://www.baidu.com")
  return splash:url()
end

3.7、get_cookies()方法

function main(splash, args)
  splash:go("http://www.baidu.com")
  splash:wait(2)
  local cookies = splash:get_cookies()
  return {
    cookies = cookies,
    html = splash:html(),
    png = splash:png(),
    har = splash:har(),
  }
end

 

3.7、  add_cookie()方法

添加cookies

【語法】

cookies = splash:add_cookie{name, value, path=nil, domain=nil, expires=nil, httpOnly=nil, secure=nil}

function main(splash)
    splash:add_cookie{"sessionid", "123456abcdef", "/", domain="http://bjsxt.com"}
    splash:go("http://bjsxt.com/")
    return splash:html()
end

3.8、clear_cookies()方法

function main(splash)
    splash:go("https://www.bjsxt.com/")
    splash:clear_cookies()
    return splash:get_cookies()
end

3.9、set_user_agent()方法

 

function main(splash, args)
  splash:set_user_agent("Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.169 Safari/537.36")
  splash:go("http://httpbin.org/get")
  splash:wait(5)
  return {
    html = splash:html(),
    png = splash:png(),   
  }
end

注意set_user_agent()方法後面直接跟具體的值。

3.10、set_custom_headers()方法

set_custom_headers()方法是用來設置請求頭信息。

function main(splash, args)
  splash:set_custom_headers({
      ["User-Agent"]="Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.169 Safari/537.36",
      ["Host"]="www.httpbin.org"
    })
  splash:go("http://httpbin.org/get")
  splash:wait(5)
  return {
    html = splash:html(),
    png = splash:png(),   
  }
end

4、splash與python整合

Splash與Python結合其實就python調用splash的api。

4.1、render.html應用

import requests
from urllib.parse import quote
# 1、render.html
# 次接口用於獲取JavaScript渲染的頁面的HTML代碼,接口地址就是Splash的運行地址加次接口名稱,如http://192.168.2.10:8050/render.html
url = "http://192.168.2.10:8050/render.html?url=http://www.hnwznz.com&wait=2"
response = requests.get(url)
print(response.text)

# 2、render.png 此接口可以獲取網頁截圖
url_2= "http://192.168.2.10:8050/render.png?url=https://www.jd.com&wait=3&width=1000&height=700"
response_2 = requests.get(url_2)
with open("jd.png","wb") as f:
    f.write(response.content)

4.2、execute的調用

#3、execute 作爲最強大的接口,用次接口便可實現與Lua腳本的對接。

lua = """
function main(splash, args)
 return "hello"
end
"""
url_3 = "http://192.168.2.10:8050/execute?lua_source="+quote(lua)
response_3 = requests.get(url_3)
print(response_3.text)

【例子】

import requests
from fake_useragent import UserAgent
from urllib.parse import quote
url = "https://www.guazi.com/bj/buy/"
lua_script = '''
function main(splash, args)
    splash:go('{}')
    splash:wait(1)
    return splash:html()
end
'''.format(url)
splash_url = "http://192.168.2.10:8050/execute?lua_source={}".format(quote(lua_script))
response = requests.get(splash_url, headers={"User-Agent": UserAgent().random})
response.encoding = 'utf-8'
print(response.text)

5、應用例子

5.1、爬取京東商品

import json
import requests
from lxml import etree
from urllib.parse import quote
lua = '''
function main(splash, args)
    local treat = require("treat")
    local response = splash:http_get("https://search.jd.com/Search?keyword=相機&enc=utf-8")
        return {
            html = treat.as_string(response.body),
            url = response.url,
            status = response.status
        }    
end
'''
# 線上部署的服務,需要將localhost換成服務器的公網地址(不是內網地址)
url = 'http://192.168.2.10:8050/execute?lua_source=' + quote(lua)
response = requests.get(url)
# 由於使用splash,response.text返回結果爲{"status":200,"html":"xxxxxxxxx","url":"yyyyyy"}
html = json.loads(response.text)['html']
# print(html)
tree = etree.HTML(html)

# 單品
products_1 = tree.xpath('//div[@class="gl-i-wrap"]')
for item in products_1:
    try:
        name_1 = item.xpath('./div[@class="p-name p-name-type-2"]/a/em/text()')[0]
        price_1 = item.xpath('./div[@class="p-price"]/strong/@data-price | ./div[@class="p-price"]/strong/i/text()')[0]
        print(name_1)
        print(price_1)
    except:
        pass
print("="*90)

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章