基于Selenium与图像识别的百度指数爬虫

前言

在参与一个项目的时候,得到了这样一个需求,需要我用爬虫爬取某个关键词的百度指数,而当我打开网址后http://index.baidu.com/,简单登陆输入关键词后,发现事情并不那么简单。
基于Selenium与图像识别的百度指数爬虫_第1张图片
表面上看,这里只需要模拟鼠标操作,然后读取弹出的每一个ViewBox的数据便大功告成了。但百度不会让你那么简单获取数据。
基于Selenium与图像识别的百度指数爬虫_第2张图片
通过这张图我们很开心地发现,百度指数具体的数字竟然是图片!!!每一个数字竟然都是一个图片!!!!显然,常规的思路已经无法驾驭百度指数了,在经过综合考虑过后,我决定采用Python的图像识别包来识别并爬取百度指数。

主要技术介绍

Selenium

Selenium是一个用于Web应用程序测试的工具。Selenium测试直接运行在浏览器中,就像真正的用户在操作一样。它可以最大限度地模拟浏览器操作,每运行一个Selenium程序就会打开一个浏览器。
在本次数据采集工作中我们最为核心的是采用了ActionChains这个类,实现了模拟鼠标的移动。每次移动的距离就是从一天到下一天的距离。

 ActionChains(browser).move_to_element_with_offset(xoyelement, x_0, y_0).perform()

Pytesseract

而在获取到图像数据后,我们使用Python一个常用的图像识别包完成了图像数据向数字数据的转换。

 image = Image.open(path + "/zoom/" + printString)
        code = pytesseract.image_to_string(image)

Pytesseract的安装

 sudo apt-get install tesseract-ocr
 sudo apt-get install python-imaging
 sudo pip install pytesseract

流程介绍与代码分析

此处仅摘取部分重要代码

登陆

在登陆方面我没有下太大功夫,甚至没有实现自动化,因为百度指数在爬取的过程中不会出现需要重新登陆的情况,故用一个input()函数让程序暂停会儿,登陆后输入1便可。

#百度指数网站
url = "http://index.baidu.com/"
browser = webdriver.Chrome()
browser.get(url)
# 点击网页的登录按钮  browser.find_element_by_xpath("//ul[@class='usernav']/li[4]").click()
# 完成登陆后在控制台输入1
jud=input("登录好后输入1")
while 1:
   if jud==1:
       break

输入关键词并搜索

# 清空网页输入框
browser.find_element_by_id("schword").clear()
# 写入需要搜索的百度指数      browser.find_element_by_id("schword").send_keys(name)
# 点击搜索
browser.find_element_by_id("searchWords").click()

搜索ViewBox的位置并获取坐标

#找到ViewBox
imgelement = browser.find_element_by_xpath('//div[@id="viewbox"]')
#定位ViewBox
locations = imgelement.location

保存网页截图并截取ViewBox中的指数图片

#确定截图范围
rangle = (int(int(locations['x'])), int(int(locations['y'])),
              int(int(locations['x'])+100) ,
              int(int(locations['y'])) + 80)
#保存整体网页截图
browser.save_screenshot(str(path) + "/raw/" + printString + ".png")
#打开网页截图
img = Image.open(str(path) + "/raw/" + printString + ".png")
#截取ViewBox
jpg = img.crop(rangle)

放大并识别图片

#打开截取的图片
jpgzoom = Image.open(str(imgpath))
(x, y) = jpgzoom.size
#设置放大倍数
x_s = 60 * 10
y_s = 20 * 10
#放大图片并保存
out = jpgzoom.resize((x_s, y_s), Image.ANTIALIAS)
out.save(path + "/zoom/" + printString, 'jpeg', quality=95)
#读取待识别的图片
image = Image.open(path + "/zoom/" + printString)
code = pytesseract.image_to_string(image)

错误处理

由于不可抗的因素,有些时候鼠标移动时候不一定会弹出ViewBox,这会导致空指针错误,故在截图的时候需要先做ViewBox是否Exist的判断。为了优化该问题,我们也可以写一个循环,当ViewBox不出现的时候不断循环重复鼠标的操作。

cot=0
while (ExistBox(browser)==False):
        cot+=1
 ActionChains(browser).move_to_element_with_offset(xoyelement, x_0, y_0).perform()
    if ExistBox(browser)==True:
          break
    if cot==6:
          return None

图像识别包始终会存在错误,故有可能有一些普遍的识别错误,故可以对识别得到的数字做一个简单的替换处理

dealcode = code.replace("S", '5').replace(" ", "").replace(",", "").replace("E", "8").replace(".", ""). \
            replace("'", "").replace(u"‘", "").replace("B", "8").replace("\"", "").replace("I", "1").replace(
            "i", "").replace("-", ""). \
replace("$", "8").replace(u"’", "").strip()

以上便是本博客的全部内容

本博客主要介绍的是百度指数爬虫主要涉及的几个模块,通过设计拼凑循环可以完成更多的任务。
代码已在Github上
https://github.com/TerenceLiu2/BaiduIndexCrawl

你可能感兴趣的:(爬虫开发)