时间:2021-07-01 10:21:17 帮助过:65人阅读
百度指数抓取,再用图像识别得到指数
前言:
土福曾说,百度指数很难抓,在淘宝上面是20块1个关键字:
哥那么叼的人怎么会被他吓到,于是乎花了零零碎碎加起来大约2天半搞定,在此鄙视一下土福
安装的库很多:
- 谷歌图像识别tesseract-ocr
- pip3 install pillow
- pip3 install pyocr
- selenium2.45
- Chrome47.0.2526.106 m or Firebox32.0.1
- chromedriver.exe
进入百度指数需要登陆,登陆的账号密码写在文本account里面:
万能登陆代码如下:
- # 打开浏览器
- def openbrowser():
- global browser
- # http://www.gxlcms.com/
- 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" 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)
天数也就是这里:
找到图形框:
- xoyelement = browser.find_elements_by_css_selector("#trend rect")[2]
图形框就是:
根据坐标点的不同构造偏移量:
选取7天的坐标来观察:
第一个点的横坐标为1031.66666
第二个点的横坐标为1234
所以7天两个坐标之间的差为:202.33,其他的天数类似
用selenium库来模拟鼠标滑动悬浮:
- from selenium.webdriver.common.action_chains import ActionChains
- ActionChains(browser).move_to_element_with_offset(xoyelement,x_0,y_0).perform()
但是这样子确定的点指出是在这个位置:
也就是矩形的左上角,这里是不会加载js显示弹出框的,所以要给横坐标+1:
- x_0 = 1
- y_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自动识别之...:
- # <p class="imgtxt" style="margin-left:-117px;"></p>
- imgelement = browser.find_element_by_xpath('//p[@id="viewbox"]')
并且确定这个框的大小位置:
- # 找到图片坐标
- 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进行计算,但是我懒,忽略了搜索词的长度,直接暴力的写成:
- # 构造指数的位置
- 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的长度进行判断,长度过长会导致截图坐标出现偏差,反正我知道怎么做,就是不写出来给你们看!
后面的完整代码是:
- # <p class="imgtxt" style="margin-left:-117px;"></p>
- imgelement = browser.find_element_by_xpath('//p[@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")
但是后面发现裁剪的图片太小,识别精度太低,所以需要对图片进行扩大:
- # 将图片放大一倍
- # 原图大小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像素
最后就是图像识别
- # 图像识别
- index = []
- image = Image.open(str(path) + "zoom.jpg")
- code = pytesseract.image_to_string(image)
- if code:
- index.append(code)
最后效果图:
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持PHP中文网。
更多详解python3百度指数抓取实例相关文章请关注PHP中文网!