Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

百度指数-图像识别抓取,逻辑不难,代码写得渣渣

Notifications You must be signed in to change notification settings

sobeited/Baiduindex

Folders and files

NameName
Last commit message
Last commit date

Latest commit

History

13 Commits

Repository files navigation

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

前言:

土福曾说,百度指数很难抓,在淘宝上面是20块1个关键字:

哥那么叼的人怎么会被他吓到,于是乎花了零零碎碎加起来大约2天半搞定,在此鄙视一下土福

安装的库很多:

谷歌图像识别tesseract-ocr

pip3 install pillow

pip3 install pyocr

selenium2.45

Chrome47.0.2526.106 m or Firebox32.0.1

chromedriver.exe

图像识别验证码请参考我的博客:

python图像识别--验证码

selenium用法请参考我的博客:

python之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" 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自动识别之...:

# <div class="imgtxt" style="margin-left:-117px;"></div>
imgelement = browser.find_element_by_xpath('//div[@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的长度进行判断,长度过长会导致截图坐标出现偏差,这里实现的逻辑不难,读者自己捣鼓!

后面的完整代码是:

# <div class="imgtxt" style="margin-left:-117px;"></div>
imgelement = browser.find_element_by_xpath('//div[@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)

最后效果图:

详细解说请观看我的博客:

TTyb

About

百度指数-图像识别抓取,逻辑不难,代码写得渣渣

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages

  • Python 100.0%

AltStyle によって変換されたページ (->オリジナル) /