前言:
土福曾说,百度指数很难抓,在淘宝上面是20块1个关键字:
哥那么叼的人怎么会被他吓到,于是乎花了零零碎碎加起来大约2天半搞定,在此鄙视一下土福
安装的库很多:
1
2
3
4
5
6
7
8
9
10
11
|
谷歌图像识别tesseract-ocr
pip3 install pillow
pip3 install pyocr
selenium2.45
Chrome47.0.2526.106 m or Firebox32.0.1
chromedriver.exe
|
图像识别验证码请参考:http://www.zzvips.com/article/101416.html
selenium用法请参考:http://www.zzvips.com/article/103695.html
进入百度指数需要登陆,登陆的账号密码写在文本account里面:
万能登陆代码如下:
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
|
# 打开浏览器
def openbrowser():
global browser
# https://passport.baidu.com/v2/?login
url = "https://passport.baidu.com/v2/?login&tpl=mn&u=http%3A%2F%2Fwww.baidu.com%2F"
# 打开谷歌浏览器
# Firefox()
# Chrome()
browser = webdriver.Chrome()
# 输入网址
browser.get(url)
# 打开浏览器时间
# print("等待10秒打开浏览器...")
# time.sleep(10)
# 找到id="TANGRAM__PSP_3__userName"的对话框
# 清空输入框
browser.find_element_by_id( "TANGRAM__PSP_3__userName" ).clear()
browser.find_element_by_id( "TANGRAM__PSP_3__password" ).clear()
# 输入账号密码
# 输入账号密码
account = []
try :
fileaccount = open ( "../baidu/account.txt" )
accounts = fileaccount.readlines()
for acc in accounts:
account.append(acc.strip())
fileaccount.close()
except Exception as err:
print (err)
input ( "请正确在account.txt里面写入账号密码" )
exit()
browser.find_element_by_id( "TANGRAM__PSP_3__userName" ).send_keys(account[ 0 ])
browser.find_element_by_id( "TANGRAM__PSP_3__password" ).send_keys(account[ 1 ])
# 点击登陆登陆
# id="TANGRAM__PSP_3__submit"
browser.find_element_by_id( "TANGRAM__PSP_3__submit" ).click()
# 等待登陆10秒
# print('等待登陆10秒...')
# time.sleep(10)
print ( "等待网址加载完毕..." )
select = input ( "请观察浏览器网站是否已经登陆(y/n):" )
while 1 :
if select = = "y" or select = = "Y" :
print ( "登陆成功!" )
print ( "准备打开新的窗口..." )
# time.sleep(1)
# browser.quit()
break
elif select = = "n" or select = = "N" :
selectno = input ( "账号密码错误请按0,验证码出现请按1..." )
# 账号密码错误则重新输入
if selectno = = "0" :
# 找到id="TANGRAM__PSP_3__userName"的对话框
# 清空输入框
browser.find_element_by_id( "TANGRAM__PSP_3__userName" ).clear()
browser.find_element_by_id( "TANGRAM__PSP_3__password" ).clear()
# 输入账号密码
account = []
try :
fileaccount = open ( "../baidu/account.txt" )
accounts = fileaccount.readlines()
for acc in accounts:
account.append(acc.strip())
fileaccount.close()
except Exception as err:
print (err)
input ( "请正确在account.txt里面写入账号密码" )
exit()
browser.find_element_by_id( "TANGRAM__PSP_3__userName" ).send_keys(account[ 0 ])
browser.find_element_by_id( "TANGRAM__PSP_3__password" ).send_keys(account[ 1 ])
# 点击登陆sign in
# id="TANGRAM__PSP_3__submit"
browser.find_element_by_id( "TANGRAM__PSP_3__submit" ).click()
elif selectno = = "1" :
# 验证码的id为id="ap_captcha_guess"的对话框
input ( "请在浏览器中输入验证码并登陆..." )
select = input ( "请观察浏览器网站是否已经登陆(y/n):" )
else :
print ( "请输入“y”或者“n”!" )
select = input ( "请观察浏览器网站是否已经登陆(y/n):" )
|
登陆的页面:
登陆过后需要打开新的窗口,也就是打开百度指数,并且切换窗口,在selenium用:
1
2
3
4
5
6
7
8
9
10
|
# 新开一个窗口,通过执行js来新开一个窗口
js = 'window.open("http://index.baidu.com");'
browser.execute_script(js)
# 新窗口句柄切换,进入百度指数
# 获得当前打开所有窗口的句柄handles
# handles为一个数组
handles = browser.window_handles
# print(handles)
# 切换到当前最新打开的窗口
browser.switch_to_window(handles[ - 1 ])
|
清空输入框,构造点击天数:
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
|
# 清空输入框
browser.find_element_by_id( "schword" ).clear()
# 写入需要搜索的百度指数
browser.find_element_by_id( "schword" ).send_keys(keyword)
# 点击搜索
# <input type="submit" value="" id="searchWords" onclick="searchDemoWords()">
browser.find_element_by_id( "searchWords" ).click()
time.sleep( 2 )
# 最大化窗口
browser.maximize_window()
# 构造天数
sel = int ( input ( "查询7天请按0,30天请按1,90天请按2,半年请按3:" ))
day = 0
if sel = = 0 :
day = 7
elif sel = = 1 :
day = 30
elif sel = = 2 :
day = 90
elif sel = = 3 :
day = 180
sel = '//a[@rel="' + str (day) + '"]'
browser.find_element_by_xpath(sel).click()
# 太快了
time.sleep( 2 )
|
天数也就是这里:
找到图形框:
1
|
xoyelement = browser.find_elements_by_css_selector( "#trend rect" )[ 2 ]
|
图形框就是:
根据坐标点的不同构造偏移量:
选取7天的坐标来观察:
第一个点的横坐标为1031.66666
第二个点的横坐标为1234
所以7天两个坐标之间的差为:202.33,其他的天数类似
用selenium库来模拟鼠标滑动悬浮:
1
2
|
from selenium.webdriver.common.action_chains import ActionChains
ActionChains(browser).move_to_element_with_offset(xoyelement,x_0,y_0).perform()
|
但是这样子确定的点指出是在这个位置:
也就是矩形的左上角,这里是不会加载js显示弹出框的,所以要给横坐标+1:
1
2
|
x_0 = 1
y_0 = 0
|
写个按照天数的循环,让横坐标累加:
1
2
3
4
5
6
7
8
9
10
11
|
# 按照选择的天数循环
for i in range (day):
# 构造规则
if day = = 7 :
x_0 = x_0 + 202.33
elif day = = 30 :
x_0 = x_0 + 41.68
elif day = = 90 :
x_0 = x_0 + 13.64
elif day = = 180 :
x_0 = x_0 + 6.78
|
鼠标横移时会弹出框,在网址里面找到这个框:
selenium自动识别之...:
1
2
|
# <div class="imgtxt" style="margin-left:-117px;"></div>
imgelement = browser.find_element_by_xpath( '//div[@id="viewbox"]' )
|
并且确定这个框的大小位置:
1
2
3
4
5
6
7
8
9
|
# 找到图片坐标
locations = imgelement.location
print (locations)
# 找到图片大小
sizes = imgelement.size
print (sizes)
# 构造指数的位置
rangle = ( int (locations[ 'x' ]), int (locations[ 'y' ]), int (locations[ 'x' ] + sizes[ 'width' ]),
int (locations[ 'y' ] + sizes[ 'height' ]))
|
截取的图形为:
下面的思路就是:
1.将整个屏幕截图下来
2.打开截图用上面得到的这个坐标rangle进行裁剪
但是最后裁剪出来的是上面的那个黑框,我想要的效果是:
所以要对rangle进行计算,但是我懒,忽略了搜索词的长度,直接暴力的写成:
1
2
3
|
# 构造指数的位置
rangle = ( int (locations[ 'x' ] + sizes[ 'width' ] / 3 ), int (locations[ 'y' ] + sizes[ 'height' ] / 2 ), int (locations[ 'x' ] + sizes[ 'width' ] * 2 / 3 ),
int (locations[ 'y' ] + sizes[ 'height' ]))
|
这个写法最终不太好,最起码要对keyword的长度进行判断,长度过长会导致截图坐标出现偏差,反正我知道怎么做,就是不写出来给你们看!
后面的完整代码是:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
# <div class="imgtxt" style="margin-left:-117px;"></div>
imgelement = browser.find_element_by_xpath( '//div[@id="viewbox"]' )
# 找到图片坐标
locations = imgelement.location
print (locations)
# 找到图片大小
sizes = imgelement.size
print (sizes)
# 构造指数的位置
rangle = ( int (locations[ 'x' ] + sizes[ 'width' ] / 3 ), int (locations[ 'y' ] + sizes[ 'height' ] / 2 ), int (locations[ 'x' ] + sizes[ 'width' ] * 2 / 3 ),
int (locations[ 'y' ] + sizes[ 'height' ]))
# 截取当前浏览器
path = "../baidu/" + str (num)
browser.save_screenshot( str (path) + ".png" )
# 打开截图切割
img = Image. open ( str (path) + ".png" )
jpg = img.crop(rangle)
jpg.save( str (path) + ".jpg" )
|
但是后面发现裁剪的图片太小,识别精度太低,所以需要对图片进行扩大:
1
2
3
4
5
6
7
8
|
# 将图片放大一倍
# 原图大小73.29
jpgzoom = Image. open ( str (path) + ".jpg" )
(x, y) = jpgzoom.size
x_s = 146
y_s = 58
out = jpgzoom.resize((x_s, y_s), Image.ANTIALIAS)
out.save(path + 'zoom.jpg' , 'png' , quality = 95 )
|
原图大小请 右键->属性->详细信息 查看,我的是长73像素,宽29像素
最后就是图像识别
1
2
3
4
5
6
|
# 图像识别
index = []
image = Image. open ( str (path) + "zoom.jpg" )
code = pytesseract.image_to_string(image)
if code:
index.append(code)
|
最后效果图:
源码下载:demo
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持服务器之家。
原文链接:http://www.cnblogs.com/TTyb/p/6051366.html