python ghost.py使用笔记
- >>> import ghost
- >>> dir(ghost)
- ['Error', 'Ghost', 'GhostTestCase', 'TimeoutError', '__builtins__', '__doc__', '__file__', '__name__', '__package__', '__path__', '__version__', 'ghost', 'logger', 'test']
- >>>
- >>>gh = ghost.Ghost(display=True)

- >>> 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插件的视频,打开的视频网页就无法播放
- >>> 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']
- >>> 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.
- >>>
- >>> page, source = gh.open('http://www.baidu.com')

- >>> gh.sleep(10)
- >>> page, resources = gh.open("http://www.baidu.com")
- 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(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']
- >>>
- 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
- >>> 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
- >>> gh.show()
- >>> gh.hide()
- def sleep(self, value=0.1):
- started_at = time.time()
- while time.time() <= (started_at + value):
- time.sleep(0.01)
Ghost._app.processEvents()
- 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'
- >>> 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
- @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>])
- >>>
- >>> 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)
- @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))
- >>> 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

- >>> 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
- @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(),
- )
- 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)
- 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()
- 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()
- 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
- 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()
- 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()
- 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()
- 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
- 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())
- 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 = (500, 0, 800, 500)
- >>> gh.capture_to("./baidu.png", region=region)

- >>> gh.capture_to("./baidu.png", selector='#su')

- if region is None and selector is not None:
- region = self.region_for_selector(selector)
- 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)
- @property
- def cookies(self):
- """Returns all cookies."""
- return self.cookie_jar.allCookies()
- def delete_cookies(self):
- """Deletes all cookies."""
- self.cookie_jar.setAllCookies([])
- 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.
- """
- 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.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.
- """
- #部分源码
self.page.settings().setAttribute(- QtWebKit.QWebSettings.AutoLoadImages, download_images)
- >>> 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
- 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')
- >>> from PySide import QtWebKit
- >>> gh.page.settings().setAttribute(
- QtWebKit.QWebSettings.AutoLoadImages, False)
- >>>
- >>> gh.main_frame.findFirstElement("#su").toPlainText()
- u''
- >>> gh.main_frame.findFirstElement("#su").attribute('value')
- u'\u767e\u5ea6\u4e00\u4e0b'
- >>>
python ghost.py使用笔记的更多相关文章
- Ghost.py 0.1b3 : Python Package Index
Ghost.py 0.1b3 : Python Package Index Ghost.py 0.1b3 Download Ghost.py-0.1b3.tar.gz Webkit based web ...
- Requests:Python HTTP Module学习笔记(一)(转)
Requests:Python HTTP Module学习笔记(一) 在学习用python写爬虫的时候用到了Requests这个Http网络库,这个库简单好用并且功能强大,完全可以代替python的标 ...
- 关于Python网络爬虫实战笔记①
python网络爬虫项目实战笔记①如何下载韩寒的博客文章 python网络爬虫项目实战笔记①如何下载韩寒的博客文章 1. 打开韩寒博客列表页面 http://blog.sina.com.cn/s/ar ...
- python网络爬虫学习笔记
python网络爬虫学习笔记 By 钟桓 9月 4 2014 更新日期:9月 4 2014 文章文件夹 1. 介绍: 2. 从简单语句中開始: 3. 传送数据给server 4. HTTP头-描写叙述 ...
- Python学习的个人笔记(基础语法)
Python学习的个人笔记 题外话: 我是一个大二的计算机系的学生,这份python学习个人笔记是趁寒假这一周在慕课网,w3cschool,还有借鉴了一些博客,资料整理出来的,用于自己方便的时候查阅, ...
- ghost.py在代用JavaScript时的超时问题
在写爬虫的时候,关于JavaScript的解析问题,我在网上找到的一个解决方案是使用ghost.py这个模块,他是一个基于webkit封装的一个客户端,可以用来解析动态页面.它的使用非常简单,它从2. ...
- 知了课堂 Python Flask零基础 笔记整理
目录 起步 安装Python2.7: Python虚拟环境介绍与安装: pip安装flask: 认识url: URL详解 web服务器和应用服务器以及web应用框架: Flask 第一个flask程序 ...
- 《简明Python编程》核心笔记(1~5章)
2014年8月20日 <简明Python编程>核心笔记 (1~5章) 昨天和今天两天时间里.把<简明Python编程>这一本书学完了,包含书上的代码.现把核心笔记记录下来,以 ...
- python调用py中rar的路径问题。
1.python调用py,在py中的os.getcwd()获取的不是py的路径,可以通过os.path.split(os.path.realpath(__file__))[0]来获取py的路径. 2. ...
随机推荐
- bzoj 4036 [HAOI2015]按位或——min-max容斥+FMT
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=4036 题解:https://www.cnblogs.com/Zinn/p/10260126. ...
- 判断网络类(获取mac) InternetCheck
using System; using System.Collections.Generic; using System.Net.NetworkInformation; using System.Ru ...
- C++等语言中整型int等的取值范围计算方式
举short为例说明 如果以最高位为符号位,二进制原码最大为0111111111111111=2的15次方减1=32767.最小为1111111111111111=-2的15次方减1=-32767此时 ...
- 使用JS 加入收藏,设为首页.
<script type="text/javascript" language="javascript"> function AddFavorite ...
- Makefile编写 二
变量 1. Makefile中变量和函数的展开(除规则命令行中的变量和函数以外),是在make读取makefile文件时进行的,包括“define”定义的变量. 2. 变量可以用来代表一个文件名列表. ...
- emacs之配置yasnippet
~/emacsConfig/auto-complete-yasnippet-setting.el (require 'yasnippet) (setq ac-sources (append '(ac- ...
- iSCSI 协议
iSCSI 协议 iSCSI协议结构 如同任何一个协议一样,iSCSI也有一个清晰的层次结构,根据OSI模型,iSCSI的协议栈自顶向下一共可以分为五层,如图所示: SCSI层:根据应用发出的请求建立 ...
- bzoj3802: Vocabulary
Description 给你三个字符串,这些字符串有些单词模糊不可认了,用"?"来代表. 现在你可以用任意英文小写字母来代表它们.要求是使得给定的三个字符串中 所有的"? ...
- bootstrap全局css样式
以下从官网抄来的,感觉还是很实用的,运用得好,灵活运用,非常方便快捷,能大大提高开发效率,也为调整不同尺寸的屏幕节省了时间. hidden-xs @media (max-width: 767px){ ...
- laravel上传文件到七牛云存储
背景 最近在用PHP和laravel框架做一个图片网站,需要将图片存贮到云端,搜索下了对比了下功能,发现七牛云存储不错(主要小流量免费),便选择使用七牛作为图片存储空间. 要实现的功能很简单,选择本地 ...