继续修改,未完成

This commit is contained in:
g1879 2024-06-29 23:01:42 +08:00
parent fddc472ad5
commit 139bee5a91
15 changed files with 100 additions and 201 deletions

View File

@ -54,7 +54,6 @@ class BaseElement(BaseParser):
def __init__(self, owner=None):
self.owner = owner
# self.page = owner._page if owner else None
self._type = 'BaseElement'
# ----------------以下属性或方法由后代实现----------------

View File

@ -213,9 +213,6 @@ class BasePage(BaseParser):
@property
def timeout(self) -> float: ...
@timeout.setter
def timeout(self, second: float) -> None: ...
@property
def url_available(self) -> bool: ...

View File

@ -47,7 +47,6 @@ class Browser(object):
r._chromium_options = opt
r.is_headless = is_headless
r.id = browser_id
r.address = opt.address
cls._BROWSERS[browser_id] = r
return r
@ -61,7 +60,6 @@ class Browser(object):
self._created = True
self._type = 'Browser'
self._driver = BrowserDriver(self.id, 'browser', self.address, self)
self._frames = {}
self._drivers = {}
@ -70,15 +68,14 @@ class Browser(object):
self._set = None
self._wait = None
self._timeouts = Timeout(page_load=self._chromium_options.timeouts['page_load'],
script=self._chromium_options.timeouts['script'],
base=self._chromium_options.timeouts['base'])
if self._chromium_options.timeouts['base'] is not None:
self._timeout = self._chromium_options.timeouts['base']
self._timeouts = Timeout(**self._chromium_options.timeouts)
self._load_mode = self._chromium_options.load_mode
self._download_path = str(Path(self._chromium_options.download_path).absolute())
self.retry_times = self._chromium_options.retry_times
self.retry_interval = self._chromium_options.retry_interval
self.user_data_path = self._chromium_options.user_data_path
self.address = self._chromium_options.address
self._driver = BrowserDriver(self.id, 'browser', self.address, self)
if self.is_headless != self._chromium_options.is_headless:
self.quit(3, True)
@ -113,54 +110,6 @@ class Browser(object):
self._session_options = SessionOptions() if session_options is True else session_options
def _get_driver(self, tab_id, owner=None):
"""新建并返回指定tab id的Driver
:param tab_id: 标签页id
:param owner: 使用该驱动的对象
:return: Driver对象
"""
d = self._drivers.pop(tab_id, None)
if not d:
d = Driver(tab_id, 'page', self.address)
d.owner = owner
self._all_drivers.setdefault(tab_id, set()).add(d)
return d
def _onTargetCreated(self, **kwargs):
"""标签页创建时执行"""
if (kwargs['targetInfo']['type'] in ('page', 'webview')
and kwargs['targetInfo']['targetId'] not in self._all_drivers
and not kwargs['targetInfo']['url'].startswith('devtools://')):
try:
tab_id = kwargs['targetInfo']['targetId']
d = Driver(tab_id, 'page', self.address)
self._drivers[tab_id] = d
self._all_drivers.setdefault(tab_id, set()).add(d)
except WebSocketBadStatusException:
pass
def _onTargetDestroyed(self, **kwargs):
"""标签页关闭时执行"""
tab_id = kwargs['targetId']
if hasattr(self, '_dl_mgr'):
self._dl_mgr.clear_tab_info(tab_id)
for key in [k for k, i in self._frames.items() if i == tab_id]:
self._frames.pop(key, None)
for d in self._all_drivers.get(tab_id, tuple()):
d.stop()
self._drivers.pop(tab_id, None)
self._all_drivers.pop(tab_id, None)
def _run_cdp(self, cmd, **cmd_args):
"""执行Chrome DevTools Protocol语句
:param cmd: 协议项目
:param cmd_args: 参数
:return: 执行的结果
"""
ignore = cmd_args.pop('_ignore', None)
r = self._driver.run(cmd, **cmd_args)
return r if __ERROR__ not in r else raise_error(r, ignore)
@property
def process_id(self):
"""返回浏览器进程id"""
@ -204,8 +153,7 @@ class Browser(object):
def tab_ids(self):
"""返回所有标签页id组成的列表"""
j = self._driver.get(f'http://{self.address}/json').json() # 不要改用cdp因为顺序不对
return [i['id'] for i in j if i['type'] in ('page', 'webview')
and not i['url'].startswith('devtools://')]
return [i['id'] for i in j if i['type'] in ('page', 'webview') and not i['url'].startswith('devtools://')]
@property
def latest_tab(self):
@ -213,8 +161,7 @@ class Browser(object):
当Settings.singleton_tab_obj==True时返回Tab对象否则返回tab id"""
return self.get_tab(self.tab_ids[0], as_id=not Settings.singleton_tab_obj)
def new_tab(self, url=None, new_window=False, background=False,
new_context=False):
def new_tab(self, url=None, new_window=False, background=False, new_context=False):
"""新建一个标签页
:param url: 新标签页跳转到的网址
:param new_window: 是否在新窗口打开标签页
@ -225,8 +172,7 @@ class Browser(object):
return self._new_tab(ChromiumTab, url=url, new_window=new_window,
background=background, new_context=new_context)
def new_mix_tab(self, url=None, new_window=False, background=False,
new_context=False):
def new_mix_tab(self, url=None, new_window=False, background=False, new_context=False):
"""新建一个标签页
:param url: 新标签页跳转到的网址
:param new_window: 是否在新窗口打开标签页
@ -237,8 +183,7 @@ class Browser(object):
return self._new_tab(MixTab, url=url, new_window=new_window,
background=background, new_context=new_context)
def _new_tab(self, obj, url=None, new_window=False, background=False,
new_context=False):
def _new_tab(self, obj, url=None, new_window=False, background=False, new_context=False):
"""新建一个标签页
:param obj: 要创建的Tab类型
:param url: 新标签页跳转到的网址
@ -273,7 +218,7 @@ class Browser(object):
:param title: 要匹配title的文本模糊匹配为None则匹配所有
:param url: 要匹配url的文本模糊匹配为None则匹配所有
:param tab_type: tab类型可用列表输入多个 'page', 'iframe' 为None则匹配所有
:param as_id: 是否返回标签页id而不是标签页对象dual_mode=False时无效
:param as_id: 是否返回标签页id而不是标签页对象
:return: Tab对象
"""
return self._get_tab(id_or_num=id_or_num, title=title, url=url, tab_type=tab_type, as_id=as_id)
@ -283,7 +228,7 @@ class Browser(object):
:param title: 要匹配title的文本
:param url: 要匹配url的文本
:param tab_type: tab类型可用列表输入多个
:param as_id: 是否返回标签页id而不是标签页对象dual_mode=False时无效
:param as_id: 是否返回标签页id而不是标签页对象
:return: Tab对象列表
"""
return self._get_tabs(title=title, url=url, tab_type=tab_type, as_id=as_id)
@ -294,30 +239,29 @@ class Browser(object):
:param title: 要匹配title的文本模糊匹配为None则匹配所有
:param url: 要匹配url的文本模糊匹配为None则匹配所有
:param tab_type: tab类型可用列表输入多个 'page', 'iframe' 为None则匹配所有
:param as_id: 是否返回标签页id而不是标签页对象dual_mode=False时无效
:param as_id: 是否返回标签页id而不是标签页对象
:return: Tab对象
"""
return self._get_tab(id_or_num=id_or_num, title=title, url=url, tab_type=tab_type, dual_mode=True, as_id=as_id)
return self._get_tab(id_or_num=id_or_num, title=title, url=url, tab_type=tab_type, mix=True, as_id=as_id)
def get_mix_tabs(self, title=None, url=None, tab_type='page', as_id=False):
"""查找符合条件的tab返回它们组成的列表title和url是与关系
:param title: 要匹配title的文本
:param url: 要匹配url的文本
:param tab_type: tab类型可用列表输入多个
:param as_id: 是否返回标签页id而不是标签页对象dual_mode=False时无效
:param as_id: 是否返回标签页id而不是标签页对象
:return: Tab对象列表
"""
return self._get_tabs(title=title, url=url, tab_type=tab_type, dual_mode=True, as_id=as_id)
return self._get_tabs(title=title, url=url, tab_type=tab_type, mix=True, as_id=as_id)
def _get_tab(self, id_or_num=None, title=None, url=None, tab_type='page',
dual_mode=False, as_id=False):
def _get_tab(self, id_or_num=None, title=None, url=None, tab_type='page', mix=False, as_id=False):
"""获取一个标签页对象id_or_num不为None时后面几个参数无效
:param id_or_num: 要获取的标签页id或序号序号从1开始可传入负数获取倒数第几个不是视觉排列顺序而是激活顺序
:param title: 要匹配title的文本模糊匹配为None则匹配所有
:param url: 要匹配url的文本模糊匹配为None则匹配所有
:param tab_type: tab类型可用列表输入多个 'page', 'iframe' 为None则匹配所有
:param dual_mode: 是否返回可切换模式的Tab对象
:param as_id: 是否返回标签页id而不是标签页对象dual_mode=False时无效
:param mix: 是否返回可切换模式的Tab对象
:param as_id: 是否返回标签页id而不是标签页对象mix=False时无效
:return: Tab对象
"""
if id_or_num is not None:
@ -326,12 +270,7 @@ class Browser(object):
elif isinstance(id_or_num, int):
id_or_num = self.tab_ids[id_or_num - 1 if id_or_num > 0 else id_or_num]
elif isinstance(id_or_num, ChromiumTab):
if as_id:
return id_or_num.tab_id
elif Settings.singleton_tab_obj:
return id_or_num
else:
return self._get_tab(id_or_num.tab_id) # fixme: 这里会出现循环调用
return id_or_num.tab_id if as_id else ChromiumTab(self, id_or_num.tab_id)
elif title == url is None and tab_type == 'page':
id_or_num = self.tab_ids[0]
@ -346,15 +285,15 @@ class Browser(object):
if as_id:
return id_or_num
with self._lock:
return MixTab(self, id_or_num) if dual_mode else ChromiumTab(self, id_or_num)
return MixTab(self, id_or_num) if mix else ChromiumTab(self, id_or_num)
def _get_tabs(self, title=None, url=None, tab_type='page', dual_mode=False, as_id=False):
def _get_tabs(self, title=None, url=None, tab_type='page', mix=False, as_id=False):
"""查找符合条件的tab返回它们组成的列表title和url是与关系
:param title: 要匹配title的文本
:param url: 要匹配url的文本
:param tab_type: tab类型可用列表输入多个
:param dual_mode: 是否返回可切换模式的Tab对象
:param as_id: 是否返回标签页id而不是标签页对象dual_mode=False时无效
:param mix: 是否返回可切换模式的Tab对象
:param as_id: 是否返回标签页id而不是标签页对象mix=False时无效
:return: Tab对象列表
"""
tabs = self._driver.get(f'http://{self.address}/json').json() # 不要改用cdp
@ -371,7 +310,7 @@ class Browser(object):
if as_id:
return [tab['id'] for tab in tabs]
with self._lock:
if dual_mode:
if mix:
return [MixTab(self, tab['id']) for tab in tabs]
else:
return [ChromiumTab(self, tab['id']) for tab in tabs]
@ -477,6 +416,53 @@ class Browser(object):
if ok:
break
def _get_driver(self, tab_id, owner=None):
"""新建并返回指定tab id的Driver
:param tab_id: 标签页id
:param owner: 使用该驱动的对象
:return: Driver对象
"""
d = self._drivers.pop(tab_id, None)
if not d:
d = Driver(tab_id, 'page', self.address)
d.owner = owner
self._all_drivers.setdefault(tab_id, set()).add(d)
return d
def _onTargetCreated(self, **kwargs):
"""标签页创建时执行"""
if (kwargs['targetInfo']['type'] in ('page', 'webview')
and kwargs['targetInfo']['targetId'] not in self._all_drivers
and not kwargs['targetInfo']['url'].startswith('devtools://')):
try:
tab_id = kwargs['targetInfo']['targetId']
d = Driver(tab_id, 'page', self.address)
self._drivers[tab_id] = d
self._all_drivers.setdefault(tab_id, set()).add(d)
except WebSocketBadStatusException:
pass
def _onTargetDestroyed(self, **kwargs):
"""标签页关闭时执行"""
tab_id = kwargs['targetId']
self._dl_mgr.clear_tab_info(tab_id)
for key in [k for k, i in self._frames.items() if i == tab_id]:
self._frames.pop(key, None)
for d in self._all_drivers.get(tab_id, tuple()):
d.stop()
self._drivers.pop(tab_id, None)
self._all_drivers.pop(tab_id, None)
def _run_cdp(self, cmd, **cmd_args):
"""执行Chrome DevTools Protocol语句
:param cmd: 协议项目
:param cmd_args: 参数
:return: 执行的结果
"""
ignore = cmd_args.pop('_ignore', None)
r = self._driver.run(cmd, **cmd_args)
return r if __ERROR__ not in r else raise_error(r, ignore)
def _on_disconnect(self):
Browser._BROWSERS.pop(self.id, None)
if self._chromium_options.is_auto_port and self._chromium_options.user_data_path:

View File

@ -11,7 +11,7 @@ from typing import List, Optional, Set, Dict, Union, Tuple
from .driver import BrowserDriver, Driver
from .._configs.chromium_options import ChromiumOptions
from .._configs.session_options import SessionOptions
from .._pages.chromium_base import Timeout, ChromiumBase
from .._pages.chromium_base import Timeout
from .._pages.chromium_tab import ChromiumTab, MixTab
from .._units.downloader import DownloadManager
from .._units.setter import BrowserSetter
@ -24,7 +24,8 @@ class Browser(object):
version: str = ...
retry_times: int = ...
retry_interval: float = ...
is_headless:bool = ...
is_headless: bool = ...
user_data_path: str = ...
_BROWSERS: dict = ...
_chromium_options: ChromiumOptions = ...
@ -115,14 +116,14 @@ class Browser(object):
title: str = None,
url: str = None,
tab_type: str = 'page',
dual_mode: bool = False,
mix: bool = False,
as_id: bool = False) -> Union[ChromiumTab, str]: ...
def _get_tabs(self,
title: str = None,
url: str = None,
tab_type: str = 'page',
dual_mode: bool = False,
mix: bool = False,
as_id: bool = False) -> List[ChromiumTab, str]: ...
def activate_tab(self, tab_id: str) -> None: ...

View File

@ -44,7 +44,7 @@ class ChromiumElement(DrissionElement):
:param backend_id: backend id
"""
super().__init__(owner)
self.tab = self.owner.tab
self.tab = self.owner._tab
self._select = None
self._scroll = None
self._rect = None
@ -900,7 +900,7 @@ class ShadowRoot(BaseElement):
:param backend_id: cdp中的backend id
"""
super().__init__(parent_ele.owner)
self.tab = self.owner.tab
self.tab = self.owner._tab
self.parent_ele = parent_ele
if backend_id:
self._backend_id = backend_id

View File

@ -65,23 +65,11 @@ class ChromiumBase(BasePage):
if not hasattr(self, '_listener'):
self._listener = None
# if isinstance(address, int) or (isinstance(address, str) and address.isdigit()):
# address = f'127.0.0.1:{address}'
# self._d_set_start_options(address)
self._d_set_runtime_settings()
self._connect_browser(tab_id)
# def _d_set_start_options(self, address):
# """设置浏览器启动属性
# :param address: 'ip:port'
# :return: None
# """
# self.address = address.replace('localhost', '127.0.0.1').lstrip('http://').lstrip('https://')
def _d_set_runtime_settings(self):
self._timeouts = Timeout(self)
self._load_mode = 'normal'
pass
def _connect_browser(self, tab_id=None):
"""连接浏览器,在第一次时运行

View File

@ -8,7 +8,7 @@
from pathlib import Path
from typing import Union, Tuple, List, Any, Optional, Literal
from .chromium_tab import ChromiumTab
from .chromium_tab import ChromiumTab, MixTab
from .._base.base import BasePage
from .._base.browser import Browser
from .._base.driver import Driver
@ -33,8 +33,8 @@ class ChromiumBase(BasePage):
def __init__(self,
browser: Browser,
tab_id: str = None):
self._tab:Union[ChromiumTab, MixTab, ChromiumFrame] = ...
self._browser: Browser = ...
self.tab: Union[ChromiumPage, ChromiumTab] = ...
self._driver: Driver = ...
self._frame_id: str = ...
self._is_reading: bool = ...

View File

@ -27,22 +27,10 @@ class ChromiumFrame(ChromiumBase):
:param ele: frame所在元素
:param info: frame所在元素信息
"""
self.tab = owner.tab
self._tab = owner._tab
self._target_page = owner
# if owner._type in ('ChromiumPage', 'WebPage'):
# self._target_page = self.tab = owner
# self._browser = owner.browser
# else: # ChromiumTab、Frame
# # self._page = owner.page
# self._browser = self._page.browser
# self._target_page = owner
# self.tab = owner.tab if owner._type == 'ChromiumFrame' else owner
# self.address = owner.address
# self._tab_id = owner.tab_id
self._backend_id = ele._backend_id
self._frame_ele = ele
self._states = None
self._reloading = False
node = info['node'] if not info else owner.run_cdp('DOM.describeNode', backendNodeId=ele._backend_id)['node']
@ -58,13 +46,7 @@ class ChromiumFrame(ChromiumBase):
obj_id = super().run_js('document;', as_expr=True)['objectId']
self.doc_ele = ChromiumElement(self, obj_id=obj_id)
self._rect = None
self._type = 'ChromiumFrame'
# end_time = perf_counter() + 2
# while perf_counter() < end_time:
# if self.url not in (None, 'about:blank'):
# break
# sleep(.1)
def __call__(self, locator, index=1, timeout=None):
"""在内部查找元素
@ -252,11 +234,6 @@ class ChromiumFrame(ChromiumBase):
"""返回cdp中的node id"""
return self.frame_ele._node_id
# @property
# def page(self):
# """返回所属Page对象"""
# return self._page
@property
def owner(self):
"""返回所属页面对象"""
@ -319,6 +296,11 @@ class ChromiumFrame(ChromiumBase):
"""返回frame的css selector绝对路径"""
return self.frame_ele.css_path
@property
def tab(self):
"""返回frame所在tab的id"""
return self._tab
@property
def tab_id(self):
"""返回frame所在tab的id"""

View File

@ -9,9 +9,7 @@ from pathlib import Path
from typing import Union, Tuple, List, Any, Optional
from .chromium_base import ChromiumBase
# from .chromium_page import ChromiumPage
from .chromium_tab import ChromiumTab
from .web_page import WebPage
from .chromium_tab import ChromiumTab, MixTab
from .._elements.chromium_element import ChromiumElement
from .._functions.elements import ChromiumElementsList
from .._units.listener import FrameListener
@ -29,7 +27,7 @@ class ChromiumFrame(ChromiumBase):
ele: ChromiumElement,
info: dict = None):
self._target_page: Union[ChromiumTab, ChromiumFrame] = ...
self.tab: ChromiumTab = ...
self._tab: Union[MixTab, ChromiumTab] = ...
self._set: ChromiumFrameSetter = ...
self._frame_ele: ChromiumElement = ...
self._backend_id: int = ...
@ -38,7 +36,7 @@ class ChromiumFrame(ChromiumBase):
self.doc_ele: ChromiumElement = ...
self._states: FrameStates = ...
self._reloading: bool = ...
self._rect: FrameRect = ...
self._rect: Optional[FrameRect] = ...
self._listener: FrameListener = ...
def __call__(self,
@ -64,9 +62,6 @@ class ChromiumFrame(ChromiumBase):
def _onInspectorDetached(self, **kwargs): ...
# @property
# def page(self) -> Union[ChromiumPage, WebPage]: ...
@property
def owner(self) -> ChromiumBase: ...
@ -124,6 +119,9 @@ class ChromiumFrame(ChromiumBase):
@property
def wait(self) -> FrameWaiter: ...
@property
def tab(self) -> Union[ChromiumTab, MixTab]: ...
@property
def tab_id(self) -> str: ...

View File

@ -45,10 +45,8 @@ class ChromiumTab(ChromiumBase):
return
self._created = True
self.tab = self
self._browser = browser
super().__init__(browser, tab_id)
self._rect = None
self._tab = self
self._type = 'ChromiumTab'
def _d_set_runtime_settings(self):
@ -210,14 +208,6 @@ class MixTab(SessionPage, ChromiumTab, BasePage):
"""返回通用timeout设置"""
return self.timeouts.base
@timeout.setter
def timeout(self, second):
"""设置通用超时时间
:param second: 秒数
:return: None
"""
self.set.timeouts(base=second)
def get(self, url, show_errmsg=False, retry=None, interval=None, timeout=None, **kwargs):
"""跳转到一个url
:param url: 目标url

View File

@ -28,7 +28,7 @@ class ChromiumTab(ChromiumBase):
def __new__(cls, browser: Browser, tab_id: str): ...
def __init__(self, browser: Browser, tab_id: str):
self._browser: Browser = ...
self._tab: ChromiumTab = ...
self._rect: Optional[TabRect] = ...
def _d_set_runtime_settings(self) -> None: ...
@ -64,7 +64,7 @@ class ChromiumTab(ChromiumBase):
class MixTab(SessionPage, ChromiumTab):
_browser: Browser = ...
_tab: MixTab = ...
_mode: str = ...
_has_driver: bool = ...
_has_session: bool = ...

View File

@ -61,8 +61,7 @@ class SessionPage(BasePage):
def _s_set_runtime_settings(self):
"""设置运行时用到的属性"""
self._timeout = self._session_options.timeout
self._download_path = None if self._session_options.download_path is None \
else str(Path(self._session_options.download_path).absolute())
self._download_path = str(Path(self._session_options.download_path or '.').absolute())
self.retry_times = self._session_options.retry_times
self.retry_interval = self._session_options.retry_interval

View File

@ -79,9 +79,6 @@ class WebPage(SessionPage, ChromiumPage, BasePage):
@property
def timeout(self) -> float: ...
@timeout.setter
def timeout(self, second: float) -> None: ...
def get(self,
url: str,
show_errmsg: bool = False,

View File

@ -162,9 +162,9 @@ class Clicker(object):
:return: DownloadMission对象
"""
if save_path:
self._ele.owner.tab.set.download_path(save_path)
self._ele.tab.set.download_path(save_path)
elif not self._ele.tab._browser._dl_mgr._running:
self._ele.owner.tab._browser.set.download_path('.')
self._ele.tab._browser.set.download_path('.')
obj = self._ele.tab._browser if new_tab else self._ele.owner.tab
if rename or suffix:

View File

@ -52,6 +52,7 @@ class BasePageSetter(object):
class BrowserBaseSetter(BasePageSetter):
"""Browser和ChromiumBase设置"""
@property
def load_mode(self):
@ -67,7 +68,6 @@ class BrowserBaseSetter(BasePageSetter):
"""
if base is not None:
self._owner.timeouts.base = base
self._owner._timeout = base
if page_load is not None:
self._owner.timeouts.page_load = page_load
@ -135,11 +135,6 @@ class ChromiumBaseSetter(BrowserBaseSetter):
super().__init__(owner)
self._cookies_setter = None
# @property
# def load_mode(self):
# """返回用于设置页面加载策略的对象"""
# return LoadMode(self._owner)
@property
def scroll(self):
"""返回用于设置页面滚动设置的对象"""
@ -152,31 +147,6 @@ class ChromiumBaseSetter(BrowserBaseSetter):
self._cookies_setter = CookiesSetter(self._owner)
return self._cookies_setter
# def retry_times(self, times):
# """设置连接失败重连次数"""
# self._owner.retry_times = times
#
# def retry_interval(self, interval):
# """设置连接失败重连间隔"""
# self._owner.retry_interval = interval
#
# def timeouts(self, base=None, page_load=None, script=None):
# """设置超时时间,单位为秒
# :param base: 基本等待时间,除页面加载和脚本超时,其它等待默认使用
# :param page_load: 页面加载超时时间
# :param script: 脚本运行超时时间
# :return: None
# """
# if base is not None:
# self._owner.timeouts.base = base
# self._owner._timeout = base
#
# if page_load is not None:
# self._owner.timeouts.page_load = page_load
#
# if script is not None:
# self._owner.timeouts.script = script
def user_agent(self, ua, platform=None):
"""为当前tab设置user agent只在当前tab有效
:param ua: user agent字符串
@ -354,14 +324,6 @@ class SessionPageSetter(BasePageSetter):
self._cookies_setter = SessionCookiesSetter(self._owner)
return self._cookies_setter
# def retry_times(self, times):
# """设置连接失败时重连次数"""
# self._owner.retry_times = times
#
# def retry_interval(self, interval):
# """设置连接失败时重连间隔"""
# self._owner.retry_interval = interval
def download_path(self, path):
"""设置下载路径
:param path: 下载路径
@ -376,7 +338,7 @@ class SessionPageSetter(BasePageSetter):
:param second: 秒数
:return: None
"""
self._owner.timeout = second
self._owner._timeout = second
def encoding(self, encoding, set_all=True):
"""设置编码