0%

selenium 使用实例

selenium 使用实例
环境配置:http://vksec.com/2018/01/31/28_selenium环境配置Firefox和Chrome/

QQ群:397745473

selenium 使用实例1

python+selenium实现QQ群自动签到

python+selenium实现的QQ群自动签到!
QQ群里的群签到功能经常会断签,如果能用脚本去自动签到,就再也不怕忘签了~下面郑晓会告诉你如何使用python来实现QQ群的定时自动签到(邪恶脸)。
以下代码基于linux(centos),Python2.7,且须要有pyvirtualdisplay和selenium库支持。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
#!-*- coding:utf-8 -*-
from pyvirtualdisplay import Display
from selenium import webdriver
import requests
#要签到的QQ群号列表
groupid = [123456789,987654321]
headers = {"Content-Type":"application/x-www-form-urlencoded","Host":"qiandao.qun.qq.com","Origin":"http://qiandao.qun.qq.com","Referer": "http://qiandao.qun.qq.com","User-Agent":"Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/51.0.2704.84 Safari/537.36"}
#创建一个启动session的请求对象
s = requests.Session()
def login():
try:
#启动一个虚拟桌面
display = Display(visible=0, size=(1100,700))
display.start()
driver = webdriver.Firefox()
driver.set_window_position(20, 40)
driver.set_window_size(1100,700)
#打开QQ登录界面 准备登录
driver.get('http://qzone.qq.com')
driver.switch_to_frame('login_frame')
driver.find_element_by_id('switcher_plogin').click()
driver.find_element_by_id('u').clear()
#填写QQ帐号
driver.find_element_by_id('u').send_keys('qq号')
driver.find_element_by_id('p').clear()
#填写QQ密码
driver.find_element_by_id('p').send_keys('****zh30.com****')
#模拟点击登录按钮 执行登录 获取cookie
driver.find_element_by_id('login_button').click()
cookies = driver.get_cookies()
#退出浏览器
driver.quit()
display.stop()
return cookies
except:
pass

cookies = login()
for cookie in cookies:
if cookie['name'] == 'skey':
skey = cookie['value']
s.cookies.set(cookie['name'], cookie['value'])

#计算bkn并存入cookie
e = 5381
for i in range(len(skey)):
e = e + (e<<5)+ord(skey[i])
bkn = str(2147483647 & e)
s.cookies.set("Gtk", bkn)
#签到方法
def sign(groupid):
for gid in groupid:
response = s.post("http://qiandao.qun.qq.com/cgi-bin/sign", data={"gc":gid, "is_sign":0, "bkn":bkn}, headers=headers)
responseJson = response.json()
if responseJson.has_key('em') and responseJson['em'] == 'no&nbsp;login':
break
#开始签到
sign(groupid)

好了,这样就完成了一个自动签到的脚本,运行它便会自动启动浏览器、自动填上帐号密码登录、循环签到。但它只执行一次,我们要把它加入到计划任务crontab中。

1
2
3
0 0 * * * python /root/QQsign.py
#为了测试可以加个输出日志,如
0 0 * * * python /root/QQsign.py >/root/crontab-run.log 2>&1

以上任务郑晓是在root帐户中创建,定时于每天0点执行/root/目录下的QQsign.py脚本,输出日志到crontab-run.log文件中。
完成!看看以下的效果截图,是不是很贱啊?

selenium 使用实例2

python+selenium自动登录qq空间并下载相册

基于selenium的自动登录qq空间并遍历所有相册及相片的功能。只能访问自己或好友(有访问权限)的相册,好友有密码的相册不可能。。。这里只是介绍流程,所以只是实现了遍历,并未实现图片文件的下载保存。读取相册信息是请求的手机版qq空间的相册相关接口,其中写死了只遍历前50个相册,可以自己改。

脚本并未处理任何可能出现的错误,请自己完善。

在环境:64位win7+python2.7+selenium3.5.0+chromedriver2.31 下测试通过。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
#!coding:utf-8
from selenium import webdriver
import requests,time,json

login_uin = '123456789' #登录qq
pwd = 'zx1233211234567' #登录密码
album_uin = '123456789' #要读取相册的qq

s = requests.Session()

#实例化出浏览器开始登录
driver = webdriver.Chrome()
driver.set_window_size(1000,600)
driver.get('https://mobile.qzone.qq.com')
driver.find_element_by_id('u').clear()
driver.find_element_by_id('u').send_keys(login_uin)
driver.find_element_by_id('p').clear()
driver.find_element_by_id('p').send_keys(pwd)
driver.find_element_by_id('go').click()
#等待浏览器中js计算出qzonetoken
while True:
qzonetoken = driver.execute_script("return window.shine0callback")
if qzonetoken:
break
time.sleep(0.1)
#读取cookie后关闭浏览器
cookies = driver.get_cookies()
driver.quit()

cookies_ = {}
for cookie in cookies:
if cookie['name'] == 'p_skey':
skey = cookie['value']
#s.cookies.set(cookie['name'], cookie['value'])
cookies_[cookie['name']] = cookie['value']

#计算gtk
e = 5381
for i in range(len(skey)):
e = e + (e<<5)+ord(skey[i])
g_tk = str(2147483647 & e)

###################### www.zh30.com ######################

#请求中添加cookie,开始读取相册列表
requests.utils.add_dict_to_cookiejar(s.cookies, cookies_)
url="https://mobile.qzone.qq.com/list?qzonetoken="+qzonetoken+"&g_tk="+g_tk+"&format=json&list_type=album&action=0&res_uin="+album_uin+"&count=50"
r = s.get(url);
data = json.loads(r.text.encode('utf-8'))

for album in data['data']['vFeeds']:
print '相册名:'+album['pic']['albumname'].encode('utf-8')
print '相册id:'+album['pic']['albumid'].encode('utf-8')
print '图片数量:' + str(album['pic']['albumnum'])
print '开始下载相册图片:'
#读取当前相册中的图片列表
url = "https://h5.qzone.qq.com/webapp/json/mqzone_photo/getPhotoList2?qzonetoken="+qzonetoken+"&g_tk="+g_tk+"&uin="+album_uin+"&albumid="+album['pic']['albumid'].encode('utf-8')+"&ps=0"
r = s.get(url)
photo_datas = json.loads(r.text.encode('utf-8'))
for T in photo_datas['data']['photos']:
for pic in photo_datas['data']['photos'][T]:
print '图片名:'+pic['picname'].encode('utf-8')+',url:'+pic['1']['url'].encode('utf-8')
print "="*10

以下是运行截屏,右键图片在新标签页打开,可以高清~

selenium 使用实例3

自动抓取摩拜单车车辆位置数据

每天从下车站到公司还有好几米的路要走,这对于现在能免费骑车的懒癌患者怎么能忍?车站人流量大,能找到辆车实属不易,所以就得在下公交车前不停的刷新app查看下车点是否有车,有车就马上预订。

一路上不停的拿着手机刷新太麻烦了,身为码农怎么能忍?我这里要实现的就是把刷新查看目的地是否有车的这个过程实现了自动化。

实现思路是首先找到摩拜单车在地图上标记车辆位置的这个接口,然后想办法使用程序模拟这个请求,从获得的车辆数据中检查是否有符合的车辆,如果有则发送提示消息。

使用的抓包工具是charles,它可以很轻松的获取到移动设备的数据请求,具体使用方法不做介绍,请百度。

开始时是使用charles开启ssl代理,抓取手机上摩拜单车app的请求,摩拜的每个https请求都是unknow(http method是connect),看错误提示应该是证书的问题,但手机上其它的https请求是正常的(比如京东),网上的说法是使用了http隧道通信,代理工具无法抓取。

app无法抓包,转战微信小程序,在摩拜的微信小程序中查看附近车辆时,charles成功抓取到车辆位置的api(nearbyBikeInfo.do)

知道了api后就可以很轻松的模拟出请求,这里使用了python+requests进行post请求。多次测试发现header中有些看似很关键的参数其实不必要的,所以这里已经移除。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#coding=utf8
#www.zh30.com
import requests
headers = {
"Host": "mwx.mobike.com",
"time": "1500887680",
"eption": "bb15c",
"open_src": "list",
"platform": "3",
"citycode": "0532",
"User-Agent": "Mozilla/5.0 (iPhone;www.zh30.com; CPU iPhone OS 10_3_2 like Mac OS X) AppleWebKit/603.2.4 (KHTML, like Gecko) Mobile/14F89 MicroMessenger/6.5.12 NetType/WIFI Language/zh_CN",
"lang": "zh",
"Referer": "https://servicewechat.com/wxxxxxxxx/70/page-frame.html"
}
body = {
"longitude":"120.413333",
"latitude":"36.087741",
"citycode":"0532",
}

r = requests.post("https://mwx.mobike.com/mobike-api/rent/nearbyBikesInfo.do",data=body, headers=headers, verify=False);
print r.text.encode('utf-8')

注意,代码有改动:)

成功返回json数据

格式化后,数据很清晰明白,接口返回查询的坐标周围有几辆车,并包含有每辆车的编号、坐标和与目标坐标的相对距离等信息。

接下来要做的就是从数据里过滤出比较近的车辆(distance的单位是米,值可按自己的需求定),并给出提示消息。提示消息推送可以使用pushbullet这类工具,实现也很方便。更复杂点儿可以距离坐标计算一下每个车辆在目标位置的哪个方向。这里就不实现了~

完。

selenium 使用实例4

使用antiword读取word文档

antiword是linux及其他RISC OS下免费的ms word文档读取器。使用它可以很方便的在Linux中读取word文档并输出为纯文本字符串。

下载地址:http://www.winfield.demon.nl

下载后解压、编译安装:

1
2
3
4
tar -zxvf antiword-0.37.tar.gz
cd antiword-0.37
make
make install

默认安装到当前账户下的bin目录中。

使用:
终端中

1
/home/pi/bin/antiword antiword-test.doc

其他语言中通过各自执行系统命令的方式来执行,比如Python中:

1
2
3
4
import subprocess
word_file = "antiword-test.doc"
content = subprocess.check_output(["/home/pi/antiword", word_file])
print content

比如我有个doc文件是这样的:

执行结果类似这样:

其中的非字符串部分被过滤了。

selenium 使用实例5

python-DHT爬虫中路由表的实现

这是DHT协议中路由表的实现,在DHT网络中,每个节点维护着一张路由表(table),表中储存着已获取的状态良好的节点(node)。路由表又被划分为多个区间桶(bucket),节点应该储存在这些桶中,空的表只有一个桶。当桶满时不能再插入该桶中,除非当前节点(自己)ID也在这个桶中,在这种情况下,原桶需分裂为两个相同大小的桶,旧桶中的节点重新分配到新的子桶中。具体细节可查阅DHT协议。

以下代码逻辑主要来源于网络,我只是改了两个bug。。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
#coding:utf-8
from time import time
from hashlib import sha1
from random import randint
#生成一个20字节长度的node_id
def node_id():
hash = sha1()
s = "".join(chr(randint(0, 255)) for i in xrange(20))
hash.update(s)
return hash.digest()
#返回Node_id的10进制长整型表示 node_id->16->10
def int_ify(nid):
assert len(nid) == 20
return long(nid.encode('hex'), 16)
#node 节点类 每个节点都有id、ip和端口属性 重新定义了节点的等于和不等于操作
class KNode:
def __init__(self, nid, ip, port):
self.nid = nid
self.ip = ip
self.port = port
def __eq__(self, other):
return self.nid == other.nid
def __ne__(self, other):
return self.nid != other.nid
#桶满的异常类
class BucketFull:
pass
#bucket 桶类
class KBucket:
def __init__(self, min, max):
self.min = min
self.max = max
self.nodes = []
self.lastTime = time() #当前桶的最后更新时间
#检查一个node_id是否在桶的范围内
def nid_in_range(self, nid):
return self.min <= int_ify(nid) < self.max
#向桶中添加节点
def append(self, node):
if len(node.nid) != 20: return
if len(self.nodes) < 8:
if node in self.nodes:
self.nodes.remove(node)
self.nodes.append(node)
else:
self.nodes.append(node)
self.lastTime = time()
else:
raise BucketFull
#路由表类
class KTable:
def __init__(self, nid):
self.nid = nid
self.nodeTotal = 0;
self.buckets = [KBucket(0, 2 ** 160)] #路由表中所有的桶的列表 默认只有一个桶
#向路由表添加节点,即向表中某个桶中添加节点,桶满时要进行拆分
def append(self, node):
if node.nid == self.nid: return
index = self.bucket_index(node.nid)
bucket = self.buckets[index]
try:
bucket.append(node)
self.nodeTotal = self.nodeTotal+1
except BucketFull:
if not bucket.nid_in_range(self.nid): return
self.split_bucket(index)
self.append(node)
#返回待添加节点id应该在哪个桶的范围中
def bucket_index(self, nid):
for index, bucket in enumerate(self.buckets):
if bucket.nid_in_range(nid):
return index
return index
#拆分桶
def split_bucket(self, index):
old = self.buckets[index]
point = old.max - (old.max - old.min)/2
new = KBucket(point, old.max)
old.max = point
self.buckets.insert(index + 1, new)
for node in old.nodes:
if new.nid_in_range(node.nid):
new.append(node)
for node in new.nodes:
old.nodes.remove(node)
#返回离目标最近的8个node
def get_neighbor(self, target):
nodes = []
if len(self.buckets) == 0: return nodes
index = self.bucket_index(target)
nodes = self.buckets[index].nodes
min = index - 1
max = index + 1
while len(nodes) < K and (min >= 0 or max < len(self.buckets)):
if min >= 0:
nodes.extend(self.buckets[min].nodes)
if max < len(self.buckets):
nodes.extend(self.buckets[max].nodes)
min -= 1
max += 1
num = int_ify(target)
nodes.sort(lambda a, b, num=num: cmp(num^int_ify(a.nid), num^int_ify(b.nid)))
return nodes[:8]
#打印调试信息
def print_info(self):
print '桶数量:'+str(len(self.buckets))
print '节点量:'+str(self.nodeTotal)
#Demo
#实例化出路由表, 随机生成一千个node,放入表中并打印表的状态
routeTable = KTable(node_id())
for i in xrange(0,1000):
routeTable.append(KNode(node_id(), '127.0.0.1', '80012'))
routeTable.print_info()

打印出的结果显示路由表中的桶和节点数量十分有限,说明有大量的节点已经被抛弃,原因在代码中的第67行,当待加入节点所需要加入的桶已满且自身id不在这个桶中时直接忽略。
由于这种路由表实现复杂、需要不停的ping检查每个节点是否有效且储存的节点数量有限。实际做DHT爬虫时可不实现,爬虫只需要不停的认识新的node,并获取资源infohash,所以直接通过向有效的node发送完find_node后即可删除该node,只需等待node发送的get_peers和announce_peer通知即可。

selenium 使用实例6

SublimeText3按ctrl+b执行python无反应

最后更新时间:2017-09-14
现象:
在Sublime中打开.py文件,按”ctrl+b”执行时无反应。点击工具->编译系统中已经有且识别到Python,但执行”run(ctrl+shift+b)”时无反应,Sublime左下角提示”No Build System with variant run”。

解决:
首先打开一个CMD,在左上角单击,选择”属性”。在属性->选项中查看”当前代码页”一项中的数值。(这一步可选)

然后打开Sublime安装目录,打开Packages,找到里面的”Python.sublime-package”文件,复制出来一份留作备份。把这个文件后缀改为.zip,打开这个压缩包。

在打开压缩包中找到”Python.sublime-build”文件拖出来编辑一下它(编辑工具可用sublime或其它文本编辑器直接打开)。
原文件内容应该类似这样:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
{
"shell_cmd": "python -u "$file"",
"file_regex": "^[ ]*File "(...*?)", line ([0-9]*)",
"selector": "source.python",

"env": {"PYTHONIOENCODING": "utf-8"},

"variants":
[
{
"name": "Syntax Check",
"shell_cmd": "python -m py_compile "${file}"",
}
]
}

改成这样:

1
2
3
4
5
6
7
{
"cmd": ["python", "-u", "$file"],
"file_regex": "^[ ]*File "(...*?)", line ([0-9]*)",
"selector": "source.python",
"encoding": "utf-8",
"env": {"PYTHONIOENCODING": "utf-8"}
}

保存后拖回zip中覆盖,然后把.zip改回.sublime-package,覆盖回Packages目录即修改完成。

打开一个.py,敲一句print ‘hello world’, ctrl+b,成功执行。

PS:不成功的原因可能是第一行cmd命令问题或encoding编码不对(如果上述法不成功,尝试将encoding的值改为第一步查看到的数值)或其它参数有问题比如我这里的variants也有问题,所以我就直接去掉了。。。。

======================2017-09-14 更新======================
另一方法:
菜单中点击–> 工具 –> 编译系统 –> 新建编译系统
把里面的默认配置内容删除,改成下面这样:

1
2
3
4
5
{ 
"cmd": ["python", "$file"],
"file_regex": "py$",
"selector": "source.python"
}

保存,命名为python.sublime-build即可,重命名时的这个python字符串,我觉得改成其它的也可以,它只是会显示在你菜单编译系统列表里而已。
关掉sublime重新打开测试,新建一个.py文件,写一个helloworld, ctrl+b 成功。

selenium 使用实例7

使用Python+Selenium模拟登录QQ空间

使用Python+Selenium模拟登录QQ空间
爬QQ空间之类的页面时大多需要进行登录,研究QQ登录规则的话,得分析大量Javascript的加密解密,这绝对能掉好几斤头发。而现在有了selenium工具,麻麻再也不用担心你的QQ登录!

Selenium是一个WEB自动化测试工具,它运行时会直接实例化出一个浏览器,完全模拟用户的操作,比如点击链接、输入表单,点击按钮提交等。所以我们使用它可以很方便的来登录QQ空间。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
#导入selenium2中的webdriver库
from selenium import webdriver

#实例化出一个Firefox浏览器
driver = webdriver.Firefox()

#设置浏览器窗口的位置和大小
driver.set_window_position(20, 40)
driver.set_window_size(1100,700)

#打开一个页面(QQ空间登录页)
driver.get(‘http://qzone.qq.com’)
#登录表单在页面的框架中,所以要切换到该框架
driver.switch_to_frame(‘login_frame’)
#通过使用选择器选择到表单元素进行模拟输入和点击按钮提交
driver.find_element_by_id(‘switcher_plogin’).click()
driver.find_element_by_id(‘u’).clear()
driver.find_element_by_id(‘u’).send_keys(‘917464311’)
driver.find_element_by_id(‘p’).clear()
driver.find_element_by_id(‘p’).send_keys(‘123456’)
driver.find_element_by_id(‘login_button’).click()

#do something….
#退出窗口
driver.quit()

这样就能方便的登录到QQ空间,下一步就可以利用这个登录状态去抓取页面内容或其它脑洞大开的应用了~~~
安装selenium库,建议直接使用pip工具

1
#pip install selenium

2017-02-28 更新:
有网友反映登录时出现异常,我只能表示无能为力,我只是用过selenium,并不能解决各种疑难杂症,今天又收到回复说是无法使用,我以为是腾讯改什么规则了,所以又测试了一下没发现问题,并录制了gif,如下图(点击查看高清…):

环境:64位Win10 + chromedriver(2.27) + python2.7 + 密码在运行时已经修改了:)

selenium 使用实例8

python抓取安居客小区数据

某功能需要一套城市所有小区的位置信息数据,一开始是使用的百度地图api来进行关键词搜索,勉强能用,但数据量非常少,还是有大量的社区/小区搜不到。

周末在家上网时发现安居客上直接就有每个城市的小区大全,欣喜若狂,于是就立即写了个爬虫试试。
以下贴代码,python2.7,lxml+request库。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
#coding=utf-8
#author : zx
#date : 2015/07/27

import requests
import MySQLdb
import time
import string
import random
from lxml import etree
#ua头信息 get时可以随机使用
headers = [
{ "User-Agent":"Mozilla/5.0 (Linux; U; Android 4.1; en-us; GT-N7100 Build/JRO03C) AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 Mobile Safari/534.30"},
{ "User-Agent":"Mozilla/5.0 (compatible; MSIE 10.0; Windows Phone 8.0; Trident/6.0; IEMobile/10.0; ARM; Touch; NOKIA; Lumia 520)"},
{ "User-Agent":"Mozilla/5.0 (BB10; Touch) AppleWebKit/537.10+ (KHTML, like Gecko) Version/10.0.9.2372 Mobile Safari/537.10+"},
{ "User-Agent":"Mozilla/5.0 (Linux; Android 4.4.2; GT-I9505 Build/JDQ39) AppleWebKit/537.36 (KHTML, like Gecko) Version/1.5 Chrome/28.0.1500.94 Mobile Safari/537.36"}
]

#城市入口页面
#我只抓的青岛本地
#其它城市或全国城市可通过这个页面抓取城市列表http://m.anjuke.com/cityList
url = 'http://m.anjuke.com/qd/xiaoqu/'
req = requests.get(url)
cookie = req.cookies.get_dict()

#链接数据库
conn = MySQLdb.connect('localhost', '*****', '******', '***', charset='utf8')
cursor = conn.cursor()
sql = "insert into xiaoqu (name, lat, lng, address, district) values (%s, %s, %s, %s, %s)"
sql_v = []

page = etree.HTML(req.text)
districtHTML = page.xpath(u"//div[@class='listcont cont_hei']")[0]

#采集目标城市的各行政区域url
#当然如果不想区分行政区可以直接抓“全部” 即上面url中的所有小区及分页
districtUrl = {}
i = 0
for a in districtHTML:
if i==0:
i = 1
continue
districtUrl[a.text] = a.get('href')

#开始采集
total_all = 0
for k,u in districtUrl.items():
p = 1 #分页
while True:
header_i = random.randint(0, len(headers)-1)
url_p = u.rstrip('/') + '-p' + str(p)
r = requests.get(url_p, cookies=cookie, headers=headers[header_i])
page = etree.HTML(r.text) #这里转换大小写要按情况...
communitysUrlDiv = page.xpath(u"//div[@class='items']")[0]
total = len(communitysUrlDiv)
i = 0
for a in communitysUrlDiv:
i+=1
r = requests.get(a.get('href'), cookies=cookie, headers=headers[header_i])
#抓取时发现有少量404页会直接导致程序报错退出- -!
#唉 说明代码写的还不够健壮啊
#加了if判断和try, 错误时可以跳过或做一些简单处理和调试...
if r.status_code == 404:
continue
page = etree.HTML(r.text)
try:
name = page.xpath(u"//h1[@class='f1']")[0].text
except:
print a.get('href')
print r.text
raw_input()
#有少量小区未设置经纬度信息
#只能得到它的地址了
try:
latlng = page.xpath(u"//a[@class='comm_map']")[0]
lat = latlng.get('lat')
lng = latlng.get('lng')
address = latlng.get('address')
except:
lat = ''
lng = ''
address = page.xpath(u"//span[@class='rightArea']/em")[0].text
sql_v.append((name, lat, lng, address, k))
print "\r\r\r",
print u"正在下载 %s 的数据,第 %d 页,共 %d 条,当前:".encode('gbk') %(k.encode('gbk'),p, total) + string.rjust(str(i),3).encode('gbk'),
time.sleep(0.5) #每次抓取停顿
#执行插入数据库
cursor.executemany(sql, sql_v)
sql_v = []
time.sleep(5) #每页完成后停顿

total_all += total
print ''
print u"成功入库 %d 条数据,总数 %d".encode('gbk') % (total, total_all)
if total < 500:
break
else:
p += 1

#及时关闭数据库 做个好孩子 任务完成~
cursor.close()
conn.close()
print u'所有数据采集完成! 共 %d 条数据'.encode('gbk') % (total_all)
raw_input()

注释我觉得已经写的很详细了,在cmd中显示,字符串当然要转一下码。
以下是运行状态和得到的数据截图。

selenium 使用实例9

Python模拟百度登录

本来写这个玩意儿是想用来自动登录百度,然后根据贴吧内的的排名抓取会员头像的,比如生成一个贴吧千人头像图或万人头像图。也算是练练手。
完成后才发现抓那个贴吧排名完全不需要登录…也好,以后用来做自动一键签到(经常忘打卡),抢二楼什么的,也不错~~

如今在博客上发个文章用不了多长时间就被抄走了,感觉自己能做的也只有在此鄙视一下它们。
废话太多,容易招人恨,以下是代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
#-*- coding:gbk -*-
#
# 模拟百度登录 for Python2.7
# 其中显示验证码部分 需要使用PIL库
# 需要验证码时,会创建一个Tkinter窗口,用于显示和输入验证码,回车后窗口关闭。
# author:zx(www.zh30.com)
#
import urllib, urllib2, cookielib, re, time
username = 'yourusernamehere' #用户名
password = 'yourpasswordhere' #密码
cookiefile = '--login-baidu--' #cookie文件
#模拟header信息
headers = {
"Host":"passport.baidu.com",
"Referer":"http://www.baidu.com/cache/user/html/login-1.2.html",
"User-Agent":"Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/43.0.2357.124 Safari/537.36",
"Origin":"http://www.baidu.com",
"""yufang xiao tou. this code by zhengxiao(www.zh30.om)"""
"Accept":"text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8",
"Cache-Control":"max-age=0",
"Connection":"keep-alive"
}
cookie = cookielib.MozillaCookieJar(cookiefile)
#尝试加载cookie文件并验证有效性
try:
cookie.load(ignore_discard=True, ignore_expires=True)
print '读取登录状态的cookie成功'
#do something...

except Exception:
#cookie不存在或无效时 开始进行模拟登录并重新生成cookie文件
opener = urllib2.build_opener(urllib2.HTTPCookieProcessor(cookie))

loginUrl = 'http://www.baidu.com/cache/user/html/login-1.2.html'
getTokenUrl = 'https://passport.baidu.com/v2/api/?getapi&class=login&tpl=mn&tangram=true' """www . zh30 . com """
getCodeStringUrl = 'https://passport.baidu.com/v2/api/?logincheck&callback=bdPass.api.login._needCodestringCheckCallback&tpl=mn&charset=UTF-8&index=0&username=' + username + '&isphone=false&time=1436429688644'
loginPostUrl = 'https://passport.baidu.com/v2/api/?login'
#获取BAIDUID、token
request = urllib2.Request(loginUrl, headers=headers)
response = opener.open(request)

request = urllib2.Request(getTokenUrl, headers=headers)
response = opener.open(request)
hasToken = response.read()
token = re.search(r'login_token\s*=\s*\'(.+?)\'',hasToken).group(1)

#检查username是否需要验证码
request = urllib2.Request(getCodeStringUrl, headers=headers)
response = opener.open(request)
getCodeString = response.read()
codestring = re.search(r'"codestring":"?([^"]+)"?,', getCodeString).group(1)
if codestring == 'null' :
codestring = ''
verifycode = ''
else:
#需要验证码 创建一个tk显示验证码 并提示用户输入
genimageUrl = 'https://passport.baidu.com/cgi-bin/genimage?' + codestring + '&v=' + str(long(time.time()*1000))
import io, Tkinter as tk
from PIL import Image, ImageTk
request = urllib2.Request(genimageUrl, headers=headers)
image_bytes = opener.open(request).read()
pil_image = Image.open(io.BytesIO(image_bytes))

def presskey(event):
global verifycode
if event.keycode == 13:
verifycode = entry.get()
tk_root.destroy()

tk_root = tk.Tk()
tk_image = ImageTk.PhotoImage(pil_image)
label1 = tk.Label(tk_root, text='您的帐号异常,需要输入验证码')
label1.pack()

label2 = tk.Label(tk_root, image=tk_image)
label2.pack()

label3 = tk.Label(tk_root, text='输入验证码并按回车确认')
label3.pack()
entry = tk.Entry(tk_root)
entry.bind('<Key>', presskey)
entry.pack()
tk_root.mainloop()

#构造登录表单
data = {
"ppui_logintime":"134198",
"charset":"utf-8",
"codestring":"",
"isPhone":"false",
"index":"0",
"u":"",
"safeflg":"0",
"staticpage":"http://www.baidu.com/",
"loginType":"1",
"tpl":"mn",
"""yufang xiao tou. this code by zhengxiao"""
"callback":"parent.bdPass.api.login._postCallback",
"mem_pass":"on"
}
data['token'] = token
data['username'] = username
data['password'] = password
data['codestring'] = codestring
data['verifycode'] = verifycode
#开始登录
req = urllib2.Request(loginPostUrl, urllib.urlencode(data), headers)
result = opener.open(req).read()
#验证登录结果

errno = re.search(r'&error=(\d+)', result).group(1)
if errno == '0':
print '登录成功'
cookie.save(ignore_discard=True,ignore_expires=True)
elif errno == '4':
print '登录失败:密码错误'
elif errno == '257':
print '登录失败:验证码错误'
else:
print '登录失败'
print result #失败后 打印返回字符 by zh30.com

百度登录时,主要有四个步骤。
第一步:访问任意百度页面,得到名为BAIDUID的cookie
第二步:根据cookie去请求得到token(登录时要提交这个值)。
第三步:验证username是否需要验证码。返回值中如果存在codestring,说明需要验证码,然后根据这个codestring请求得到验证码。
第四步:提交登录表单,检查登录状态,记录cookie。判断登录是否成功,可以检查是否生成名为BDUSS的cookie,郑晓在这里判断的是返回字符串中的跳转链接,成功时error参数为0。
have fun!

selenium 使用实例10

用TKinter实现的一个简版HTTP请求模拟器

平时开发过程中经常会遇到需要模拟POST或GET请求的时候,当然GET一般直接通过浏览器也可以,方便快捷。郑晓看到网上也有不少软件版的HTTP模拟器,功能也非常强大。郑晓最近在学习Python,正好手闲的慌,就用Python自带的TKinter库写了个HTTP模拟工具,功能比较简单,只是实现了基本的功能。

最近我发现有的网站复制了我的文章,还把里面的各种信息都替换成了他自己的,还自己运行了程序截的图,也是挺郁闷的…所以以后发的代码中,郑晓可能会随机在其中加一点儿小点心…

这个tkinter的http模拟器代码如下,开发环境(win7 + Python2.7)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
# -*- coding: utf-8 -*-
from Tkinter import *
from ttk import *
from urlparse import urlparse
import urllib
#提交时的响应事件
def btn_submitOp(e):
#获取输入的值 并进行编码
url = entry_url.get().encode("utf-8")
entry_query = entry_para.get().encode("utf-8")

result = "请求的地址:" + url
result = result + "\n请求的方式:" + ["GET", "POST"][v.get()]
result = result + "\n请求的参数:" + entry_query

url_parse = urlparse(url)
query = url_parse.query.strip('&') +entry_query
#POST(请求原始URL, 使用编码后的参数)
try:
if v.get() == 1:
r = urllib.urlopen(url, entry_query)
#GET(根据提交的参数重新组合URL)
else:
url = url_parse.scheme+"://"+url_parse.netloc+url_parse.path+"?%s" % query
article_from_zhengxiao_blog_www_zh30_com = 0
r = urllib.urlopen(url)
data = r.read()
except:
data = "\n请求失败!"
result = result + "\n" + "-"*28 + '请求返回结果' + "-"*28 + data
#将结果输出(更新)到文本域
text_result.delete(0.0, END)
text_result.insert(1.0, result)

#####创建窗口#####
app = Tk()
app.title("HTTP请求模拟 v0.1")
app.geometry('500x500')

#####创建控件#####
#第一行 地址
lbl_url = Label(app, text="请求地址:")
lbl_url.grid(row=0, column=0, sticky=W, pady=5, padx=10)
entry_url = Entry(app, width=50)
entry_url.grid(row=0, column=1, sticky=W)
#第二行 方式
lbl_addr = Label(app, text="请求方式:")
lbl_addr.grid(row=1, column=0, sticky=W, pady=5, padx=10)
fm1 = Frame()
fm1.grid(row=1, column=1, sticky=W)
v = IntVar()
v.set(1)
btn_method = Radiobutton(fm1, variable=v, value=1, text="POST")
btn_method.pack(side = LEFT)
btn_method = Radiobutton(fm1, variable=v, value=0, text="GET")
btn_method.pack()
#第三行 参数
lbl_para = Label(app, text="请求参数:")
lbl_para.grid(row=2, column=0, sticky=W, padx=10)
entry_para = Entry(app, width=50)
entry_para.grid(row=2, column=1, sticky=W)
#第四行 提交
btn_submit = Button(app, text="发送请求")
btn_submit.bind('<Button-1>', btn_submitOp)
btn_submit.grid(row=3, column=0, sticky=W, padx=10,pady=10)

#第五行 返回结果
text_result = Text(app, width=68, height=25)
text_result.grid(row=4, column=0, columnspan=2, sticky=W, padx=10)

#第六行 其它
Label(app, text="-- by 郑晓").grid(row=5, column=1, sticky=E, padx=10, pady=10)

app.mainloop()

过程式编程看上去比较乱… 以下是运行截图,测试请求的是图灵机器人聊天接口。

python-tkinter-http请求模拟器

selenium 使用实例11

web.py使用session时报错AttributeError的解决办法

web.py使用session时报错AttributeError的解决办法
最近在学习web.py使用session时,经常会遇到AttributeError错误,大体报错内容是:
AttributeError: ‘ThreadedDict’ object has no attribute ‘xxxxx’
网上找的解决办法都是关闭web.py的调试模式,但有时关闭后也会报错,很是郁闷。

最后郑晓摸索出了使用session时需要注意的几点,在这里记录一下:

  1. 首先请关闭调试模式:
    web.config.debug = False
    代码需加到import web后,调用web.application之前,像这样:

    import web
    web.config.debug = False
    urls = (‘/‘, ‘index’)
    app = web.application(urls, globals())

  2. 创建session时,加上initializer参数,给你的session设置个默认值,像这样:

    session = web.session.Session(app, web.session.DiskStore(‘sessions’), initializer={‘user’:None, ‘login’:None})

按说不加initializer也应该可以使用啊,不知道为什么我不加的话,就会报错,不管你是不是判断了is not None,只要你调用了session.xxx就报错。

3.最囧的一点:删除之前创建的sessions文件。
上一步中,郑晓设置了将session以文件的形式储存到当前目录下的sessions目录中。所以在上二步确认无问题后,手动将sessions目录中的已存在的文件删除。不删除的话,程序还是使用的旧版session,还会报错- -!

4.have fun!

selenium 使用实例12

python函数式实现的多线程爬虫练习

写的一个爬虫练习,目的是抓取目标站点下所有链接, 并记录下问题链接url(包括问题url,入口链接,http状态码)。可以自行设置线程数量,程序开启一个子线程来维护当前线程数量。之前还好点儿,现在是越改bug越多,问题越多。

目前发现的问题有:
1.线程的管理上,之前用传统的方法,三个for循环来创建固定数量线程,不过发现如果某线程抛出异常后,线程终止,总线程数就会减少。所以自己改成了用一个死循环不停的监听活动线程数量。发现执行过程中,线程name的数量不断增长,每一个创建的线程在执行完一次方法后好像就退出了。。。
2.url_new列表保存待抓取的url,发现还是有重复的现象。 感觉用函数式的线程实现的话,线程间的同步好像不太好。。
3.lock有问题。。。因为自己还是没有掌握lock的锁法,发现url有重复时,自己把整个def都用lock锁了起来。。 还是问题不断啊。。
4.目标站还是写死在程序中。。。
待改进为面向对象!

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
#encoding: gb2312
import urllib2
import threading
import logging
import re
import sys
import os
from bs4 import BeautifulSoup
reload(sys)
sys.setdefaultencoding("utf-8")
#日志初始化
FILE = os.getcwd()
logging.basicConfig(filename=os.path.join(FILE, 'log.txt'),level=logging.DEBUG)
#待抓取的任务队列
url_new = [('none','http://www.xxxxxx.com/')]
#已完成的任务
url_old = []
#已完成的状态
url_err = {200:[]}
#锁
lock = threading.Lock()
lock2= threading.Lock()

#线程执行主方法
#从任务列表中获取一条url进行抓取
#分析url,去重复,将得到的urls重新放入任务列表
#保存当前url的访问状态
def geturl():
global url_new
try:
while True:
lock.acquire()
if len(url_new)<=0:
lock.release()
continue
url_t = url_new.pop(0)
url = url_t[1]
try:
req = urllib2.urlopen(url)
except urllib2.HTTPError, e:
#记录到对应的列表中
if url_err.has_key(e.code):
url_err[e.code].append((url,url_t[0]))
else:
url_err[e.code] = [(url,url_t[0])]
with open('log.html', 'a+') as f:
f.write(str(e.code)+':'+url+', 来路:'+url_t[0]+'<br>')
continue
else:
url_err[200].append(url)
with open('log.html', 'a+') as f:
f.write('200:'+url+', 来路:'+url_t[0]+'<br>')

#记录到已访问的列表中
url_old.append(url)
#开始提取页面url
soup = BeautifulSoup(req.read().decode('UTF-8', 'ignore'))
alink= soup.find_all('a', attrs={'href':re.compile(".*?xxxxxx.*?")})
tmp_url = []
for a in alink:
href = a.get('href')
tmp_url.append(a.get('href') if a.get('href').find('http:')>=0 else 'http://www.xxxxxx.com'+a.get('href'))
tmp_url= {}.fromkeys(tmp_url).keys()
for link in tmp_url:
if link not in url_old:
url_new.append((url, link))
tmp = []
for i in xrange(len(url_new)):
if url_new[i][1] not in tmp:
tmp.append(url_new[i][1])
else:
del url_new[i]

#url_new = {}.fromkeys(url_new).keys()

#输出一下状态信息
os.system('cls')
print threading.Thread().getName()+":当前线程数:"+str(threading.activeCount())+",当前剩余任务量:"+str(len(url_new))+", 已访问:"+str(len(url_old))
for k in url_err.keys():
print str(k)+':'+str(len(url_err[k]))

lock.release()
except Exception as e:
logging.debug(str(e))
lock.release()



#线程数检测 死循环持续检测当前活动线程数
#不够数量时自动创建启动新线程
def threadcheck(num):
t=threading.Thread(target=geturl)
t.start()
t.join()


#定义主方法
def main():
"""初始 创建200个线程
for i in xrange(190):
t = threading.Thread(target=geturl)
threads.append(t)
for i in xrange(190):
threads[i].start()
for i in xrange(190):
threads[i].join()"""
t = threading.Thread(target=threadcheck, args=(10,))
t.start()
t.join()
#geturl(url_new.pop(0))

#开始
if __name__ == '__main__':
main()
input('整站抓取已结束!')

qpython – 安卓上的python编辑利器!

在手机上敲代码纯属娱乐,输入速度比较蛋疼,不过装上玩玩也好。所以一直想找个可以在android安卓手机上编辑和运行python的软件。之前就尝试安装过qpython,不过是基于python2.7的。我是学习的python3,所以就一直没用。今天在三星app商店里找到了基于python3.2版本的qpython3,所以在这里拿出来分享给各位安卓控们。

以下是两个软件的部分截图,功能很全。
在手机上玩python的利器,Qpyton。这里提供了qpython的python2.7(即qpython0.9.7.3版)和python3.2(名字为qpython3,安装后名字叫Qpython+)的两个版本。
qpython
qpython3

selenium 使用实例13

python采集新浪热门微博

这是之前学习python采集时的一个练习程序,程序基于python3和BeautifulSoup库。用来抓取新浪微博(热门微博hot.weibo.com)页面的信息,包括每条微博的发布人,微博内容和包含的图片,微博中含有的多张图片采集为一个图片列表。

由于在页面中没有发现比较精确的发布时间字段,所以也没有去弄(目前思路是获取到它的页面中的时间信息,然后做判断去转换)。这里以热门笑话的一个页面做为采集对象。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
#-*-coding:utf-8 -*-
from bs4 import BeautifulSoup
import urllib.request
#伪造的header
headers = {'User-Agent':'Mozilla/5.0 (Windows NT 5.2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/30.0.1599.101 Safari/537.36'}
#抓取地址 读入页面源文件
fromurl='http://hot.weibo.com/?v=1899&page=2'
r = urllib.request.Request(url=fromurl, headers=headers)
response=urllib.request.urlopen(r)
page=response.read()
#实例化BS对象
soup= BeautifulSoup(page)
#定位到微博信息主节点 页面中每一条微博是它的子节点
tags = soup.find_all(name='div', attrs={'class':'WB_detail'})
#遍历所有子节点
for tag in tags:
#从子节点中找到发布人
sender = tag.find(name='a', attrs={'class':'WB_name S_func1'}).get_text()
#从子节点中找到微博内容
text = tag.find(name='div', attrs={'class':'WB_text'}).get_text()
#查找节点下的微博图片
thumbList = tag.find_all(name='img', attrs={'class':'bigcursor'})
img = []
#如果有图,把所有图片的地址放到img数组中
if thumbList:
for t in thumbList:
img.append(t['src'])
print(sender+text)
print(img)
print()
print()
input()

python抓取糗百信息并入库mysql

这里抓取的页面是糗百的最近8小时糗事页面。感觉它的列表规则比较简单一些。学习pytho的urllib库基本操作与mysql的基础使用。
连接mysql使用的是mysql自家的connector。http://dev.mysql.com/doc/connector-python/en/index.html
环境win2003+python3.3代码如下。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
#导入urllib、mysql和正则类库
import urllib.request
import mysql.connector
import re
#设置要抓取的页面
url="http://www.qiushibaike.com/8hr/page/1"
#模拟访问页面,抓取页面内容到page变量中
response=urllib.request.urlopen(url)
page=response.read()
#匹配糗事正文及图片的正则
p = re.compile(r'<div class="content" title="([\d\-\s:]+)">([^<]*(?=<br\/>[^<]+)*)<\/div>(?=\s*<div class="thumb">\s*<a[^>]+>\s*(<img[^>]+\/>)\s*<\/a>\s*<\/div>)?')
#对抓取的utf8的内容转为unicode 并执行匹配 将匹配结果放到resultlist列表。
resultlist = p.findall(page.decode('utf-8'))
print(resultlist)
#以下是数据库操作部分
#数据库连接配置字典
conn = {'host':'localhost', 'user':'root', 'password':'flake', 'database':'test'}
#建立数据库连接
conn = mysql.connector.connect(**conn)
#获得游标
cursor = conn.cursor()
#插入数据库的sql 将内容中的换行符直接替换掉
insertSql = "insert into qiubai (dates, text, img) values (%s, replace(replace(%s,'\n',''),'\r',''), %s)"
#执行批量插入操作
cursor.executemany(insertSql, resultlist)
#关闭游标及数据库连接
cursor.close()
conn.close()
input()

python-tkinter的键盘事件监听

python-tkinter的键盘事件监听的实现,特殊字符直接打印是不会显示的,但都是正常的。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
#导入tkinter
from tkinter import *
#定义的方法 监听键盘事件
def printkey(event):
print('你按下了: ' + event.char)
#实例化tk
root = Tk()
#实例化一个输入框
entry = Entry(root)
#给输入框绑定按键监听事件<Key>为监听任何按键 <Key-x>监听其它键盘,如大写的A<Key-A>、回车<Key-Return>
entry.bind('<Key>', printkey)
#显示窗体
entry.pack()
root.mainloop()

结果如下:

转自:https://www.zh30.com

自动化测试 selenium 模块 webdriver使用(一)

一、webdriver基本使用命令

1
from selenium import webdriver   # 导入webdriver模块
1
2
3
4
5
6
7
>>> chrome_obj = webdriver.Chrome()              # 打开Google浏览器
>>> chrome_obj.get("https://www.baidu.com") # 打开 网址

>>> chrome_obj.get(r"C:\desktop\text.html") # 打开本地 html页面

>>> chrome_obj.title # 获取打开网址 的名字
>>> chrome_obj.current_url # 获取打开网址的 url<br><br>>>> chrome_obj.close() #关闭浏览器窗口

二、标签导航

普通 定位标签

1
2
3
4
5
6
7
8
9
10
11
# 查找标签
>>> label = chrome_obj.find_element_by_id("kw")
>>> label = chrome_obj.find_element_by_name("wd")
>>> label = chrome_obj.find_element_by_class_name("s_ipt")
>>> label = chrome_obj.find_element_by_tag_name("imput")

>>> label = chrome_obj.find_element_by_link_text("a标签中的内容 准确定位")
>>> label = chrome_obj.find_element_by_partial_link_text("a标签中的内容 模糊定位 ")

>>> label = chrome_obj.find_element_by_xpath(“放入 copy 标签中的常css路径”)
>>> label = chrome_obj.find_element_by_css_selector(“input=[id='id_name'/name='name_name'/……/]")

标签导航 xpath 标签定位复杂的情况下 考虑使用xpath

XPath即为XML路径语言,它是一种用来确定XML(标准通用标记语言的子集)文档中某部分位置的语言。XPath基于XML的树状结构,有不同类型的节点,包括元素节点,属性节点和文本节点,提供在数据结构树中找寻节点的能力。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
# 绝对路径
>>> label = chrome_obj.find_element_by_xpath("html/boday/p/input") # 绝对路径 导航
>>> label = chrome_obj.find_element_by_xpath("html/boday/p/input[1]") # 绝对路径导航,多个input框,确定第一个input框

#相对路径
>>> label = chrome_obj.find_element_by_xpath("//input") # 相对路径导航 表示 整个文档当中的 input标签 默认为第一个 * 第一个“//” 表示 在整个文档中
>>> label = chrome_obj.find_element_by_xpath("//input[2]") # 指定页面中的第二个 input框 没有就报错


# 父节点下找子节点
>>> label = chrome_obj.find_element_by_xpath("//form//input") # // 父节点//子节点 * 返回子节点 input
>>> label = chrome_obj.find_element_by_xpath("//form//input[2]") # // 父节点//子节点 [2] * 指定 父节点下的 第二个 input子节点


# 通过子节点 定位父节点
>>> label = chrome_obj.find_element_by_xpath("//form//input/..") # 返回input的父节点 form 标签
>>> label = chrome_obj.find_element_by_xpath("//form//input/.") # 当前节点


# 通过属性查找节点
>>> label = chrome_obj.find_element_by_xpath("//input[@id]") # 相对路径导航 找到所有的 input标签 其中有 id属性的标签
>>> label = chrome_obj.find_element_by_xpath("//input[@id='1']") # 属性查找 在所有的input标签中 找到 具有 id=1 的input标签
>>> label = chrome_obj.find_element_by_xpath("//input[@name='xiahua']")


# 标签统计 countains
>>> label = chrome_obj.find_element_by_xpath("//*[countains(input)=1]") # //* 表示 整个文档中 的所有标签,[count(input)=1] 表示 父标签下只有 一个input子标签 的 input标签
>>>label = chrome_obj.find_element_by_xpath("//*[countains(input)=2]") # //* 表示 整个文档中 的所有标签,[count(input)=1] 表示 父标签下有 两个input子标签 的 input标签


# local-name 模糊查找
>>> label = chrome_obj.find_element_by _xpath("//*[local-name()='input']") # 查找当前文档中 的所有input标签 默认返回第一个
>>> label = chrome_obj.find_element_by _xpath("//*input") # 查找当前文档中 的所有input标签 默认返回第一个

>>> label = chrome_obj.find_element_by _xpath("//*[local-name(),'i']") # 查找当前文档中 标签名字中 包含字母 i的标签,比如 input title
>>> label = chrome_obj.find_element_by _xpath("//*[local-name(),'i']") # 查找当前文档中 的所有input标签 默认返回第一个

>>> label = chrome_obj.find_element_by _xpath("//*[countains(local-name(),'i')] [last()]) # 查找当前文档中 所有包含 字母“i”的 标签 的子标签 的 最后一个元素 (有点懵逼)
>>> label = chrome_obj.find_element_by _xpath("//*[strint-length(local-name()=3)] [last()]) # 查找当前文档中 所有 标签字符个数为5的标签,并且制定返回 最后一个标签。 title input(5个str)

三、 模拟用户操作

1
2
3
4
5
6
7
8
9
>>> label.get_attribute("type") # 显示标签的type属性 name type id placeholder
>>> label.tag_name() #获取标签名字 input p form ……

>>> label.size
>>> label.id

>>> chrome_obj.maximize_window()# 窗口最大化 <br>>>> #模拟鼠标悬浮
>>> label.click() # 模拟a标签 点击事件
>>> label.send_keys("模拟搜索内容") # 模拟input框 输入内容>>> label.clear() # 清除input标签中 输入的内容>>> chrome_obj.back() # 模拟浏览器 返回上一个浏览页面

1、模拟鼠标操作

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
from selenium.webdriver.common.action_chains import ActionChains #导入模块

>>> label = chrome_obj.find_element_by_link_text("点我 悬浮 显示其他 a标签")

>>> ActionChains(chrome_obj).move_to_element(label).perform() # 模拟用户悬浮

"""  ActionChains(chrome_obj) 用于生成模拟用户行为 ;
perform() 执行存储行为  """
>>> label_bel = chrome_obj.find_element_by_link_text("我是 a标签,点我页面跳转")>>> label_bel.click() # 模拟用户点击

 其他鼠标操作

label.countext_lick() # 右击
label.double_click() # 双击
label.drag_and_drop() # 拖动
label.move_to_element # 悬浮
label.click_and_hold # 按鼠标左键一直不动

2、模拟键盘操作

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

from selenium.webdriver.common.keys import Keys # 引入模块

>>> label.send_keys("input输入的内容")

>>> label.send_keys(Keys.BACK_SPANCE) # 退格键

>>>label.send_keys(Keys.CONTRL,'a') # 全选

>>>label.send_keys(Keys.CONTRL,'v') # 粘贴

>>>label.send_keys(Keys.CONTRL,'c') # 复制

>>>label.send_keys(Keys.CONTRL,'x‘’) # 剪切

>>>label.send_keys(Keys.ENTER) # 回车

四、处理对话框

python脚本实现自动登录

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
from selenium import webdriver
import time

def automatic_login(name,pwd,url):
chrome = webdriver.Chrome()
chrome.get(url)

time.sleep(2)

chrome.maximize_window()

time.sleep(5)

chrome.find_element_by_xpath("/html/body/div[3]/div[2]/div[3]/div/div").click()

chrome.find_element_by_link_text("登录").click()
time.sleep(5)

name_label = chrome.find_element_by_id("id_account_l")
name_label.clear()
name_label.send_keys(name)

pwd_label = chrome.find_element_by_id("id_password_l")
pwd_label.clear()
pwd_label.send_keys(pwd)

time.sleep(5)

login_label = chrome.find_element_by_id("login_btn")
login_label.click()

time.sleep(15)
chrome.close()

if __name__ == "__main__":
name = "helloyiwantong@163.com"
pwd = "helloyiwantong@1234"
url = "http://www.maiziedu.com/"
automatic_login(name,pwd,url)

python automatic login

五、控制多窗口

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
>>> frome selenium import webdrive

>>> chrome = webdrive.Chrome()

>>> chrome.get("https://www.baidu.come")

>>> chrome.find_element_by_id("kw").send_keys("红花")

>>> chrome.find_element_by_id("su").click() # 打开百度搜索的第一个窗口



>>> chrome.find_element_by_partial_link_text("百度百科").click() # 打开第二个窗口

>>> chrome.find_element_by_partial_link_text("中药").click() # 打开第三个窗口



>>> chrome.window_handles # 查看当前 打开窗口

['CDwindow-D41F1F3BF5038E36E91EA7F7E7E9770D',

'CDwindow-F2D1553323BDC39BE99DBF280804FCCC',

'CDwindow-B41B29B8A7CB49BF191E46FF936E6A52',]

>>> chrome.switch_to_window(chrome.window_handles[1]) # 使用索引切换到第二个窗

>>> chrome.current_url() # 查看当前url

六、模拟用户自动登录

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
from selenium import webdriver
import time
from selenium.webdriver.support.ui import WebDriverWait

def wait_response_time(chrome,waittime,func):
# 返回 func执行结果
return WebDriverWait(chrome,waittime).until(func)

def automatic_login(name,pwd,url):
chrome = webdriver.Chrome()
chrome.get(url)

time.sleep(2)

chrome.maximize_window()

# time.sleep(2)
# chrome.find_element_by_xpath("/html/body/div[3]/div[2]/div[3]/div/div").click()
############## 第二种方法 设置时间延迟
# login_btn_lable = wait_response_time(chrome,5,
# lambda chrome: chrome.find_element_by_xpath("/html/body/div[3]/div[2]/div[3]/div/div"))
# login_btn_lable.click() ## 利用函数设置等待响应时间


chrome.find_element_by_link_text("登录").click()
time.sleep(1)



name_label = chrome.find_element_by_id("id_account_l")
name_label.send_keys(" ") # 防止发送不成功
name_label.clear()
name_label.send_keys(name)

pwd_label = chrome.find_element_by_id("id_password_l")
pwd_label.clear()
pwd_label.send_keys(pwd)

time.sleep(5)

login_label = chrome.find_element_by_id("login_btn")
login_label.click()

error_id="login-form-tips"
error_message=chrome.find_element_by_id(error_id)
err=error_message.text
print(error_message,type(error_message))
print(err)

# time.sleep(10)
# chrome.close()

if __name__ == "__main__":
name = "helloyiwantong@163.com"
pwd = "helloyiwantong@134"
url = "http://www.maiziedu.com/"
automatic_login(name,pwd,url)

automatic login

七、模拟用户自动登录 封装接口

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
from selenium import webdriver
import time
from selenium.webdriver.support.ui import WebDriverWait

def open_browse():
"""
open browser obj
:return:
"""
browse_obj = webdriver.Chrome()
return browse_obj

def click_url_and_clicl_loginbtn(browse,url):

"""
open url and click "登录" btn
:param browse:
:param url:
:return:
"""
browse.get(url)
browse.maximize_window()
loginbtn_lable=browse.find_element_by_link_text("登录")
loginbtn_lable.click()
time.sleep(1)

def get_element_label(browse,element_id_dict):
"""
get element lable
:param browse:
:param element_id_dict:
:return:
"""
user_label = browse.find_element_by_id(element_id_dict["name"])
pwd_label = browse.find_element_by_id(element_id_dict.get("pwd"))
login_label = browse.find_element_by_id(element_id_dict.get("login"))
return (user_label,pwd_label,login_label)

def send_key_s(lable_tuple,userinfo_dict,userinfo_list):
"""
send userinfo and logian
:param lable_tuple:
:param userinfo_dict:
:param userinfo_list:
:return:
"""

i=0
if i<=1:
for key in userinfo_list:
# lable_tuple[i].send_keys(" ")
# lable_tuple[i].click()
lable_tuple[i].send_keys(userinfo_dict.get(key))
i+=1
time.sleep(1)

lable_tuple[2].click()


### 封装数据

url = "http://www.maiziedu.com/"
id_dict = {
"name":"id_account_l",
"pwd" : "id_password_l",
"login":"login_btn",
}

userinfo_dict={
"name" : "helloyiwantong@163.com",
"pwd" : "helloyiwantong@1234",
"url" : "http://www.maiziedu.com/",
}

# 函数使用

userinfo_list =["name","pwd"]

chrome = open_browse()
click_url_and_clicl_loginbtn(chrome,url)

lable_tuple = get_element_label(chrome,id_dict)

send_key_s(lable_tuple,userinfo_dict,userinfo_list)

automatic login

更多参考: https://www.cnblogs.com/hellosecretgarden/p/9206648.html

经典参考文档:

https://blog.csdn.net/u010986776/article/details/79266448

https://blog.csdn.net/Yeoman92/article/details/83105318

QQ群:397745473

欢迎关注我的其它发布渠道