IT星球论坛

 找回密码
 立即注册

QQ登录

只需一步,快速开始

新浪微博账号登陆

只需一步,快速开始

搜索
查看: 53|回复: 0

百度指数抓取,再用图像识别得到指数

[复制链接]

1997

主题

1

好友

1万

积分

管理员

Rank: 9Rank: 9Rank: 9

优秀会员 助人为乐 辛勤工作 技术精英 多才多艺 优秀班竹 灌水天才 星球管理 宣传大使 灌水之王 财富勋章 版主勋章 动漫勋章 勤奋会员 论坛精英 PS高手 心 8 闪游皮肤 双鱼座 8★8➹ 志愿者 乖

发表于 2017-8-9 18:06:36 |显示全部楼层
百度指数抓取,再用图像识别得到指数
前言:
土福曾说,百度指数很难抓,在淘宝上面是20块1个关键字:
哥那么叼的人怎么会被他吓到,于是乎花了零零碎碎加起来大约2天半搞定,在此鄙视一下土福
安装的库很多:
谷歌图像识别tesseract-ocr
pip3 install pillow
pip3 install pyocr
selenium2.45
Chrome47.0.2526.106 m or Firebox32.0.1
chromedriver.exe
图像识别验证码请参考我的博客:selenium用法请参考我的博客:进入百度指数需要登陆,登陆的账号密码写在文本account里面:
万能登陆代码如下:# 打开浏览器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用:# 新开一个窗口,通过执行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])    清空输入框,构造点击天数:# 清空输入框browser.find_element_by_id("schword").clear()# 写入需要搜索的百度指数browser.find_element_by_id("schword").send_keys(keyword)# 点击搜索# <input type="submit" value="" id="searchWords">browser.find_element_by_id("searchWords").click()time.sleep(2)# 最大化窗口browser.maximize_window()# 构造天数sel = int(input("查询7天请按0,30天请按1,90天请按2,半年请按3:"))day = 0if sel == 0:    day = 7elif sel == 1:    day = 30elif sel == 2:    day = 90elif sel == 3:    day = 180sel = '//a[@rel="' + str(day) + '"]'browser.find_element_by_xpath(sel).click()# 太快了time.sleep(2)天数也就是这里:
找到图形框:xoyelement = browser.find_elements_by_Css_selector("#trend rect")[2]图形框就是:
根据坐标点的不同构造偏移量:
选取7天的坐标来观察:
第一个点的横坐标为1031.66666
第二个点的横坐标为1234
所以7天两个坐标之间的差为:202.33,IT论坛的天数类似
用selenium库来模拟鼠标滑动悬浮:from selenium.webdriver.common.action_chains import ActionChainsActionChains(browser).move_to_element_with_offset(xoyelement,x_0,y_0).perform()但是这样子确定的点指出是在这个位置:
也就是矩形的左上角,这里是不会加载js显示弹出框的,所以要给横坐标+1:
x_0 = 1y_0 = 0写个按照天数的循环,让横坐标累加:# 按照选择的天数循环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自动识别之...:# <div class="imgtxt" style="margin-left:-117px;"></div>imgelement = browser.find_element_by_xpath('//div[@id="viewbox"]')并且确定这个框的大小位置:# 找到图片坐标locations = imgelement.locationprint(locations)# 找到图片大小sizes = imgelement.sizeprint(sizes)# 构造指数的位置rangle = (int(locations['x']), int(locations['y']), int(locations['x'] + sizes['width']),          int(locations['y'] + sizes['height']))
截取的图形为:
下面的思路就是:
  • 将整个屏幕截图下来
  • 打开截图用上面得到的这个坐标rangle进行裁剪
但是最后裁剪出来的是上面的那个黑框,我想要的效果是:
所以要对rangle进行计算,但是我懒,忽略了搜索词的长度,直接暴力的写成:# 构造指数的位置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的长度进行判断,长度过长会导致截图坐标出现偏差,这里实现的逻辑不难,读者自己捣鼓!后面的完整代码是:# <div class="imgtxt" style="margin-left:-117px;"></div>imgelement = browser.find_element_by_xpath('//div[@id="viewbox"]')# 找到图片坐标locations = imgelement.locationprint(locations)# 找到图片大小sizes = imgelement.sizeprint(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")但是后面发现裁剪的图片太小,识别精度太低,所以需要对图片进行扩大:# 将图片放大一倍# 原图大小73.29jpgzoom = Image.open(str(path) + ".jpg")(x, y) = jpgzoom.sizex_s = 146y_s = 58out = jpgzoom.resize((x_s, y_s), Image.ANTIALIAS)out.save(path + 'zoom.jpg', 'png', quality=95)
原图大小请 右键->属性->详细信息 查看,我的是长73像素,宽29像素
最后就是图像识别# 图像识别index = []image = Image.open(str(path) + "zoom.jpg")code = pytesseract.image_to_string(image)if code:    index.append(code)最后效果图:
代码在我的github上面:摘自:http://www.cnblogs.com/TTyb/p/6051366.html
百度指数抓取,再用图像识别得到指数
该会员没有填写今日想说内容.
您需要登录后才可以回帖 登录 | 立即注册 新浪微博账号登陆

回顶部