ghost.py目前已更新到0.2版本,變化有點大,使用方法上跟0.1還是有點差別的,本文僅以0.1.1版本為例,因為我安裝的是這個版本
我用ghost主要用來模擬在網站上的操作,比如登錄之類的,當然我也不懂別的用處。
首先,就像所有python模塊的使用一樣,都要先導入
import ghost
然后你可以使用dir方法查看ghost的一些方法屬性等
>>> import ghost >>> dir(ghost) ['Error', 'Ghost', 'GhostTestCase', 'TimeoutError', '__builtins__', '__doc__', '__file__', '__name__', '__package__', '__path__', '__version__', 'ghost', 'logger', 'test'] >>>
我只用過Ghost這個類,別的就不說了,沒用過
既然要操作網頁,那么首先得打開瀏覽器
使用ghost模塊就是先實例化一個瀏覽器對象,可能說法不太准確,不過自行理解吧
>>>gh = ghost.Ghost(display=True)
實例化的時候就用到了Ghost這個類,注意后面的那個空白小窗口,我在實例化的時候傳入了display=True這個參數,於是這個窗口便會顯示出來
默認是不顯示的,不過在調試程序的時候,顯示出來還是挺方便的,程序調試完后,將參數去掉或改成False就可以了,不過在linux系統里無論display參數是什么,好像都是不顯示的(我沒試過帶圖形化的linux系統,有興趣的可以試一下)
Ghost這個類在實例化的時候可以傳入很多參數
具體可以參見ghost的源碼或者使用help方法查看,如下
>>> help(ghost.Ghost) Help on class Ghost in module ghost.ghost: class Ghost(__builtin__.object) | Ghost manages a QWebPage. | | :param user_agent: The default User-Agent header. | :param wait_timeout: Maximum step duration in second. | :param wait_callback: An optional callable that is periodically | executed until Ghost stops waiting. | :param log_level: The optional logging level. | :param log_handler: The optional logging handler. | :param display: A boolean that tells ghost to displays UI. | :param viewport_size: A tuple that sets initial viewport size. | :param ignore_ssl_errors: A boolean that forces ignore ssl errors. | :param plugins_enabled: Enable plugins (like Flash). | :param java_enabled: Enable Java JRE. | :param plugin_path: Array with paths to plugin directories | (default ['/usr/lib/mozilla/plugins']) | :param download_images: Indicate if the browser should download images | | Methods defined here: | | __del__(self) | | __enter__(self) | | __exit__(self, exc_type, exc_val, exc_tb) | | __init__(self, user_agent='Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/535....TML, like Gecko) Chrome/15.0.874.121 Safari/535.2', wait_timeout=8, wait_callback=None, log_level=30, log_handler=<logging.StreamHandler object>, display=False, viewport_size=(800, 600), ignore_ssl_errors=True, plugins_enabled=False, java_enabled=False, javascript_enabled=True, plugin_path=['/usr/lib/mozilla/plugins'], download_images=True, show_scrollbars=True, network_access_manager_class=<class 'ghost.ghost.NetworkAccessManager'>) | | append_popup_message(self, message)
簡單解釋一下我所知道的參數的作用
- user_agent 這個是瀏覽器頭部,作用就不解釋了,請自行百度
- wait_timeout 超時參數,有些網頁加載很慢,這個超時會顯示加載時間,當加載時間超出后,就不在等待頁面加載,而繼續執行下一段代碼
- wait_callback 沒用過。。
- log_level 日志級別
- display 前面已經演示了
- viewport_size 窗口大小,默認窗口大小是800*600,不過這個可以自己設置,例如
>>> gh = ghost.Ghost(display=True, viewport_size=(1000, 100))
- download_images 是否加載網頁上的圖片,有時候為了提高網頁的加載速度或別的目的,需要禁止圖片的加載
- plugins_enabled 是否使用插件,默認為False,例如如果不改為True的話,就無法播放需要使用flash插件的視頻,打開的視頻網頁就無法播放
好了,別的參數沒用過
實例化完之后,我們就有了一個瀏覽器對象,名字就是gh(我的習慣)
然后利用dir查看gh的方法和屬性
>>> dir(gh) ['__class__', '__del__', '__delattr__', '__dict__', '__doc__', '__enter__', '__exit__', '__format__', '__getattribute__', '__hash__', '__init__', '__module__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', '_alert', '_app', '_authenticate', '_confirm_expected', '_on_manager_ssl_errors', '_page_load_started', '_page_loaded', '_prompt_expected', '_release_last_resources', '_reply_download_content', '_request_ended', '_unsupported_content', '_upload_file', 'append_popup_message', 'call', 'capture', 'capture_to', 'clear_alert_message', 'click', 'confirm', 'content', 'cookie_jar', 'cookies', 'delete_cookies', 'display', 'evaluate', 'evaluate_js_file', 'exists', 'exit', 'fill', 'fire', 'frame', 'global_exists', 'hide', 'http_resources', 'id', 'ignore_ssl_errors', 'load_cookies', 'loaded', 'logger', 'main_frame', 'manager', 'open', 'page', 'popup_messages', 'print_to_pdf', 'prompt', 'region_for_selector', 'save_cookies', 'scroll_to_anchor', 'set_field_value', 'set_proxy', 'set_viewport_size', 'show', 'sleep', 'user_agent', 'wait_callback', 'wait_for', 'wait_for_alert', 'wait_for_page_loaded', 'wait_for_selector', 'wait_for_text', 'wait_timeout', 'wait_while_selector', 'webview']
最基本的方法就是open了
>>> help(gh.open)
Help on method open in module ghost.ghost:
open(self, address, method='get', headers={}, auth=None, body=None, default_popup_response=None, wait=True, timeout=None, client_certificate=None) method of ghost.ghost.Ghost instance
Opens a web page.
:param address: The resource URL.
:param method: The Http method.
:param headers: An optional dict of extra request hearders.
:param auth: An optional tuple of HTTP auth (username, password).
:param body: An optional string containing a payload.
:param default_popup_response: the default response for any confirm/
alert/prompt popup from the Javascript (replaces the need for the with
blocks)
:param wait: If set to True (which is the default), this
method call waits for the page load to complete before
returning. Otherwise, it just starts the page load task and
it is the caller's responsibilty to wait for the load to
finish by other means (e.g. by calling wait_for_page_loaded()).
:param timeout: An optional timeout.
:param client_certificate An optional dict with "certificate_path" and
"key_path" both paths corresponding to the certificate and key files
:return: Page resource, and all loaded resources, unless wait
is False, in which case it returns None.
>>>
顧名思義,該方法的作用是打開一個網頁或別的什么頁面,利用help我們可以看到他的參數
好吧,貌似這么多參數,我只用過一個,就是address了
比如打開百度
>>> page, source = gh.open('http://www.baidu.com')
代碼如上,然后我們可以看到下圖,
不過當上面的代碼執行完之后,瀏覽器窗口是不可以使用鼠標或鍵盤操作的
,會進入一種很像卡死的狀態,未響應,不過如果想操作這個窗口,也是有辦法的,如下
>>> gh.sleep(10)
sleep方法可以傳入秒數,在指定時間內讓這個窗口保持活動狀態,但同時也能組織代碼向下繼續運行
但在這10秒內,我們就可已把這個窗口當作一個真正的瀏覽器來進行操作,雖然這個瀏覽器沒那么多的功能吧
當然,我們的目的是用代碼來操作這個瀏覽器,因此這個sleep也沒什么用,我主要用他來等待頁面加載
在打開百度的時候,代碼如下
>>> page, resources = gh.open("http://www.baidu.com")
我使用了兩個變量來接受open方法的返回值,在ghost這個模塊里,大部分方法,只要涉及到頁面加載的都會放回兩個值
具體返回什么可以在ghost的源碼里看到
以open方法為例,對抓包有所了解,或者寫過網站的人,都知道在打開一個網頁時,會加載很多的資源,不是僅僅加載當前這個主頁面就夠了
在ghost里,每個被加載過來的資源都是一個HttpResource對象,下圖是源碼中這個對象的部分
class HttpResource(object):
"""Represents an HTTP resource.
"""
def __init__(self, ghost, reply, content):
self.ghost = ghost
self.url = reply.url().toString()
self.content = content
try:
self.content = unicode(content)
except UnicodeDecodeError:
self.content = content
通過dir,我們可以知道這個HttpResource對象的基本方法,不細說了,差不多也能看出來這些方法都是什么意思
>>> dir(page) ['__class__', '__delattr__', '__dict__', '__doc__', '__format__', '__getattribute__', '__hash__', '__init__', '__module__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', '_reply', 'content', 'ghost', 'headers', 'http_status', 'url'] >>>
那么page就是加載的主頁面的資源對象,resources則是其他資源對象的列表
那么ghost是怎么區分誰是主頁面呢,其實很簡單
源碼如下
def wait_for_page_loaded(self, timeout=None):
"""Waits until page is loaded, assumed that a page as been requested.
:param timeout: An optional timeout.
"""
self.wait_for(lambda: self.loaded,
'Unable to load requested page', timeout)
resources = self._release_last_resources()
page = None
url = self.main_frame.url().toString()
url_without_hash = url.split("#")[0]
for resource in resources:
if url == resource.url or url_without_hash == resource.url:
page = resource
self.logger.info('Page loaded %s' % url)
return page, resources
哈哈,是不是很簡單,不知道的時候我還以為多么高大上呢
其實這個HttpResource對象,我用到的方法只有url,content,url用來確定是不是我想要的資源,content用來獲取資源的內容
在打開一個頁面時,可能會出現超時,超時的情況下,ghost會拋出一個異常TimeoutError,請注意捕獲
>>> gh.open('http://www.google.com')
Traceback (most recent call last):
File "<pyshell#4>", line 1, in <module>
gh.open('http://www.google.com')
File "C:\Python27\lib\site-packages\ghost.py-0.1.1-py2.7.egg\ghost\ghost.py", line 850, in open
return self.wait_for_page_loaded(timeout=timeout)
File "C:\Python27\lib\site-packages\ghost.py-0.1.1-py2.7.egg\ghost\ghost.py", line 1144, in wait_for_page_loaded
'Unable to load requested page', timeout)
File "C:\Python27\lib\site-packages\ghost.py-0.1.1-py2.7.egg\ghost\ghost.py", line 1122, in wait_for
raise TimeoutError(timeout_message)
TimeoutError: Unable to load requested page
下面進入正題,打開一個頁面后,我們需要用代碼去操作這個頁面,因此ghost模塊提供了很多的方法
我就一個一個解釋一下我會使用的吧
還是以百度為例
show()
>>> gh.show()
該方法用來顯示瀏覽器窗口
hide()
>>> gh.hide()
該方法用來隱藏瀏覽器窗口
sleep()
不解釋了
def sleep(self, value=0.1):
started_at = time.time()
while time.time() <= (started_at + value):
time.sleep(0.01)
Ghost._app.processEvents()
exit()
該方法用於銷毀當前實例,相當於關閉瀏覽器
def exit(self):
"""Exits application and related."""
if self.display:
self.webview.close()
Ghost._app.quit()
del self.manager
del self.page
del self.main_frame
if hasattr(self, 'xvfb'):
self.xvfb.terminate()
>>> gh.exit()
>>> page, resources = gh.open('http://www.baidu.com')
Traceback (most recent call last):
File "<pyshell#8>", line 1, in <module>
page, resources = gh.open('http://www.baidu.com')
File "C:\Python27\lib\site-packages\ghost.py-0.1.1-py2.7.egg\ghost\ghost.py", line 842, in open
self.main_frame.load(request, method, body)
AttributeError: 'Ghost' object has no attribute 'main_frame'
exists()
>>> help(gh.exists)
Help on method exists in module ghost.ghost:
exists(self, selector) method of ghost.ghost.Ghost instance
Checks if element exists for given selector.
:param string: The element selector.
>>> gh.exists('#su')
True
exists方法接收一個參數selector,這個selector是css選擇器,ghost使用選擇器來操作頁面上的對象,不懂什么是選擇器的,請自行百度
上例中的selector 是 "#su" ,這個選擇器指向了百度頁面上那個百度一下按鈕
exists方法用於判斷當前頁面是否存在傳入的選擇器,存在返回True,不存在返回False,
這個方法在判斷頁面加載是否完成、或者頁面是否是預期頁面時很有用。
click()
源碼如下
@can_load_page
def click(self, selector):
"""Click the targeted element.
:param selector: A CSS3 selector to targeted element.
"""
if not self.exists(selector):
raise Error("Can't find element to click")
return self.evaluate("""
(function () {
var element = document.querySelector(%s);
var evt = document.createEvent("MouseEvents");
evt.initMouseEvent("click", true, true, window, 1, 1, 1, 1, 1,
false, false, false, false, 0, element);
return element.dispatchEvent(evt);
})();
""" % repr(selector))
>>> gh.click("#su", expect_loading=True)
(<ghost.ghost.HttpResource object at 0x0000000002571C18>, [<ghost.ghost.HttpResource object at 0x0000000002571C18>, <ghost.ghost.HttpResource object at 0x0000000002610390>, <ghost.ghost.HttpResource object at 0x00000000026104E0>, <ghost.ghost.HttpResource object at 0x00000000026106D8>, <ghost.ghost.HttpResource object at 0x0000000002610710>, <ghost.ghost.HttpResource object at 0x0000000002610748>, <ghost.ghost.HttpResource object at 0x00000000026107B8>, <ghost.ghost.HttpResource object at 0x0000000002610828>, <ghost.ghost.HttpResource object at 0x0000000002610898>, <ghost.ghost.HttpResource object at 0x00000000026109E8>, <ghost.ghost.HttpResource object at 0x0000000002610A58>, <ghost.ghost.HttpResource object at 0x0000000002610B00>, <ghost.ghost.HttpResource object at 0x0000000002610BA8>, <ghost.ghost.HttpResource object at 0x0000000002610C50>, <ghost.ghost.HttpResource object at 0x0000000002610CF8>, <ghost.ghost.HttpResource object at 0x0000000002610DA0>, <ghost.ghost.HttpResource object at 0x0000000002610EB8>, <ghost.ghost.HttpResource object at 0x0000000002610F60>, <ghost.ghost.HttpResource object at 0x0000000002610F98>, <ghost.ghost.HttpResource object at 0x0000000004B3C048>])
>>>
第一個參數為選擇器,后面的參數是裝飾器@can_load_page賦予的,所有被這個裝飾器裝飾的函數都可以添加這個參數,
click函數模擬鼠標左鍵點擊作用,點擊對象由selector確定,expect_loading參數用於告訴瀏覽器頁面是否需要加載,
因為不是所有的點擊都需要加載頁面的。
我們可以在需要加載的時候將其設為True,不需要加載的時候可以不傳,默認為False,因為頁面加載是會消耗時間的
同樣需要注意的是,凡是需要加載頁面的時候都要捕獲TimeoutError異常,因為超時是很常見的
fire()
有時候我們需要出發頁面上某個對象的效果,但又不是click,就要用到fire方法了
selector為對象的選擇器,event為要觸發的事件名字
例如下圖,就是實現click的另一種方式
>>> gh.fire("#su", 'click', expect_loading=True)
(<ghost.ghost.HttpResource object at 0x00000000026105F8>, [<ghost.ghost.HttpResource object at 0x00000000026105F8>, <ghost.ghost.HttpResource object at 0x00000000088D38D0>, <ghost.ghost.HttpResource object at 0x00000000088D3860>, <ghost.ghost.HttpResource object at 0x00000000088D3940>, <ghost.ghost.HttpResource object at 0x00000000088D39E8>, <ghost.ghost.HttpResource object at 0x00000000088D3A20>, <ghost.ghost.HttpResource object at 0x00000000088D3A58>, <ghost.ghost.HttpResource object at 0x00000000088D3AC8>, <ghost.ghost.HttpResource object at 0x00000000088D3B38>, <ghost.ghost.HttpResource object at 0x00000000088D3C18>, <ghost.ghost.HttpResource object at 0x00000000088D3CC0>, <ghost.ghost.HttpResource object at 0x00000000088D3D68>, <ghost.ghost.HttpResource object at 0x00000000088D3E10>, <ghost.ghost.HttpResource object at 0x00000000088D3EB8>, <ghost.ghost.HttpResource object at 0x00000000088D3F60>, <ghost.ghost.HttpResource object at 0x00000000092DD048>, <ghost.ghost.HttpResource object at 0x00000000092DD0B8>, <ghost.ghost.HttpResource object at 0x00000000092DD160>])
@can_load_page
def fire(self, selector, event):
"""Fire `event` on element at `selector`
:param selector: A selector to target the element.
:param event: The name of the event to trigger.
"""
self.logger.debug('Fire `%s` on `%s`' % (event, selector))
element = self.main_frame.findFirstElement(selector)
return element.evaluateJavaScript("""
var event = document.createEvent("HTMLEvents");
event.initEvent('%s', true, true);
this.dispatchEvent(event);
""" % event)
set_field_value()
@can_load_page
def set_field_value(self, selector, value, blur=True):
"""Sets the value of the field matched by given selector.
:param selector: A CSS selector that target the field.
:param value: The value to fill in.
:param blur: An optional boolean that force blur when filled in.
"""
self.logger.debug('Setting value "%s" for "%s"' % (value, selector))
該方法源碼比較長,就不上全圖了
作用就是向指定選擇器中添加數據
value即為添加的數據,字符轉類型的,
blur我就不解釋了,沒用過,沒看出來有什么作用,應該當光標進入會引發一些事件的時候才有用,一般情況下默認就行
>>> gh.set_field_value("#kw", "hello", expect_loading=True)
Traceback (most recent call last):
File "<pyshell#18>", line 1, in <module>
gh.set_field_value("#kw", "hello", expect_loading=True)
File "C:\Python27\lib\site-packages\ghost.py-0.1.1-py2.7.egg\ghost\ghost.py", line 215, in wrapper
timeout=kwargs.pop('timeout', None))
File "C:\Python27\lib\site-packages\ghost.py-0.1.1-py2.7.egg\ghost\ghost.py", line 1144, in wait_for_page_loaded
'Unable to load requested page', timeout)
File "C:\Python27\lib\site-packages\ghost.py-0.1.1-py2.7.egg\ghost\ghost.py", line 1122, in wait_for
raise TimeoutError(timeout_message)
TimeoutError: Unable to load requested page
fill()
用於向表單中添加數據,內部調用了set_field_value方法,其實也可以直接使用set_field_value方法,只不過fill比較方便
selector參數指向一個form表單,
values參數為字典類型
key是form中某個input的name值
value是你要填寫的值
>>> gh.fill("#form", {"wd":"hello"})
(True, [])
@can_load_page
def fill(self, selector, values):
"""Fills a form with provided values.
:param selector: A CSS selector to the target form to fill.
:param values: A dict containing the values.
"""
if not self.exists(selector):
raise Error("Can't find form")
resources = []
for field in values:
r, res = self.set_field_value(
"%s [name=%s]" % (selector, repr(field)), values[field])
resources.extend(res)
return True, resources
如果你注意了的話,會發現上面的方法其實貌似最后都是執行的js語句
如果你是js高手的話,你完全可以用js去實現上面的功能,以及上面沒有的功能,那么直接執行js的方法就是
evaluate()
參數script為一段js代碼
返回值為js執行后的返回值(沒有返回值就是None)和執行過程中產生的資源對象列表(open方法中的第二個返回值)
@can_load_page
def evaluate(self, script):
"""Evaluates script in page frame.
:param script: The script to evaluate.
"""
return (
self.main_frame.evaluateJavaScript("%s" % script),
self._release_last_resources(),
)
evaluate_js_file()
從指定文件中讀取js代碼並執行,參數就不解釋了
def evaluate_js_file(self, path, encoding='utf-8', **kwargs):
"""Evaluates javascript file at given path in current frame.
Raises native IOException in case of invalid file.
:param path: The path of the file.
:param encoding: The file's encoding.
"""
with codecs.open(path, encoding=encoding) as f:
return self.evaluate(f.read(), **kwargs)
wait_for()
condition參數是一個判斷函數
當condition()返回為True時,wait_for函數才停止工作,
timeout_message參數為當超時后拋出的異常信息
timeout參數設置超時時間
后面有好幾個函數會調用這個函數去實現一些常用的功能
def wait_for(self, condition, timeout_message, timeout=None):
"""Waits until condition is True.
:param condition: A callable that returns the condition.
:param timeout_message: The exception message on timeout.
:param timeout: An optional timeout.
"""
timeout = self.wait_timeout if timeout is None else timeout
started_at = time.time()
while not condition():
if time.time() > (started_at + timeout):
raise TimeoutError(timeout_message)
self.sleep()
if self.wait_callback is not None:
self.wait_callback()
wait_for_alert()
等待頁面加載直到有alert動作
def wait_for_alert(self, timeout=None):
"""Waits for main frame alert().
:param timeout: An optional timeout.
"""
self.wait_for(lambda: self._alert is not None,
'User has not been alerted.', timeout)
msg = self._alert
self._alert = None
return msg, self._release_last_resources()
wait_for_page_loaded()
等待頁面完全加載成功
def wait_for_page_loaded(self, timeout=None):
"""Waits until page is loaded, assumed that a page as been requested.
:param timeout: An optional timeout.
"""
self.wait_for(lambda: self.loaded,
'Unable to load requested page', timeout)
resources = self._release_last_resources()
page = None
url = self.main_frame.url().toString()
url_without_hash = url.split("#")[0]
for resource in resources:
if url == resource.url or url_without_hash == resource.url:
page = resource
self.logger.info('Page loaded %s' % url)
return page, resources
wait_for_selector()
等待頁面加載直到指定選擇器出現
def wait_for_selector(self, selector, timeout=None):
"""Waits until selector match an element on the frame.
:param selector: The selector to wait for.
:param timeout: An optional timeout.
"""
self.wait_for(
lambda: self.exists(selector),
'Can\'t find element matching "%s"' % selector,
timeout,
)
return True, self._release_last_resources()
wait_while_selector()
等待頁面加載直到指定選擇器消失
def wait_while_selector(self, selector, timeout=None):
"""Waits until the selector no longer matches an element on the frame.
:param selector: The selector to wait for.
:param timeout: An optional timeout.
"""
self.wait_for(
lambda: not self.exists(selector),
'Element matching "%s" is still available' % selector,
timeout,
)
return True, self._release_last_resources()
wait_for_text()
等待頁面加載直到指定文本出現
def wait_for_text(self, text, timeout=None):
"""Waits until given text appear on main frame.
:param text: The text to wait for.
:param timeout: An optional timeout.
"""
self.wait_for(
lambda: text in self.content,
'Can\'t find "%s" in current frame' % text,
timeout,
)
return True, self._release_last_resources()
下面說一下截圖
region_for_selector()
此函數根據selector返回此選擇器的一個同時包含左上和右下坐標的元組
def region_for_selector(self, selector):
"""Returns frame region for given selector as tuple.
:param selector: The targeted element.
"""
geo = self.main_frame.findFirstElement(selector).geometry()
try:
region = (geo.left(), geo.top(), geo.right(), geo.bottom())
except:
raise Error("can't get region for selector '%s'" % selector)
return region
PS:有時候無法寫出一個想截圖的元素的選擇器不是唯一的,無法定位,則可以先獲取到所有的同樣選擇器的元素,然后根據其他條件,比如內容判斷出那個是目標元素,然后使用geometry()方法獲取這個元素的坐標進行截圖
代碼如下:
selector = 'div' elements_div = gh.main_frame.findAllElements(selector) for element in elements_div: if 'target' in element.toPlainText(): break geo = element.geometry() region = (geo.left(), geo.top(), geo.right(), geo.bottom())
capture()
此函數用來根據指定的條件截取網頁上的某部分,不指定任何條件的話就截取整個網頁
def capture(
self,
region=None,
selector=None,
format=None,
):
"""Returns snapshot as QImage.
:param region: An optional tuple containing region as pixel
coodinates.
:param selector: A selector targeted the element to crop on.
:param format: The output image format.
"""
if format is None:
format = QImage.Format_ARGB32_Premultiplied
參數region 是一個元組,將需要截取的區域的左上角(x1,y1)和右下角(x2,y2)的坐標整合在一起(x1,y1,x2,y2)
例如
>>> region = (500, 0, 800, 500)
>>> gh.capture_to("./baidu.png", region=region)
參數selector是選擇器,ghost會根據選擇器的范圍進行截圖
其實就是算選擇器的坐標,然后再根據坐標截圖
>>> gh.capture_to("./baidu.png", selector='#su')
region的優先級大於selector
if region is None and selector is not None:
region = self.region_for_selector(selector)
有時候使用選擇器可能不會把我們想截取的部分全部選中,這時就要用到region了
capture_to()
其實就是調用capture()方法並save(),使用capture_to()方便一些,不用save了
def capture_to(
self,
path,
region=None,
selector=None,
format=None,
):
"""Saves snapshot as image.
:param path: The destination path.
:param region: An optional tuple containing region as pixel
coodinates.
:param selector: A selector targeted the element to crop on.
:param format: The output image format.
"""
if format is None:
format = QImage.Format_ARGB32_Premultiplied
self.capture(region=region, format=format,
selector=selector).save(path)
下面說一下cookie的處理
cookies
返回包含所有cookie的一個列表
@property
def cookies(self):
"""Returns all cookies."""
return self.cookie_jar.allCookies()
delete_cookies()
清除所有cookie
def delete_cookies(self):
"""Deletes all cookies."""
self.cookie_jar.setAllCookies([])
load_cookies()
參數cookie_storage 為CookieJar對象或文件名,當為文件名時,cookie信息會從指定文件里加載
參數keep_old為是否保留已經存在的cookie
PS:使用cookielib.LWPCookieJar的時候,無論是保存cookie到文件還是從文件加載cookie,默認都是會把過期的cookie和含有discard屬性的cookie丟棄的,而有些網站在登錄之后會把一些很關鍵的cookie設為discard,就導致把cookie保存到文件之后會丟失一部分,造成下次無法使用,這是一個坑,還有更深的一個坑就是,在ghost中使用load_cookies的時候,從文件中讀取cookie, 默認是使用LWPCookieJar的load方法加載,並且默認丟棄過期和discard的cookie,並且無法通過指定參數來改變這個默認設置,因此如果你想用會被丟棄的cookie的時候,需要先使用LWPCookieJar的的load方法從文件中加載cookie,加載的時候執行 ignore_discard=True, ignore_expires=True,然后在使用ghost的load_cookies方法,參數為LWPCookieJar管理器
代碼如下:
import cookielib
gh = ghost.Ghost()
cj = cookielib.LWPCookieJar()
cj.load('cookie.txt', ignore_discard=True, ignore_expires=True)
gh.load_cookies(cj)
def load_cookies(self, cookie_storage, keep_old=False):
"""load from cookielib's CookieJar or Set-Cookie3 format text file.
:param cookie_storage: file location string on disk or CookieJar
instance.
:param keep_old: Don't reset, keep cookies not overridden.
"""
save_cookies()
參數cookie_storage 為CookieJar對象或文件名,當為文件名時,cookie信息會保存到指定文件
def save_cookies(self, cookie_storage):
"""Save to cookielib's CookieJar or Set-Cookie3 format text file.
:param cookie_storage: file location string or CookieJar instance.
"""
當然你也可以直接操作gh.cookie_jar這樣你就可以更靈活的使用,畢竟真正封裝好的方法只是最基本的,常用的,不能面對一些特殊的需求的,
當需要做一些現有方法無法實現的功能時,最好研究下源碼,看內部是怎么實現的,這樣解決問題的路子就會變的很寬了
還有代理,差點忘了
set_proxy()
使用方法如下
參數type_ 代理類型,常見的有http,https
參數host 代理ip地址
參數port 代理端口
>>> gh.set_proxy("http", "192.168.1.1", 80)
去掉代理時使用如下方法,也就是添加一個默認的代理
>>> gh.set_proxy("default")
def set_proxy(
self,
type_,
host='localhost',
port=8888,
user='',
password='',
):
"""Set up proxy for FURTHER connections.
:param type_: proxy type to use: \
none/default/socks5/https/http.
:param host: proxy server ip or host name.
:param port: proxy port.
"""
一些小技巧:
1,禁止圖片加載
在實例化的時候我們可以禁止圖片的加載,不過我們可能需要打開多個頁面,有些頁面是需要加載圖片的,有些是不需要的,但實例化的時候寫死了怎么辦呢
如下
#部分源碼
self.page.settings().setAttribute( QtWebKit.QWebSettings.AutoLoadImages, download_images)
download_images參數是實例化的時候傳入的,在源碼中ghost是如上圖所示去使用的,那么當你碰到需要下載圖片的時候就可以這么干
>>> gh.page.settings().setAttribute(
QtWebKit.QWebSettings.AutoLoadImages, False)
Traceback (most recent call last):
File "<pyshell#24>", line 2, in <module>
QtWebKit.QWebSettings.AutoLoadImages, False)
NameError: name 'QtWebKit' is not defined
不下載的時候把True改成False就行
注意的是參數更改后立刻生效,所以要判斷好什么時候改下載,什么時候不下載
上圖中有個異常 name 'QtWebKit' is not defined
因為我們是直接導入的ghost,當前作用域里並沒有QtWebKit這個東西,那么這個東西在哪里呢,看源碼
bindings = ["PySide", "PyQt4"]
def _import(name):
if binding is None:
return LazyBinding()
name = "%s.%s" % (binding.__name__, name)
module = __import__(name)
for n in name.split(".")[1:]:
module = getattr(module, n)
return module
QtWebKit = _import('QtWebKit')
我安裝的是PySide,因此我可以這么做就可以了
>>> from PySide import QtWebKit
>>> gh.page.settings().setAttribute(
QtWebKit.QWebSettings.AutoLoadImages, False)
>>>
如果你要用到這個技巧的話,可以把 from PySide import QtWebKit 放在腳本最開始處
2,如果你對dom模型熟悉的話,你可以直接操作當前的gh,main_frame從中獲取所需要的數據,而不是利用正則從page.content.data()中獲取數據
>>> gh.main_frame.findFirstElement("#su").toPlainText()
u''
>>> gh.main_frame.findFirstElement("#su").attribute('value')
u'\u767e\u5ea6\u4e00\u4e0b'
>>>
