selenium+云打码+百度ocr爬取360的电话号码标记
??写了个脚本,用于从www.so.com 上查询电话号码的标记情况,记录下号码所属公司、标记类型、标记人数(如果存在)。如下图红框中的信息。主要使用python的beautifulsoup和selenium,还用到了云打码平台(固定ip频繁查询后会被360要求输入验证码,需要收费,1分钱1个码)和百度OCR(360的查询结果中,所属公司是图片形式,因此需要文字识别,每天50000张以下免费)。约4-8秒处理一个号码,只能单进程(多进程啥的无意义,毕竟固定ip只有一个)。我们用来处理9000个号码,0点开始,大约10点结束。(python3.7.2)
??云打码平台:http://www.yundama.com/apidoc/YDM_SDK.html#demo
??百度OCR:https://ai.baidu.com/sdk#ocr
??1、需要用到的模块
#-*- coding: UTF-8 -*- import sys import time import os import re import random import base64 #百度ocr模块 from aip import AipOcr import datetime from ctypes import * from selenium import webdriver from pyquery import PyQuery as pq from bs4 import BeautifulSoup from selenium.webdriver.common.keys import Keys from selenium.webdriver.common.action_chains import ActionChains default_encoding = 'utf-8' if sys.getdefaultencoding() != default_encoding: reload(sys) sys.setdefaultencoding(default_encoding)
??2、准备工作
# 调用云打码api,需要提供账号id、api key、用户名、密码、识别类型、超时时间 # 注意指定云打码的dll文件路径 YDMApi = windll.LoadLibrary('C:\\phone\\yundamaAPI-x64.dll') appId = 账号id appKey = b'api key' username = b'用户名' password = b'密码' # 1004表示识别类型是4个字母或数字 codetype = 1004 timeout = 60 # 使用selenium chrome_options = webdriver.ChromeOptions() # 使用最高权限模式,并使用无图形化界面模式 chrome_options.add_argument("--no-sandbox") chrome_options.add_argument('--headless') browser=webdriver.Chrome(chrome_options=chrome_options) # 窗口最大化,无图形化模式下不用 browser.maximize_window() # 先打开360的查询页面 url='https://www.so.com/s?q=021' browser.get(url)
??3、查询号码,这里只用1个号码举例,批量查询可以用循环
phone=号码 # 中间有些sleep是为了保证运行不出错,可以适当再调快 try: # 定位搜索框控件 sousuokuang=browser.find_element_by_id("keyword") time.sleep(0.5) # 搜索框清空 sousuokuang.clear() time.sleep(0.5) # 输入号码 sousuokuang.send_keys(phone) time.sleep(0.5) # 点击搜索按钮 browser.find_element_by_id("su").submit() time.sleep(random.uniform(0.5,1.3)) # 试图定位验证码控件,如果定位失败,进入except,如果定位成功(说明有验证码),则进入else yanzhengma=browser.find_element_by_id("img") except: # 没有验证码,查询成功,进入结果页面 pass
??4、有验证码的情况,尝试云打码
else: # 如果有验证码,先点击验证码图片(图片要先点击一次才会显示验证码) time.sleep(0.3) ActionChains(browser).click(yanzhengma).perform() time.sleep(0.3) # 将验证码图片保存到本地(号码.png) yanzhengma.screenshot("c:\\phone\\%s.png" % phone) # 进行云打码(参考云打码文档) result = c_char_p(b" ") filename = b'C:\\phone\\%s.png' % phone.encode('gbk') captchaId = YDMApi.YDM_EasyDecodeByPath(username, password, appId, appKey, filename, codetype, timeout, result) # 验证码数据解码获取 shuruma=(result.value).decode('gbk') # 定位验证码输入框 shurukuang=browser.find_element_by_name("rcode") time.sleep(0.3) # 输入验证码并点击按钮 shurukuang.send_keys(shuruma) time.sleep(0.3) browser.find_element_by_class_name("btn").submit() # 删除验证码图片 os.remove('c:\\phone\\%s.png' % phone) finally: # 读取网页内容并初始化 html=browser.page_source data=str(pq(html))
??5、百度OCR准备工作(如果号码有所属公司标记,公司名称是图片格式,需要识别)
# 读取需要ocr识别的图片 def get_file_content(filePath): with open(filePath, 'rb') as fp: return fp.read() # 百度ocr需要有appid、apikey、秘钥,调用函数 APP_ID = 'appid' API_KEY = 'API key' SECRET_KEY = '秘钥' client = AipOcr(APP_ID, API_KEY, SECRET_KEY)
??6、网页内容解析,找出标记类型和标记数量
# 页面信息分析 soup = BeautifulSoup(data,"lxml") # 查找class名为mohe-tips的div标签 soup_div=soup.find('div',{'class':"mohe-tips"}) # 如果有mohe-tips if soup_div!=None: # 进一层查找span标签 soup_spans=soup_div.findAll('span') # 如果有2个span标签(有标记的号码,正常情况都是2个span) if len(soup_spans)==2: # 第1个span是号码标记(骚扰电话、房产中介等,用state变量) state=soup_spans[0].getText().replace('\t','').replace('\n','').replace(' ','') # 第2个span是标记数,有的号码可能没有,就标为0(用num变量) try: num=soup_spans[1].find('b').getText() except: num=0 else: pass # 如果进一层查找结果span标签有1个(第一种特殊情况) else: # 重新查找class名为mohe-tips mh-ws-hy的div标签 soup_div=soup.find('div',{'class':"mohe-tips mh-ws-hy"}) # 如果查找结果不为空 if soup_div!=None: # 再进一层查找span标签 soup_spans=soup_div.findAll('span') # 第1个span是号码标记 state=soup_spans[0].getText().replace('\t','').replace('\n','').replace(' ','') # 第2个span是标记数,有的号码可能没有,就标为0 try: num=soup_spans[1].find('b').getText() except: num=0 else: pass # 如果进一层查找结果为空,则表示该号码无标记 else: num=u'0' state=u'无' # 如果没有mohe-tips标签,第二种特殊情况 else: # 直接查找class名为mohe-tips mh-ws-hy的div标签 soup_div=soup.find('div',{'class':"mohe-tips mh-ws-hy"}) # 如果查找结果不为空 if soup_div!=None: # 进一层查找span标签 soup_spans=soup_div.findAll('span') # 第1个span是号码标记 state=soup_spans[0].getText().replace('\t','').replace('\n','').replace(' ','') # 第2个span是标记数,有的号码可能没有,就标为0 try: num=soup_spans[1].find('b').getText() except: num=0 else: pass #如果进一层查找结果为空,则表示该号码无标记 else: num=u'0' state=u'无'
??7、网页内容解析,识别所属公司
# 查找有无class名为mh-hy-img的img控件 soup_img=soup.find('img',{'class':"mh-hy-img"}) try: # 尝试把img控件的前缀'data:image/png;base64,'给删除 img_src=soup_img.get("src").replace('data:image/png;base64,','') except: # 如果删除失败,就表示没有所属公司标记,就标记为无(用company变量) company=u'无' else: # 如果有img控件,就把图片保存到本地 f = open('c:\\phone\\%s.png' % phone,'wb') f.write(base64.b64decode(img_src)) f.close() # 读取本地图片,通过百度ocr识别,并把图片删除 image = get_file_content('c:\\phone\\%s.png' % phone) company=client.basicGeneral(image)['words_result'][0]['words'] os.remove('c:\\phone\\%s.png' % phone) # 在没有mh-hy-img的img控件情况下,有一种特殊情况 if soup_img==None: # 查找有无class名为mohe-tips mh-hy的strong控件 soup_strong=soup.find('strong',{'class':"mohe-tips mh-hy"}) try: # 进一步查找有无img控件 soup_img=soup_strong.find('img') img_src=soup_img.get("src").replace('data:image/png;base64,','') except: # 如果没有img控件,公司标记为无 company=u'无' else: # 有img控件,就把图片识别处理并删除 f = open('c:\\phone\\%s.png' % phone,'wb') f.write(base64.b64decode(img_src)) f.close() image = get_file_content('c:\\phone\\%s.png' % phone) company=client.basicGeneral(image)['words_result'][0]['words'] os.remove('c:\\phone\\%s.png' % phone)
??8、输出结果
print phone,state,num,company
相关推荐
xiangxiaojun 2020-09-23
letheashura 2020-08-14
王练 2020-07-18
xiangxiaojun 2020-06-25
Feastaw 2020-06-18
云之高水之远 2020-06-14
Reiki 2020-06-12
songerxing 2020-06-11
王练 2020-06-11
tiankele0 2020-06-09
云之高水之远 2020-06-05
Reiki 2020-08-16
tiankele0 2020-07-29
curiousL 2020-07-18
tiankele0 2020-07-18
amei0 2020-07-08