基于网页文档的提取方法将 HTML 文档视为文本进行处理,适用于处理含有大量文本信息且结构简单易于处理的单记录网页,或者具有实时要求的在线分析网页应用。 这种方式主要利用自然语言处理相关技术实现,通过理解 文本语义、分析上下文、设定提取规则等,实现对大段网页文档的快速处理。其中,较为知名的方法有 TSIMMIS、Web-OQL、Serrano、FAR-SW 和 FOREST,但这些方法由于通常需要人工的参与,且存在耗时长、效率低的弊端。 基于 DOM 结构信息的方法将 HTML 文档解析为相应的 DOM 树,然后根据 DOM 树的语法结构创建提取规则, 相对于以前的方法而言有了更高的性能和准确率。 W4F 和 XWRAP 将 HTML 文档解析成 DOM 树,然后通过组件化引导用户通过人工选择或者标记生成目标包装器代码。Omini、IEPAD 和 ITE 提取 DOM 树上的关键路径, 获取其中存在的重复模式。MDR 和 DEPTA 挖掘了页面中的数据区域,得到数据记录的模式。CECWS 通过聚类算法从数据库中提取出自同一网站的一组页面,并进行 DOM 树结构的对比,删除其中的静态部分,保留动态内容作为信息提取的结果。虽然此类方法相对于上一类方法 具有较高的提取精度,且克服了对大段连续文本的依赖, 但由于网页的 DOM 树通常较深,含有大量 DOM 节点, 因此基于 DOM 结构信息的方法具有较高的时间和空间消耗。目前来说,大部分原理还是基于 DOM 节点的文本密度、标点符号密度等计算的,其准确率还是比较可观的。今天所介绍的 Readability 和 Newspaper 的库的实现原理就是类似。 目前比较先进的是基于视觉信息的网页信息提取方法,通过浏览器接口或者内核对目标网页预渲染,然后基于网页的视觉规律提取网页数据记录。经典的 VIPS 算法首先从 DOM 树中提取出所有合适的页面区域,然后根据这些页面和分割条重新构建 Web 页面的语义结构。作为对 VIPS 的拓展,ViNT、ViPER、ViDE 也成功利用了网页的视觉特征来实现数据提取。CMDR 为通过神经网络学习多记录型页面中的特征,结合基于 DOM 结构信息的 MDR 方法,挖掘社区论坛页面的数据区域。与上述方法不同,VIBS 将图像领域的 CNN 卷积神经网络运用于网页的截图,同时通过类 VIPS 算法生成视觉块,最后结合两个阶段的结果识别网页的正文区域。另外还有最新的国内提出的 VBIE 方法,基于网页视觉的基础上改进,可以实现无监督的网页信息提取。
authors: ['Cnn Wire'] date: 2013-12-30 00:00:00 text: By Leigh Ann Caldwell
WASHINGTON (CNN) — Not everyone subscribes to a New Year’s resolution, but Americans will be required to follow new laws in 2014.
Some 40,000 measures taking effect range from sweeping, national mandates under Obamacare to marijuana legalization in Colorado, drone prohibition in Illinois and transgender protections in California.
Although many new laws are controversial, they made it through legislatures, public referendum or city councils and represent the shifting composition of American beliefs. ... ... Colorado: Marijuana becomes legal in the state for buyers over 21 at a licensed retail dispensary.
(Sourcing: much of this list was obtained from the National Conference of State Legislatures). top image: https://localtvkstu.files.wordpress.com/2012/04/national-news-e1486938949489.jpg?quality=85&strip=all movies: [] keywords: ['drones', 'national', 'guns', 'wage', 'law', 'pot', 'leave', 'family', 'states', 'state', 'latest', 'obamacare', 'minimum', 'laws'] summary: Oregon: Family leave in Oregon has been expanded to allow eligible employees two weeks of paid leave to handle the death of a family member. Arkansas: The state becomes the latest state requiring voters show a picture ID at the voting booth. Minimum wage and former felon employmentWorkers in 13 states and four cities will see increases to the minimum wage. New Jersey residents voted to raise the state’s minimum wage by $1 to $8.25 per hour. California is also raising its minimum wage to $9 per hour, but workers must wait until July to see the addition.
Building prefix dict from /usr/local/lib/python3.7/site-packages/jieba/dict.txt ... Dumping model to file cache /var/folders/1g/l2xlw12x6rncs2p9kh5swpmw0000gn/T/jieba.cache Loading model cost 1.7178938388824463 seconds. Prefix dict has been built succesfully. authors: [] title: 今年iPhone只有小改进?分析师:还有其他亮点 date:2019-09-0908:10:26+08:00 text: (原标题:Apple Bets More Cameras Can Keep iPhone Humming)
有人说,这个技术不是什么好技术。万一有人拿着我们的照片一变脸,就能够把我们任意的表情和头部动作模拟出来,拿着去做认证,比如刷脸支付什么的咋办,那我们的钱不就被盗刷了吗? 对于这个问题,支付宝官方也做了回应,支付宝称刷脸支付实际上会通过软硬件结合的方式进行检测,其会判断被刷物体是否是照片、视频或者软件模拟的方式生成的,可以有效避免身份冒用情况。其中有一个核心技术就是通过 3D 结构光摄像头来进行信息采集和识别,如果被拍摄物体是平面的,也就是说如果是照片或者视频,是无法通过检测的。 这时候我自然而然想到,既然用的是 3D 结构光摄像头,那么如果用了 3D 打印技术把一个人的肖像打印出来,或者用一个非常逼真的蜡像来进行刷脸识别,能不能通过呢?我看了一些报道,发现不少案例的确通过了刷脸测试,比如解开了 iPhone 面部识别锁等等。但要通过 3D 打印技术来模拟一个人的肖像成本还是蛮高的,所以基本上也不太会有人来搞这些。 如果对此还心有余悸的话,支付宝还回应称,即便是真的被盗刷了,支付宝也会通过保险公司进行全额赔付。 所以基本上是不用担心其安全性的,尤其是 Zao 这个软件的出现是没有对刷脸支付的风险造成大的影响的,其就是增加了一个活体视频模拟的实现,对刷脸支付的安全性没有出现大的突破性威胁。
用户上传发布内容后,意味着同意授予 ZAO 及其关联公司以及 ZAO 用户在“全球范围内完全免费、不可撤销、永久、可转授权和可再许可的权利”,“包括但不限于可以对用户内容进行全部或部分的修改与编辑(如将短视频中的人脸或者声音换成另一个人的人脸或者声音等)以及对修改前后的用户内容进行信息网络传播以及《著作权法》规定的由著作权人享有的全部著作财产权利及邻接权利”。
这条款没人说还真没注意到,因为一般咱用一个软件,一般不会去仔细看它的条款,那么密密麻麻的一坨,有几个人会去仔细看呢?但要不同意,这个软件还没法用,所以用过这个软件的人,这个条款一定是已经同意了。 这条条款其实是很过分的,同意授予 Zao 及其关联公司以及 Zao 用户在“全球范围内完全免费、不可撤销、永久、可转授权和可再许可的权利。注意这里有几个字,完全免费、不可撤销、永久、可转授权、可再许可,这几个词就代表我们已经把我们的肖像权永久授予了 Zao 及其关联公司了,而且不能撤销,账号注销了也不能撤销,也就是以后它们可以有权利永久滥用我们的肖像。更可怕的是,其中还有一个词叫可转授权,那也就是说,Zao 可以对我们的肖像权进行转授权,你懂得,给点钱,啥办不到呢?这就更无法控制了,这可能就意味着,世界上任何一个人可能都能获得我们的肖像权。 所以说,如果你还没用的话,一定要谨慎谨慎再谨慎! 哎,反正我已经同意了,貌似我现在也没什么办法了。
社会影响
这个软件的出现,更深一点想,其实它所隐含的影响还是蛮大的。 有了这个变脸技术,如果有人获得了我们在条款里面所”捐出“的肖像权,拿着我们的照片去生产那种你懂得的影片,把视频里面的男主或者女主换成我们的人脸,然后到处传播,或者以此作为敲诈勒索的工具。即便我们有理,那也说不清了,首先这个条款已经说了它们可以有权利随意使用我们的肖像,所以告侵犯肖像权已经行不通了,而且即使我们有证据证明这是假的,但这种视频的传播也一定会带来非常大的影响。 按照现在大众们的观念,比如说一张图,我们如果不信的话可以说它是 P 的,但如果换做是视频的话,很多人可能就会相信了,因为很多人不知道视频中的肖像也可以伪造得这么真了,毕竟很多人并不知道这种技术。因此,有了这种技术的出现,以后视频类的证据,可能也不可信了。因此这个软件的出现,可以说从另一个侧面昭示,以后视频也不能作为犯案的证据和验证人的真伪的依据了。 所以以后可能是这样子的:
坐在电脑面前的网络女主播,即便不开美颜和滤镜,你所看到的她也不是真的她了。
你要给人打个钱,说开个视频吧,我看看是不是真的你,即便看到的是他,你也不能信了。
有人要 Qiao Zha 你,把你的人脸换成 Zuo An 分子的脸,你到哪里说理去?
某一天,你作为男女主角,出现在了 P 站和 91….
我一开始想的还没这么深,边想边写,写到这,我自己都开始后怕了… 怎么甚至感觉,以后的社会可能会乱套了呢?这可能就是 AI 发展的一个隐患吧。 所以写到最后,虽然这个软件很有意思,但还是劝大家还没有用的就不要用了吧,真的很可怕。同时我也不知道这个软件这样的条款和做法会不会有什么问题,但还是希望能引起有关部门的注意。 以后,也希望大家也可以在使用软件的时候,要更加谨慎和小心,有条款就稍微看一看,尤其是对于这种和用户隐私相关的软件,要更加心存戒备。
name: Nicholas Wilson address: 70561 Simmons Road Apt. 893 Lake Raymondville, HI 35240 text: Bothbegin bring federal space. Official start idea specific. Able under young fire. Who showline traditional easy people. Until economic lead event case. Technology college his director style.
[<faker.providers.user_agent.Providerobject at 0x10249de48>, <faker.providers.ssn.zh_CN.Providerobject at 0x10249dc18>, <faker.providers.python.Providerobject at 0x10249dd68>, <faker.providers.profile.Providerobject at 0x10249dcc0>, <faker.providers.phone_number.zh_CN.Providerobject at 0x10249dc88>, <faker.providers.person.zh_CN.Providerobject at 0x10249de80>, <faker.providers.misc.Providerobject at 0x10249df60>, <faker.providers.lorem.zh_CN.Providerobject at 0x10249dc50>, <faker.providers.job.zh_CN.Providerobject at 0x10249de10>, <faker.providers.isbn.Providerobject at 0x10249c6d8>, <faker.providers.internet.zh_CN.Providerobject at 0x10249c828>, <faker.providers.geo.en_US.Providerobject at 0x102484748>, <faker.providers.file.Providerobject at 0x102484828>, <faker.providers.date_time.en_US.Providerobject at 0x1023789e8>, <faker.providers.currency.Providerobject at 0x102484780>, <faker.providers.credit_card.Providerobject at 0x1024845f8>, <faker.providers.company.zh_CN.Providerobject at 0x102499ef0>, <faker.providers.color.en_US.Providerobject at 0x1023532e8>, <faker.providers.barcode.Providerobject at 0x101cb6d30>, <faker.providers.bank.en_GB.Providerobject at 0x102378f98>, <faker.providers.automotive.en_US.Providerobject at 0x1017a5c50>, <faker.providers.address.zh_CN.Providerobject at 0x101787c18>]
Expected type 'int', got 'float' instead This inspection detects type errors in function call expressions. Due to dynamic dispatch and duck typing, this is possible in a limited but useful number of cases. Types of function parameters can be specified in docstrings orin Python 3 function annotations.
另外也有一些库是支持类型检查的,比如 mypy,安装之后,利用 mypy 即可检查出 Python 脚本中不符合类型注解的调用情况。 上面只是用一个简单的 int 类型做了实例,下面我们再看下一些相对复杂的数据结构,例如列表、元组、字典等类型怎么样来声明。 可想而知了,列表用 list 表示,元组用 tuple 表示,字典用 dict 来表示,那么很自然地,在声明的时候我们就很自然地写成这样了:
这里可以看到主要用到的类型有 Set、Union、List、MutableMapping、Optional,这些在上文都已经做了解释,另外这里使用了多次 Union 来声明了一些新的类型,如 _Find 则要么是是 Element 对象的列表,要么是单个 Element 对象,_Result 则要么是 Result 对象的列表,要么是单个 Result 对象。另外 _Attrs 其实就是字典类型,这里用 MutableMapping 来表示了,没有用 Dict,也没有用 Mapping。 接下来再看一个 Element 类的声明:
classElement(BaseParser): """An element of HTML. :param element: The element from which to base the parsing upon. :param url: The URL from which the HTML originated, used for ``absolute_links``. :param default_encoding: Which encoding to default to. """
def__repr__(self) -> str: attrs = ['{}={}'.format(attr, repr(self.attrs[attr])) for attr in self.attrs] return"<Element {} {}>".format(repr(self.element.tag), ' '.join(attrs))
@property defattrs(self) -> _Attrs: """Returns a dictionary of the attributes of the :class:`Element <Element>` (`learn more <https://www.w3schools.com/tags/ref_attributes.asp>`_). """ if self._attrs isNone: self._attrs = {k: v for k, v in self.element.items()}
# Split class and rel up, as there are ussually many of them: for attr in ['class', 'rel']: if attr in self._attrs: self._attrs[attr] = tuple(self._attrs[attr].split())
我们在上一节了解了代理的设置方法,利用代理我们可以解决目标网站封 IP 的问题,而在网上又有大量公开的免费代理,其中有一部分可以拿来使用,或者我们也可以购买付费的代理 IP,价格也不贵。但是不论是免费的还是付费的,都不能保证它们每一个都是可用的,毕竟可能其他人也可能在用此 IP 爬取同样的目标站点而被封禁,或者代理服务器突然出故障或网络繁忙。一旦我们选用了一个不可用的代理,势必会影响我们爬虫的工作效率。 所以说,在用代理时,我们需要提前做一下筛选,将不可用的代理剔除掉,保留下可用代理,接下来在获取代理时从可用代理里面取出直接使用就好了。 所以本节我们来搭建一个高效易用的代理池。
接口模块需要用 API 来提供对外服务的接口,其实我们可以直接连数据库来取,但是这样就需要知道数据库的连接信息,不太安全,而且需要配置连接,所以一个比较安全和方便的方式就是提供一个 Web API 接口,通过访问接口即可拿到可用代理。另外由于可用代理可能有多个,我们可以提供随机返回一个可用代理的接口,这样保证每个可用代理都可以取到,实现负载均衡。
defrun(self): print('获取器开始执行') ifnot self.is_over_threshold(): for callback_label in range(self.crawler.__CrawlFuncCount__): callback = self.crawler.__CrawlFunc__[callback_label] proxies = self.crawler.get_proxies(callback) for proxy in proxies: self.redis.add(proxy)
我们在做爬虫的过程中经常会遇到这样的情况,最初爬虫正常运行,正常抓取数据,一切看起来都是那么的美好,然而一杯茶的功夫可能就会出现错误,比如 403 Forbidden,这时候打开网页一看,可能会看到“您的 IP 访问频率太高”这样的提示,或者跳出一个验证码让我们输入,输入之后才可能解封,但是输入之后过一会儿就又这样了。 出现这样的现象的原因是网站采取了一些反爬虫的措施,比如服务器会检测某个 IP 在单位时间内的请求次数,如果超过了这个阈值,那么会直接拒绝服务,返回一些错误信息,这种情况可以称之为封 IP,于是乎就成功把我们的爬虫禁掉了。 既然服务器检测的是某个 IP 单位时间的请求次数,那么我们借助某种方式来伪装我们的 IP,让服务器识别不出是由我们本机发起的请求,不就可以成功防止封 IP 了吗? 所以这时候代理就派上用场了,本章我们会详细介绍一下代理的基本知识及各种代理的使用方式,帮助爬虫脱离封 IP 的苦海。 本章接下来会介绍代理的设置、代理池的维护、付费代理的使用、ADSL拨号代理的搭建方法。
import time from io import BytesIO from PIL import Image from selenium import webdriver from selenium.common.exceptions import TimeoutException from selenium.webdriver.common.by import By from selenium.webdriver.support.ui import WebDriverWait from selenium.webdriver.support import expected_conditions as EC
defget_points(self, captcha_result): """ 解析识别结果 :param captcha_result: 识别结果 :return: 转化后的结果 """ groups = captcha_result.get('pic_str').split('|') locations = [[int(number) for number in group.split(',')] for group in groups] return locations
deftouch_click_words(self, locations): """ 点击验证图片 :param locations: 点击位置 :return: None """ for location in locations: print(location) ActionChains(self.browser).move_to_element_with_offset(self.get_touclick_element(), location[0], location[1]).click().perform() time.sleep(1)
defget_gap(self, image1, image2): """ 获取缺口偏移量 :param image1: 不带缺口图片 :param image2: 带缺口图片 :return: """ left = 60 for i in range(left, image1.size[0]): for j in range(image1.size[1]): ifnot self.is_pixel_equal(image1, image2, i, j): left = i return left return left
模拟拖动的这个过程说复杂并不复杂,只是其中的坑比较多。现在我们已经获取到了缺口的位置,接下来只需要调用拖动的相关函数将滑块拖动到对应位置不就好了吗?然而事实很残酷,如果匀速拖动,极验必然会识别出来这是程序的操作,因为人是无法做到完全匀速拖动的,极验利用机器学习模型筛选出此类数据,归类为机器操作,验证码识别失败。 随后我又尝试了分段模拟,将拖动过程划分几段,每段设置一个平均速度,同时速度围绕该平均速度小幅度随机抖动,同样无法完成验证。 最后尝试了完全模拟加速减速的过程通过了验证,在前段滑块需要做匀加速运动,后面需要做匀减速运动,在这里利用物理学的加速度公式即可完成。 设滑块滑动的加速度用 a 来表示,当前速度用 v 表示,初速度用 v0 表示,位移用 x 表示,所需时间用 t 表示,则它们之间满足如下关系:
while current < distance: if current < mid: # 加速度为正2 a = 2 else: # 加速度为负3 a = -3 # 初速度v0 v0 = v # 当前速度v = v0 + at v = v0 + a * t # 移动距离x = v0t + 1/2 * a * t^2 move = v0 * t + 1 / 2 * a * t * t # 当前位移 current += move # 加入轨迹 track.append(round(move)) return track
文档中有介绍,它以 os.getcwd() 的形式将路径返回。我们去源码中一探究竟(Pycharm 编辑器快捷键 ctrl+鼠标左键点击即可跟进指定对象) 原来它是对 os 模块中一些对象进行了封装,看 cwd 的注释: Return a new path pointing to the current working directory 意为:返回指向当前工作目录的新路径。 看起来也没什么特别的,但是为什么官方特意将它推出呢?
Pure paths are useful in some special cases; for example: If you want to manipulate Windows paths on a Unix machine (or vice versa). You cannot instantiate a WindowsPath when running on Unix, but you can instantiate PureWindowsPath. You want to make sure that your code only manipulates paths without actually accessing the OS. In this case, instantiating one of the pure classes may be useful since those simply don’t have any OS-accessing operations. 翻译:纯路径在某些特殊情况下很有用; 例如: 如果要在Unix计算机上操作Windows路径(反之亦然)。WindowsPath在Unix上运行时无法实例化,但可以实例化PureWindowsPath。 您希望确保您的代码仅操作路径而不实际访问操作系统。在这种情况下,实例化其中一个纯类可能很有用,因为那些只是没有任何操作系统访问操作。
还附上了一张图: 一下子也不是很理解,这是什么意思。不要紧,继续往下看。
对应关系
通过以上的例子我们可以感受到,它不仅封装了 os.path 相关常用方法,还集成了 os 的其他模块,比如创建文件夹 Path.mkdir。 如果你担心记不住,没关系的,文档一直都在。并且文档给我们列出了对应关系表
This module offers classes representing filesystem paths with semantics appropriate for different operating systems. Path classes are divided between pure paths, which provide purely computational operations without I/O, and concrete paths, which inherit from pure paths but also provide I/O operations. 释义:pathlib 提供表示文件系统路径的类,其语义适用于不同的操作系统。路径类在纯路径之间划分,纯路径提供纯粹的计算操作而没有I / O,以及具体路径,它继承纯路径但也提供I / O操作。
回顾刚才这张图,重新理解 pathlib 如果你以前从未使用过这个模块,或者只是不确定哪个类适合您的任务,那么Path很可能就是您所需要的。它为代码运行的平台实例化一个具体路径。 总结:pathlib 不单纯是对 os 中一些模块或方法进行封装,而是为了兼容不同的操作系统,它为每类操作系统定义了接口。你希望在UNIX机器上操作Windows的路径,然而直接操作是做不到的,所以为你创建了一套接口 PurePath,你可以通过接口来实现你的目的(反之亦然)
最后,a = 5, b = 3。我们可以用 C 语言和 PYTHON 语言进行验证,对应的 PYTHON 代码如下:
1 2 3 4 5 6
# python a, b = 3, 5 a = a ^ b b = a ^ b a = a ^ b print(a, b)
代码运行结果为 5 3,说明变量交换成功。对应的 C 代码如下:
1 2 3 4 5 6 7 8 9 10
#include<stdio.h> voidmain() { int a = 3, b = 5; printf("交换前:a=%d , b=%dn",a,b); a = a^b; b = a^b; a = a^b; printf("交换后:a=%d , b=%dn",a, b); }
代码运行结果如下:
1 2
交换前:a=3 , b=5 交换后:a=5 , b=3
这说明变量交换成功。 求 x 与 2 的 n 次方乘积 设一个数为 x,求 x 与 2 的 n 次方乘积。这用数学来计算都是非常简单的: 在位运算中,要实现这个需求只需要用到左移运算,即 x << n。 取 x 的第 k 位 即取数字 x 对应的二进制的第 k 位上的二进制值。假设数字为 5,其对应的二进制为 0000 0101,取第 k 位二进制值的位运算为 x >> k & 1。我们可以用 PYTHON 代码进行验证:
1 2 3 4
# python x = 5 # 00000101 for i in range(8): print(x >> i & 1)
代码运行结果如下:
1 2 3 4 5 6 7 8
1 0 1 0 0 0 0 0
这说明位运算的算法是正确的,可以满足我们的需求。 判断赋值
1 2 3 4
if a == x: x = b else: x = a
等效于 x = a ^ b ^ x。我们可以通过 PYTHON 代码来验证:
1 2 3 4 5 6 7
# python a, b, x = 6, 9, 6 if a == x: x = b else: x = a print(a, b, x)
代码运行结果为 699,与之等效的代码如下:
1 2 3 4
# python a, b, x = 6, 9, 6 x = a ^ b ^ x print(a, b, x)
response1 = requests.get(url, headers=headers) if response1.status_code == 200: cookies = response1.cookies print(cookies)
输出:
1
<RequestsCookieJar[<Cookie PHPSESSID=52asgghnqsntitqd7c8dqesgh6 for www.ctic.org/>, <Cookie _csrf=2571c72a4ca9699915ea4037b967827150715252de98ea2173b162fa376bad33s%3A32%3A%22TAhjwgNo5ElZzV55k3DMeFoc5TWrEmXj%22%3B for www.ctic.org/>]>
def new(): session = requests.Session() response = session.get(url=url, headers=headers) html = etree.HTML(response.text) return session, html
session, html = new() years = html.xpath('//*[@id="crmsearchform-year"]/option/text()') regions = html.xpath('//*[@id="crmsearchform-region"]/option/text()') _csrf = html.xpath('/html/head/meta[3]/@content')[0] region_state = {} state_county = {} for region in regions: data = {'region': region, '_csrf': _csrf} response = session.post(url_state, data=data) html = etree.HTML(response.json()) region_state[region] = {x: y for x, y in zip(html.xpath('//option/@value'), html.xpath('//option/text()'))} forstatein region_state[region]: data = {'state': state, '_csrf': _csrf} response = session.post(url_county, data=data) html = etree.HTML(response.json()) state_county[state] = html.xpath('//option/@value')
remain = [[str(year), str(region), str(state), str(county)] for year in years for region in regions forstatein region_state[region] for county in state_county[state]] remain = pd.DataFrame(remain, columns=['CRMSearchForm[year]', 'CRMSearchForm[region]', 'CRMSearchForm[state]', 'CRMSearchForm[county]']) remain.to_csv('remain.csv', index=False) # 由于州名有缩写和全称,也本地保存一份 import json with open('region_state.json', 'w') as json_file: json.dump(region_state, json_file, indent=4)
import pyodbc withopen("region_state.json") as json_file: region_state = json.load(json_file) data = pd.read_csv('remain.csv') # 读取已经爬取的 cnxn = pyodbc.connect('DRIVER={Microsoft Access Driver (*.mdb, *.accdb)};' 'DBQ=./ctic_crm.accdb') crsr = cnxn.cursor() crsr.execute('select Year_, Region, State, County from ctic_crm') done = crsr.fetchall() done = [list(x) for x in done] done = pd.DataFrame([list(x) for x in done], columns=['CRMSearchForm[year]', 'CRMSearchForm[region]', 'CRMSearchForm[state]', 'CRMSearchForm[county]']) done['CRMSearchForm[year]'] = done['CRMSearchForm[year]'].astype('int64') state2st = {y: x for z in region_state.values() for x, y in z.items()} done['CRMSearchForm[state]'] = [state2st[x] for x in done['CRMSearchForm[state]']] # 排除已经爬取的 remain = data.append(done) remain = remain.drop_duplicates(keep=False) total = len(remain) print(f'{total} left.n') del data
//dream zepto.init = function(selector, context) { var dom // If nothing given, return an empty Zepto collection if (!selector) return zepto.Z() // Optimize for string selectors elseif (typeof selector == 'string') { selector = selector.trim() // If it's a html fragment, create nodes from it // Note: In both Chrome 21 and Firefox 15, DOM error 12 // is thrown if the fragment doesn't begin with < if (selector[0] == '<' && fragmentRE.test(selector)) dom = zepto.fragment(selector, RegExp.$1, context), selector = null // If there's a context, create a collection on that context first, and select // nodes from there elseif (context !== undefined) return $(context).find(selector) // If it's a CSS selector, use it to select nodes. else dom = zepto.qsa(document, selector) } // If a function is given, call it when the DOM is ready elseif (isFunction(selector)) return $(document).ready(selector) // If a Zepto collection is given, just return it elseif (zepto.isZ(selector)) return selector else { // normalize array if an array of nodes is given if (isArray(selector)) dom = compact(selector) // Wrap DOM nodes. elseif (isObject(selector)) dom = [selector], selector = null // If it's a html fragment, create nodes from it elseif (fragmentRE.test(selector)) dom = zepto.fragment(selector.trim(), RegExp.$1, context), selector = null // If there's a context, create a collection on that context first, and select // nodes from there elseif (context !== undefined) return $(context).find(selector) // And last but no least, if it's a CSS selector, use it to select nodes. else dom = zepto.qsa(document, selector) } // create a new Zepto collection from the nodes found return zepto.Z(dom, selector) }
// Make a request for a user with a given ID axios.get('/user?ID=12345') .then(function(response) { console.log(response); }) .catch(function(error) { console.log(error); });
var formData = new FormData(); formData.append('file', $('#file')[0].files[0]); $.ajax({ url : 'upload.php', type : 'POST', data : formData, processData: false, // tell jQuery not to process the data contentType: false, // tell jQuery not to set contentType success : function(data) { console.log(data); alert(data); } });
var request = require('request'); request('http://www.google.com', function (error, response, body) { console.log('error:', error); // Print the error if one occurred console.log('statusCode:', response && response.statusCode); // Print the response status code if a response was received console.log('body:', body); // Print the HTML for the Google homepage. });
我们看现在的广告,有一种潜意识默认的原则,就是注意力只给它们 3 秒钟。 但现在的 VR 广告,是给你无限的时间,让你自己去体验。 AR 火起来,还是被 2015 年 Snapchat 的搞怪 AR 滤镜,以及 2016 年的神奇宝贝 GO 带动,这也改变了市场营销对 AR 的看法,让 AR 开始在广告界生根发芽。 宜家是首批尝试购买 AR 技术并以此宣传的公司之一。 在 IKEA Place app 中 ,人们可以看到新款家具实际摆放在家里的样子,以判断它们是不是有足够空间布局放置、颜色风格是否和周围环境搭调,这可以帮宜家提高客户满意度以及降低产品退回率。 随后苹果发布了 ARkit 技术,Google、Facebook、亚马逊等大公司也在 2017 年和 2018 年期间发布了自己 AR 软件开发套件,以支持日后 AR 技术的发展。 Facebook 去年就为广告商提供了 展示产品的新方式 ,让人们在新闻流中看到品牌广告时,能够通过前置摄像头对比自己戴上太阳镜等配饰、甚至穿各种衣服的样子。现在 Facebook 也一直在通过各个平台包括 Instagram 扩大购物范围和增值产品。 除了家居服饰,美容时尚等行业也开始尝试利用 AR 营销,主要是为了弥补线上和线下的差距。 两周前,人们已经能在 YouTube 上一边看美妆博主的化妆教程,一边在分屏之下跟着博主一起涂口红试色,这个名为 AR Beauty Try-On 的功能 由 Google 推出,M・A・C 是第一个跟上这项 AR 广告的品牌。测试结果发现,人们愿意花费超过 80 秒的时间去体验虚拟唇膏色调。 甚至当你逛淘宝店,在前几周 天猫旗舰店升级的 2.0 版本,能直接让你像逛线下实体店一样逛线上 3D 商店、参观漫游,每家店铺展示内容也因人而异。 而且,你还可以实地进入 AR 广告之中。 在汽车行业,宝马、保时捷、丰田等汽车品牌都成为了 AR 广告的追随者。 丰田上个月给 2020 年卡罗拉 推出了 AR 移动广告 ,人们可以 360 度全方位观看车内视图和功能,以及固定在一个地方的 3D 数字模型,甚至还可以在车内行走。这能让购买者更简单地了解车辆的技术特性,也有助于在购买车辆前对其预先认证。 这种自然而直观的方式,不仅让人们和品牌建立起更真实的关系,与以往广告最大的不同就是,人们还能随时参与、持续互动,并响应内容。
我们可以拿回看广告的主动权
现在,我们自己可以掌控广告。 目前我们 能看到的 AR 广告 ,主要包括被赞助的拍照滤镜镜头、应用软件和游戏内的 AR 广告单元,信息流内的 AR 广告单元等。 之前是广告「邀请」我们看,没有任何协商。但现在我们「侵入」广告,去满足自己的好奇心。广告变成了一个工具,我们通过它与我们喜欢的品牌获得联系。 这种形式现在也让 AR 广告成为当今市场上破坏性最小的广告单元之一。 ▲ 图片来自:unsplash 另外,AR 广告已经不再是单独的一个内容,而是进入我们的真实生活,或者进入其它我们沉浸的内容之中——广告本身就是商品的展示位,不会再有其它如美化特效、夸张视觉等因素插入和干扰。 而且这些 AR 广告最初打开的阀门,就掌握在消费者手上。 因为 AR 广告现在都需要申请对其相机/设备的访问,在非相机优先的应用中,也需要申请特定权限,因此你完全可以选择你需要的内容,并与之开始进一步互动。 ▲ 图片来自: Cyber Infrastructure 可以说,AR 就是有史以来最强大的故事叙述媒体。它的互动带来的「响应式特色」,就是它最大的优势。 Unity 技术的 AR / VR 广告创新 负责人 Tony Parisi 说 : 响应性 AR 广告是一种更加友好,不那么令人生畏的方法,这些广告能够提高客户的选择率,同时通过控制权来提高用户的舒适度。 尽管 AR 广告现在还不足以吸引大多数用户,人们似乎更觉得这只是消费者的一种自我意淫。 但实际上幸运的是,现在它背后有一批最大的科技公司在支持和推动,这就让更多设计师有机会去创造更好的 AR 广告环境,更多品牌有空间去施放更大的营销活动。 Google、苹果、Facebook 这样的大平台仍然主导着 AR 领域及其营销的发展。这些科技公司还和零售商 组成了一个小组 ,为用于增强现实购物的 3D 图像创建一套通用标准。 ▲ Google 推出名为 Swirl 的沉浸式显示,消费者可以 360 度查看、旋转、放大、缩小商品 在这个背景之下,市场研究公司 Markets and Markets 的数据 预计,到明年 AR 将拥有 10 亿用户,到 2022 年将达到 22 亿美元的广告支出。 AR 广告进入我们的生活将会更加快速,而我们掌握的主动权也会越来越多,正如以色列最大的互联网公司 IronSource 首席设计官 Dan Greenberg所认为的 : 我们不断研究如何在广告中为用户提供尽可能多的选择的方法。因为给用户提供更多控制权,才是创建真正个性化移动体验的关键。
AR 会是下一个广告形态
数字广告总体上正朝着更丰富、更身临其境、更多选择的方向发展,消费者正在被置于互动体验的中心。 根据 Gartner 的估计 ,随着 5G 高速移动服务的推出,明年它将推动 AR 购物增长到 1 亿消费者。 ▲ 图片来自:unsplash 因为在高速运行的网络下,开发者不仅能够创造更高质量的 3D 可视化技术,消费者也能获得更多形式的沉浸式体验,品牌也能将其购物平台更多扩展到商店和传统网站之外的移动设备上,而且广告也不会再只限于移动设备的小屏幕。 还可以预见的是,5G 网络之下数据信息密度也会迅速加大,除了文本,还有图像、视频,人们接受的购物信息无疑更广、更深、更繁杂,而 AR 能够降低广告的感知成本,让人们消费数字内容将更简便和直观。 ▲ 图片来自:unsplash 但现在 AR 广告还未普及的主要问题,就在于它的成本和技术。 比起其他广告形式来说,其实它的投入成本并不低。Digiday 指出 单一的广告体验 可能需要花费 5,000 到 30,000 美元甚至更多才能正常开发,投资回报率也很难衡量。 而近阶段虽然 AR 技术发展很快,但 5G 手机还刚推出第一批,5G 网络也并未稳定普及,这也是影响 AR 广告现在扩大规模的关键因素——没有与之匹配的设备。另外,比起其它开发多年的其它形式的广告,AR 广告迭代和优化也还不太灵活,并非广告商们信手就可捏来。 ▲ 图片来自:unsplash AR 热潮刚刚开始真正起飞,我们现在看到的只是关于 AR 能带来什么以及它能做些什么的一瞥。不过苹果 2017 年推出 ARKit 时,首席执行官蒂姆・库克在 财报电话会议上就指出 AR 将成为「主流」: 虽然我们现在还只触及冰山一角,但它将永久改变我们使用技术的方式。 而这个未来正在靠近。Digi-Capital 预计在未来五年内 AR 广告的市场价值将达到 830 亿美元。而且下一代移动设备,还会为我们带来更多新的可能性。 折叠手机的柔性屏幕将能让 AR 广告拥有更多形式;内置投影仪的手机,能让 AR 广告用更大的位置呈现,当广告变成了一种看电影的方式,这对广告商也意味着有更多的空间来宣传。 ▲ 图片来自: satzuma 但无论何种新的形式,接下来,当我们沉迷于自己所选的 AR 广告体验中无法自拔,会不会更加停不下来「买买买」呢? 我开始觉得这是一篇关于 AR 的沉浸式广告了。 原文:https://www.ifanr.com/1230440
info AppiumDoctor Appium Doctor v.1.4.3 info AppiumDoctor ### Diagnostic starting ### info AppiumDoctor ✔ The Node.js binary was found at: /Users/chenwenguan/.nvm/versions/node/v8.9.3/bin/node info AppiumDoctor ✔ Node version is 8.9.3 info AppiumDoctor ✔ Xcode is installed at: /Library/Developer/CommandLineTools info AppiumDoctor ✔ Xcode Command Line Tools are installed. info AppiumDoctor ✔ DevToolsSecurity is enabled. info AppiumDoctor ✔ The Authorization DB is set up properly. WARN AppiumDoctor ✖ Carthage was NOTfound! info AppiumDoctor ✔ HOME issetto: /Users/chenwenguan WARN AppiumDoctor ✖ ANDROID_HOME isNOTset! WARN AppiumDoctor ✖ JAVA_HOME isNOTset! WARN AppiumDoctor ✖ adb could not be found because ANDROID_HOME isNOTset! WARN AppiumDoctor ✖ android could not be found because ANDROID_HOME isNOTset! WARN AppiumDoctor ✖ emulator could not be found because ANDROID_HOME isNOTset! WARN AppiumDoctor ✖ Bindirectoryfor $JAVA_HOME isnotset info AppiumDoctor ### Diagnostic completed, 7 fixes needed. ### info AppiumDoctor info AppiumDoctor ### Manual Fixes Needed ### info AppiumDoctor The configuration cannot be automatically fixed, please do the followingfirst: WARN AppiumDoctor - Please install Carthage. Visit https://github.com/Carthage/Carthage#installing-carthage for more information. WARN AppiumDoctor - Manually configure ANDROID_HOME. WARN AppiumDoctor - Manually configure JAVA_HOME. WARN AppiumDoctor - Manually configure ANDROID_HOME and run appium-doctor again. WARN AppiumDoctor - Add'$JAVA_HOME/bin'to your PATH environment info AppiumDoctor ### info AppiumDoctor info AppiumDoctor Bye! Run appium-doctor again whenallmanual fixes have been applied! info AppiumDoctor
1.8.0_60, x86_64:"Java SE 8"/Library/Java/JavaVirtualMachines/jdk1.8.0_60.jdk/Contents/Home /Library/Java/JavaVirtualMachines/jdk1.8.0_60.jdk/Contents/Home
org.openqa.selenium.WebDriverException: An unknown server-side error occurred while processing the command. (WARNING: The server did not provide any stacktrace information) Command duration or timeout: 1.41 seconds Build info: version: '2.44.0', revision: '76d78cf', time: '2014-10-23 20:02:37' System info: host: 'wenguanchen-MacBook-Pro.local', ip: '30.85.214.6', os.name: 'Mac OS X', os.arch: 'x86_64', os.version: '10.13.2', java.version: '1.8.0_112-release' Driver info: io.appium.java_client.android.AndroidDriver Capabilities [{appPackage=com.tencent.mm, noReset=true, dontStopAppOnReset=true, deviceName=emulator-5554, fullReset=false, platform=LINUX, deviceUDID=emulator-5554, desired={app=, appPackage=com.tencent.mm, recreateChromeDriverSessions=true, noReset=true, dontStopAppOnReset=true, deviceName=MuMu, fullReset=false, appActivity=.ui.LauncherUI, platformVersion=4.4.4, automationName=Appium, unicodeKeyboard=true, fastReset=false, chromeOptions={args=[], extensions=[], androidProcess=com.tencent.mm:tools}, platformName=Android, resetKeyboard=true}, platformVersion=4.4.4, webStorageEnabled=false, automationName=Appium, takesScreenshot=true, javascriptEnabled=true, unicodeKeyboard=true, platformName=Android, resetKeyboard=true, app=, networkConnectionEnabled=true, recreateChromeDriverSessions=true, warnings={}, databaseEnabled=false, appActivity=.ui.LauncherUI, locationContextEnabled=false, fastReset=false, chromeOptions={args=[], extensions=[], androidProcess=com.tencent.mm:tools}}] Session ID: 592813d6-7c6e-4a3c-8183-e5f93d1d3bf0 at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method) at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62) at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45) at java.lang.reflect.Constructor.newInstance(Constructor.java:423) at org.openqa.selenium.remote.ErrorHandler.createThrowable(ErrorHandler.java:204) at org.openqa.selenium.remote.ErrorHandler.throwIfResponseFailed(ErrorHandler.java:156) at org.openqa.selenium.remote.RemoteWebDriver.execute(RemoteWebDriver.java:599) at io.appium.java_client.DefaultGenericMobileDriver.execute(DefaultGenericMobileDriver.java:27) at io.appium.java_client.AppiumDriver.execute(AppiumDriver.java:1) at io.appium.java_client.android.AndroidDriver.execute(AndroidDriver.java:1) at org.openqa.selenium.remote.RemoteWebDriver.findElement(RemoteWebDriver.java:352) at org.openqa.selenium.remote.RemoteWebDriver.findElementByXPath(RemoteWebDriver.java:449) at io.appium.java_client.DefaultGenericMobileDriver.findElementByXPath(DefaultGenericMobileDriver.java:99) at io.appium.java_client.AppiumDriver.findElementByXPath(AppiumDriver.java:1) at io.appium.java_client.android.AndroidDriver.findElementByXPath(AndroidDriver.java:1) at org.openqa.selenium.By$ByXPath.findElement(By.java:357) at org.openqa.selenium.remote.RemoteWebDriver.findElement(RemoteWebDriver.java:344) at io.appium.java_client.DefaultGenericMobileDriver.findElement(DefaultGenericMobileDriver.java:37) at io.appium.java_client.AppiumDriver.findElement(AppiumDriver.java:1) at io.appium.java_client.android.AndroidDriver.findElement(AndroidDriver.java:1) at com.example.AppiumAutoScan.getArticleDetail(AppiumAutoScan.java:335) at com.example.AppiumAutoScan.launchBrowser(AppiumAutoScan.java:96) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:498) at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:45) at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:15) at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:42) at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:20) at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:263) at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:68) at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:47) at org.junit.runners.ParentRunner$3.run(ParentRunner.java:231) at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:60) at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:229) at org.junit.runners.ParentRunner.access$000(ParentRunner.java:50) at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:222) at org.junit.runners.ParentRunner.run(ParentRunner.java:300) at org.junit.runner.JUnitCore.run(JUnitCore.java:157) at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:117) at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:42) at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:262) at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:84) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:498) at com.intellij.rt.execution.application.AppMain.main(AppMain.java:147)
org.openqa.selenium.StaleElementReferenceException: stale element reference: element is not attached to the page document (Session info: webview=33.0.0.0) (Driver info: chromedriver=2.20.353124 (035346203162d32c80f1dce587c8154a1efa0c3b),platform=Mac OS X 10.13.2 x86_64) (WARNING: The server did not provide any stacktrace information) Command duration or timeout: 2.41 seconds For documentation on this error, please visit: http://seleniumhq.org/exceptions/stale_element_reference.html Build info: version: '2.44.0', revision: '76d78cf', time: '2014-10-23 20:02:37' System info: host: 'wenguanchen-MacBook-Pro.local', ip: '30.85.214.81', os.name: 'Mac OS X', os.arch: 'x86_64', os.version: '10.13.2', java.version: '1.8.0_112-release' Driver info: io.appium.java_client.android.AndroidDriver Capabilities [{appPackage=com.tencent.mm, noReset=true, dontStopAppOnReset=true, deviceName=emulator-5554, fullReset=false, platform=LINUX, deviceUDID=emulator-5554, desired={app=, appPackage=com.tencent.mm, recreateChromeDriverSessions=true, noReset=true, dontStopAppOnReset=true, deviceName=MuMu, fullReset=false, appActivity=.ui.LauncherUI, platformVersion=4.4.4, automationName=Appium, unicodeKeyboard=true, fastReset=false, chromeOptions={args=[], extensions=[], androidProcess=com.tencent.mm:tools}, platformName=Android, resetKeyboard=true}, platformVersion=4.4.4, webStorageEnabled=false, automationName=Appium, takesScreenshot=true, javascriptEnabled=true, unicodeKeyboard=true, platformName=Android, resetKeyboard=true, app=, networkConnectionEnabled=true, recreateChromeDriverSessions=true, warnings={}, databaseEnabled=false, appActivity=.ui.LauncherUI, locationContextEnabled=false, fastReset=false, chromeOptions={args=[], extensions=[], androidProcess=com.tencent.mm:tools}}] Session ID: b5e933e1-0ddf-421d-9144-e423a7bb25b1 at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method) at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62) at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45) at java.lang.reflect.Constructor.newInstance(Constructor.java:423) at org.openqa.selenium.remote.ErrorHandler.createThrowable(ErrorHandler.java:204) at org.openqa.selenium.remote.ErrorHandler.throwIfResponseFailed(ErrorHandler.java:156) at org.openqa.selenium.remote.RemoteWebDriver.execute(RemoteWebDriver.java:599) at io.appium.java_client.DefaultGenericMobileDriver.execute(DefaultGenericMobileDriver.java:27) at io.appium.java_client.AppiumDriver.execute(AppiumDriver.java:1) at io.appium.java_client.android.AndroidDriver.execute(AndroidDriver.java:1) at org.openqa.selenium.remote.RemoteWebElement.execute(RemoteWebElement.java:268) at io.appium.java_client.DefaultGenericMobileElement.execute(DefaultGenericMobileElement.java:27) at io.appium.java_client.MobileElement.execute(MobileElement.java:1) at io.appium.java_client.android.AndroidElement.execute(AndroidElement.java:1) at org.openqa.selenium.remote.RemoteWebElement.getText(RemoteWebElement.java:152) at com.example.AppiumAutoScan.getArticleDetail(AppiumAutoScan.java:294) at com.example.AppiumAutoScan.launchBrowser(AppiumAutoScan.java:110) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:498) at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:45) at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:15) at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:42) at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:20) at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:263) at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:68) at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:47) at org.junit.runners.ParentRunner$3.run(ParentRunner.java:231) at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:60) at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:229) at org.junit.runners.ParentRunner.access$000(ParentRunner.java:50) at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:222) at org.junit.runners.ParentRunner.run(ParentRunner.java:300) at org.junit.runner.JUnitCore.run(JUnitCore.java:157) at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:117) at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:42) at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:262) at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:84) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:498) at com.intellij.rt.execution.application.AppMain.main(AppMain.java:147)
org.openqa.selenium.remote.SessionNotFoundException: no such session (Driver info: chromedriver=2.21.371459 (36d3d07f660ff2bc1bf28a75d1cdabed0983e7c4),platform=Mac OS X 10.13.2 x86_64) (WARNING: The server did not provide any stacktrace information) Command duration or timeout: 14 milliseconds Build info: version: '2.44.0', revision: '76d78cf', time: '2014-10-23 20:02:37' System info: host: 'wenguanchen-MacBook-Pro.local', ip: '192.168.1.102', os.name: 'Mac OS X', os.arch: 'x86_64', os.version: '10.13.2', java.version: '1.8.0_112-release' Driver info: io.appium.java_client.android.AndroidDriver Capabilities [{appPackage=com.tencent.mm, noReset=true, dontStopAppOnReset=true, deviceName=55CDU16C07009329, fullReset=false, platform=LINUX, deviceUDID=55CDU16C07009329, desired={app=, appPackage=com.tencent.mm, recreateChromeDriverSessions=True, noReset=true, dontStopAppOnReset=true, deviceName=FRD-AL00, fullReset=false, appActivity=.ui.LauncherUI, platformVersion=6.0, automationName=Appium, unicodeKeyboard=true, fastReset=false, chromeOptions={args=[], extensions=[], androidProcess=com.tencent.mm:tools}, platformName=Android, resetKeyboard=true}, platformVersion=6.0, webStorageEnabled=false, automationName=Appium, takesScreenshot=true, javascriptEnabled=true, unicodeKeyboard=true, platformName=Android, resetKeyboard=true, app=, networkConnectionEnabled=true, recreateChromeDriverSessions=True, warnings={}, databaseEnabled=false, appActivity=.ui.LauncherUI, locationContextEnabled=false, fastReset=false, chromeOptions={args=[], extensions=[], androidProcess=com.tencent.mm:tools}}] Session ID: e2e50190-398b-4fa2-bc66-db1097201e3f at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method) at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62) at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45) at java.lang.reflect.Constructor.newInstance(Constructor.java:423) at org.openqa.selenium.remote.ErrorHandler.createThrowable(ErrorHandler.java:204) at org.openqa.selenium.remote.ErrorHandler.throwIfResponseFailed(ErrorHandler.java:162) at org.openqa.selenium.remote.RemoteWebDriver.execute(RemoteWebDriver.java:599) at io.appium.java_client.DefaultGenericMobileDriver.execute(DefaultGenericMobileDriver.java:27) at io.appium.java_client.AppiumDriver.execute(AppiumDriver.java:272) at org.openqa.selenium.remote.RemoteWebDriver.getPageSource(RemoteWebDriver.java:459) at com.example.AppiumAutoScan.getArticleDetail(AppiumAutoScan.java:238) at com.example.AppiumAutoScan.launchBrowser(AppiumAutoScan.java:78) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:498) at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:45) at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:15) at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:42) at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:20) at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:263) at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:68) at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:47) at org.junit.runners.ParentRunner$3.run(ParentRunner.java:231) at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:60) at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:229) at org.junit.runners.ParentRunner.access$000(ParentRunner.java:50) at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:222) at org.junit.runners.ParentRunner.run(ParentRunner.java:300) at org.junit.runner.JUnitCore.run(JUnitCore.java:157) at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:117) at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:42) at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:262) at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:84) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:498) at com.intellij.rt.execution.application.AppMain.main(AppMain.java:147)
cd /Applications/Appium.app/Contents/Resources/node_modules/appium/node_modules/appium-android-driver/node_modules/appium-chromedriver/chromedriver/mac/ open .
the default rule for AnyProxy. Anyproxy rules initialize finished, have fun! The WebSocket will not work properly in the https intercept mode :( fs.js:885 return binding.mkdir(pathModule._makeLong(path), ^ Error:EACCES: permission denied, mkdir '/Users/chenwenguan/.anyproxy/cache_r929590' at Object.fs.mkdirSync (fs.js:885:18) at Object.module.exports.generateCacheDir (/Users/chenwenguan/.nvm/versions/node/v8.9.3/lib/node_modules/anyproxy/lib/util.js:54:8) at new Recorder (/Users/chenwenguan/.nvm/versions/node/v8.9.3/lib/node_modules/anyproxy/lib/recorder.js:16:31) at /Users/chenwenguan/.nvm/versions/node/v8.9.3/lib/node_modules/anyproxy/proxy.js:116:43 at ChildProcess.exithandler (child_process.js:282:5) at emitTwo (events.js:126:13) at ChildProcess.emit (events.js:214:7) at maybeClose (internal/child_process.js:925:16) at Socket.stream.socket.on (internal/child_process.js:346:11) at emitOne (events.js:116:13)
对于 onDragEnd 方法来说,其实就是检测最后的结果了,刚才我们用 state 变量里面的 over 属性来代表是否拖动到目标位置上,这里我们也定义了另外的 dragged 属性来代表是否已经拖动完成,dragging 属性来代表是否正在拖动,所以整个方法的逻辑上是检测 over 属性,然后对 dragging、dragged 属性做赋值,然后做一些相应的提示,实现如下:
def drop_nonattrs(d, type): if not isinstance(d, dict): return d attrs_attrs = getattr(type, '__attrs_attrs__', None) if attrs_attrs is None: raise ValueError(f'type {type} isnotanattrsclass') attrs: Set[str] = {attr.name for attr in attrs_attrs} return {key: val for key, valin d.items()if key in attrs}
from typing import Set from attr import attrs, attrib import cattr
@attrs classPoint(object): x = attrib(type=int, default=0) y = attrib(type=int, default=0)
defdrop_nonattrs(d, type): ifnotisinstance(d, dict): returnd attrs_attrs = getattr(type, '__attrs_attrs__', None) ifattrs_attrsisNone: raiseValueError(f'type {type} isnot an attrs class') attrs: Set[str] = {attr.name for attr in attrs_attrs} return {key: val for key, val in d.items() if key in attrs}
import csv with open("employee.csv", mode="r") as csv_file: csv_reader = csv.DictReader(csv_file) line_count = 0 for row in csv_reader: if line_count == 0: print(f'Column names are {", ".join(row)}') line_count += 1 print(f'\\t{row["name"]} salary: {row["salary"]}' f'and was born in {row["birthday month"]}.') line_count += 1 print(f'Processed {line_count} lines.')
将代码分解为函数有助于使复杂的代码变的易于阅读和调试。 这里的代码在 with 语句中执行多项操作。为了提高可读性,您可以将带有 process salary 的代码从 CSV 文件中提取到另一个函数中,以降低出错的可能性。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
import csv with open("employee.csv", mode="r") as csv_file: csv_reader = csv.DictReader(csv_file) line_count = 0 process_salary(csv_reader)
defprocess_salary(csv_reader): """Process salary of user from csv file.""" for row in csv_reader: if line_count == 0: print(f'Column names are {", ".join(row)}') line_count += 1 print(f'\\t{row["name"]} salary: {row["salary"]}' f'and was born in {row["birthday month"]}.') line_count += 1 print(f'Processed {line_count} lines.')
代码是不是变得容易理解了不少呢。 在这里,创建了一个帮助函数,而不是在 with 语句中编写所有内容。这使读者清楚地了解了函数的实际作用。如果想处理一个特定的异常或者想从 CSV 文件中读取更多的数据,可以进一步分解这个函数,以遵循单一职责原则,一个函数一做一件事。这个很重要
defcall_weather_api(url, location): """Get the weather of specific location. Calling weather api to check for weather by using weather api and location. Make sure you provide city name only, country and county names won't be accepted and will throw exception if not found the city name. :param url:URL of the api to get weather. :type url: str :param location:Location of the city to get the weather. :type location: str :return: Give the weather information of given location. :rtype: str"""
defcall_weather_api(url: str, location: str) -> str: """Get the weather of specific location. Calling weather api to check for weather by using weather api and location. Make sure you provide city name only, country and county names won't be accepted and will throw exception if not found the city name. """
"""This module contains all of the network related requests. This module will checkforall the exceptionswhile making the network calls andraiseexceptionsforanyunknown exception. Make sure that when you use this module, you handle these exceptionsinclient code as: NetworkError exceptionfor network calls. NetworkNotFound exceptionif network not found. """ import urllib3 import json
在为模块编写文档字符串时,应考虑执行以下操作:
对当前模块写一个简要的说明
如果想指定某些对读者有用的模块,如上面的代码,还可以添加异常信息,但是注意不要太详细。
1 2
NetworkError exception for network calls. NetworkNotFound exception if network not found.
classStudent: """Student class information. This class handle actions performed by a student. This class provides information about student full name, age, roll-number and other information. Usage: import student student = student.Student() student.get_name() >>> 678998 """ def__init__(self): pass
这个类 docstring 是多行的; 我们写了很多关于 Student 类的用法以及如何使用它。
函数的 docstring
函数文档字符串可以写在函数之后,也可以写在函数的顶部。
1 2 3 4 5 6 7 8 9 10 11 12
def is_prime_number(number): """Checkfor prime number.
Check the given numberis prime number ornotby checking against all the numbers less the square root of given number.
:param number:Given numbertocheckfor prime :typenumber: int :return: Trueifnumberis prime otherwise False. :rtype: boolean """
如果我们使用类型注解对其进一步优化。
1 2 3 4 5 6 7
defis_prime_number(number: int)->bool: """Check for prime number. Check the given number is prime number or not by checking against all the numbers less the square root of given number. """