写了个脚本,用于从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
#-*- 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)
# 调用云打码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)
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
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))
# 读取需要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)
# 页面信息分析
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'无'
# 查找有无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)
print phone,state,num,company
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。