早就想写博客,但是做的东西感觉很low就不好意思发出来,最近由于女票需要百度指数得数据,于是研究起爬虫。以前毕设的题目就是爬虫,不过是特别简单的那种。在爬取百度指数的指数数据时,才感觉到爬虫不是那么简单。自己也是在网上找了许多大神的教程,但是都不能够很好的抓到数据。下面就将我所使用的方法做一个简单介绍,全部代码在整理完后后放到github上。
(一)需要的工具
我使用的是Python+Selenium+Opencv,IDE用的是PyCharm,个人感觉这个IDE比较好用,至于怎么安装不会的可以
直接百度,较简单。需要特意注意一点的是,需要用到一个库,在该IDE上不能自动下载,需要手动下载,放到库的目录下,也就是
aircv,用于直接匹配模板的。
(二)登陆百度账号并打开百度指数界面
我用的是火狐浏览器,本打算用谷歌,但是驱动老是版本不正确,只能用火狐。用selenium打开百度账号登陆界面,
自动输入账号密码,当然有验证码的问题,这个我就没有做,网上有许多识别验证码的代码,有兴趣的可以做做,
我直接是手动输入验证码(由于只需要登陆一次)。在进入登陆页面之后,在该浏览器打开百度指数搜索的页面(保证账
号登陆)。用selenium模拟输入关键词并查找进入查找结果页面。由于百度指数数据是浮动的div,为了保证在界面上能
找到所有的数据,将浏览器窗口最大化,以便于获取全部的数据。下面给出关键代码:
-
url =
"https://passport.baidu.com/v2/?login&tpl=mn&u=http%3A%2F%2Fwww.baidu.com%2F"
-
# 打开谷歌浏览器
-
# Firefox()
-
# Chrome()
-
option = webdriver.FirefoxOptions()
-
option.add_argument(
'--user-data-dir=C:\\Users\\LMR\\AppData\\Local\\Google\\Chrome\\User Data')
# 设置成用户自己的数据目录
-
-
browser = webdriver.Firefox(firefox_options=option)
-
# browser = webdriver.Chrome()
-
# 输入网址
-
browser.get(url)
-
browser.find_element_by_id(
"TANGRAM__PSP_3__footerULoginBtn").click()
-
# 找到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 =[
'账号',
'密码']
-
-
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])
-
time.sleep(
10)
-
# 点击登陆登陆
-
# id="TANGRAM__PSP_3__submit"
-
browser.find_element_by_id(
"TANGRAM__PSP_3__submit").click()
#打开百度指数界面并输入关键字
-
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])
-
# 在新窗口里面输入网址百度指数
-
# 清空输入框
-
time.sleep(
5)
-
browser.find_element_by_id(
"schword").clear()
-
# 写入需要搜索的百度指数
-
browser.find_element_by_id(
"schword").send_keys(keyword)
-
time.sleep(
2)
-
print keyword
-
# 点击搜索
-
# <input type="submit" value="" id="searchWords" onclick="searchDemoWords()">
-
browser.find_element_by_id(
"searchWords").click()
-
time.sleep(
5)
-
# 最大化窗口
-
browser.maximize_window()
(三)模拟鼠标移动获取浮动窗口数据并截图
由于指数数据必须将鼠标放到相应位置才可以显示出来,所以需要模拟鼠标移动,当浮动窗口显示出来时截取当前
界面保
存。关键代码如下:
-
xoyelement = browser.find_element_by_xpath(
'//li[@data-value="all"]')
#基准元素
-
time.sleep(
2)
-
num =
0
-
x_0 =
3
-
y_0 =
130
-
print xoyelement.location,
"trend"
-
if day ==
"all":
-
day =
1000000
-
# 储存数字的数组
-
index = []
-
try:
-
webdriver.ActionChains(browser).move_to_element(xoyelement).perform()
-
# 只有移动位置xoyelement[2]是准确的
-
for i
in range(day
-1):
-
# 相对于基准元素的偏移量
-
ActionChains(browser).move_to_element_with_offset(xoyelement, x_0, y_0).perform()
-
time.sleep(
2)
-
while (
1 ==
1):
#无限循环模拟鼠标移动直到出现所需要的数据为止
-
try:
-
a = browser.find_element_by_xpath(
"//div[@id='viewbox']")
-
locs = a.location
-
x = locs[
"x"]
-
if x !=
0.0:
-
break
-
ActionChains(browser).move_to_element_with_offset(xoyelement, x_0+
8, y_0).perform()
-
ActionChains(browser).move_to_element_with_offset(xoyelement, x_0, y_0).perform()
-
except Exception
as err:
-
print i
-
-
ActionChains(browser).move_to_element_with_offset(xoyelement, x_0, y_0).perform()
-
time.sleep(
1)
-
# 截取当前浏览器
-
path =
"../baidu/" + str(num)
-
browser.save_screenshot(str(path) +
".png")
-
所截取的图片如下图所示:
其中黑色区域即是我们需要获取的数据区域。