python ghost.py使用笔记

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'
>>> 

转载于:https://www.cnblogs.com/dyfblog/p/4670249.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值