百度指数获取踩坑小结

作者: 0xE8551CCB | 来源:发表于2017-06-01 19:01 被阅读159次

    引言

    经过若干天不断地踩坑,总算能够正常获取百度指数啦,Just for fun~

    百度指数爬虫开发的难点不在于爬虫本身,当然主要是因为 Python + Selenium 组合已经足够完成完整的登录+关键词查询的基本功能了。指数获取的难点在于:指数的数据是以 image text 的形式呈现,因此无法直接获取这种看似文本格式的数据。


    image.png

    登录

    登录功能很容易借助 Selenium 实现,整体流程如下:

    1. 直接控制浏览器打开百度指数](https://index.baidu.com)) 页面;
    2. 优先查看下当前的状态,如果此时处于登录状态(可以看见用户名),就停止登录后续流程并返回;
    3. 在该页面模拟点击右上角的登录按钮,等待片刻即可看见弹窗;
    4. 在输入框中模拟输入用户名、密码并点击记住登录信息候选框后,点击登录按钮完成登录过程。
      image.png

    Cookie 管理

    为了方便后期直接使用 Cookie 登录,我们可以在完成前一步的登录流程后保存浏览器的 Cookies,并在下次启动查询之前优先加载本地的 Cookies。完整的 Cookie 处理代码如下:

    def dump_cookies(driver, to_file=None):
        to_file = to_file or DEFAULT_CACHE_COOKIE_FILE
        json.dump(driver.get_cookies(), open(to_file, 'w'), ensure_ascii=False, indent=2)
    
    
    def setup_cookies(driver, from_file=None):
        try:
            from_file = from_file or DEFAULT_CACHE_COOKIE_FILE
            driver.get(LOGIN_URL)
            hint('Setup cookies from file "{}"'.format(from_file))
            for cookie in json.load(open(from_file, 'r')):
                try:
                    driver.add_cookie(cookie)
                except WebDriverException:
                    pass
        except Exception:
            pass
        finally:
            return driver
    

    搜索关键词

    关键词搜索依然在 百度指数) 首页中可以看到搜索框,因此可以控制在该区域输入关键词并回车后即可得到关键词指数页面:

    image.png

    提取指数

    就目前来说,我只需要默认搜索条件下对应的整体搜索指数移动搜索指数,然后也可以得到PC 端搜搜指数 了。以下是提取整体指数的流程:

    1. 首先定位到整体指数元素:xpath(//table[contains(@class, "mtable")]//tr/td[2]//span[@class="ftlwhf enc2imgVal"][1]),如此,我们可以得到该元素对象;
    2. 获取上一步得到的元素的位置和大小(location & size):loc, size = element.location, element.size
    3. 紧接着,我们将获取当前页面的截图(这个在 Selenium 下很好做,直接 调用driver.get_screenshot_as_png 方法即可;
    4. 这一步比较关键,我们将使用 PIL 工具完成截图,截图方法如下:
    # Get the location and size of the element
    loc, size = element.location, element.size
    # Crop the element from the full screenshot
    element_image = crop_sub_image(loc, size, full_screenshot)
    
    1. 至此,我们将会得到如下类似的图片(放大了图片,实际截取的图片并没有那么大):
    image.png

    指数图片识别

    既然是数字图像识别,比较好用的开源工具自然是网上推荐的 Tesseract OCR,使用该工具识别上面的图片也非常简单:tesseract overall_index.png output.txt,然后在 output.txt 中即可看到识别的结果。

    至此,似乎已经完成任务了。但是,等等,还有一个问题没有解决,Tesseract OCR 真的在默认情况下可以准确识别各种指数?答案当然是不可以的,所以为了增加指数识别的精确度,我们需要对 Tesseract 进行训练。

    训练 Tesseract OCR

    准备工作

    在对 Tesseract OCR 进行训练之前,我们需要做如下准备工作(以 Mac 环境为例):

    1. 安装 JRE 1.8 环境,并下载 jTessBoxEditor 辅助训练工具,将在后面使用它;
    2. 安装 Tesseract 及其需要的训练工具(使用代理增加下载安装的速度):http_proxy=localhost:8118 https_proxy=localhost:8118 brew install --with-training-tools tesseract

    准备样本

    1. 为了得到更好的纠正训练数据,提前准备了一些指数图片作为样本(做了二值化处理,并放大了一定的倍数便于查看):
    image.png image.png
    1. 生成 TIFF 文件,这个使用 jTessBoxEditor 很容易做到:
      1. 打开该工具后选择菜单Tools->Merge TIFF
      2. 在弹出的对话框中选择格式为 PNG,并全选所有图片:
    image.png
    1. 将 TIFF 文件保存到相关目录下,假设名为 num.font.duindex.tif
    2. 生成 box 文件,使用命令生成 box 文件:tesseract num.font.duindex.tif num.font.duindex batch.nochop makebox,可以得到 .box 后缀的文件。

    编辑 BOX 文件

    1. 使用 JTessBoxEditorBox Editor 面板,打开上一步生成的 box 文件;
    2. 查看每一页识别的结果,如果存在问题,就一一修正,并在修正后 Save 下来,直到所有的都修正完毕为止(如下图的 7 被错误识别成了 ?,在左侧输入正确的识别结果即可):
    image.png

    训练

    1. 打开 JTessBoxEditorTrainer 面板,导入上一步修正后的 box 文件;
    2. 点击操作面板的 Run 按钮开始训练,很快即可完成训练:
    image.png
    1. 训练结束后我们可以随意挑选几张图片进行测试,使用 Validate 功能即可,此处不再演示。

    使用训练数据

    1. 上一步可以到一个 tessdata 目录,里面含有一个 digit.traineddata (文件名可能是其它的)文件;
    2. traineddata 拷贝到 /usr/local/share/tesseract/tessdata 目录下(其它系统可能在不同的目录下);
    3. 接下来,使用命令即可利用刚才训练的结果参与指数数据识别了:tesseract overall_index.png output.txt -l digit,注意,这里的 -l digit 为上一步 digit.traineddata 的文件名,然后多多测试查看效果吧。事实证明,识别准确度将会得到极大的提升,非常值得一试。

    改进指数文本识别代码

    当我们使用了训练后的数据后,识别结果的正确率将会大幅度提升,在 Python 中很容易改进先前的识别代码:

    def recognize_image_text(img):
        if img is None:
            return None
        return pytesseract.image_to_string(img, config='-l digit')
    

    重要的依赖包

    1. wttoolkit
    2. selenium
    3. pytesseract
    4. beautifulsoup4
    5. Pillow

    参考

    1. Selenium Python doc
    2. Tesseract official docs
    3. Training Tesseract
    4. firehood: Tesseract-OCR 字符识别---样本训练](http://blog.csdn.net/firehood_/article/details/8433077))
    5. Pillow: crop image
    6. rickArkin: 在Python下利用PIL实现可设定阈值的二值图像转换

    版权声明

    1. 本文由 Christopher L 发表,采用 知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议 进行许可。请确保你已了解许可协议,并在 转载 时声明。
    2. 本文固定链接:http://blog.chriscabin.com/?p=1545

    相关文章

      网友评论

        本文标题:百度指数获取踩坑小结

        本文链接:https://www.haomeiwen.com/subject/igwefxtx.html