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)
selenium+雲打碼+百度ocr爬取360的電話號碼標記
selenium+雲打碼+百度ocr爬取360的電話號碼標記
  雲打碼平臺:http://www.yundama.com/apidoc/YDM_SDK.html#demo
  百度OCR:https://ai.baidu.com/sdk#ocrhtml

  一、須要用到的模塊

#-*- 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)

  三、查詢號碼,這裏只用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

  四、有驗證碼的狀況,嘗試雲打碼

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準備工做(若是號碼有所屬公司標記,公司名稱是圖片格式,須要識別)

# 讀取須要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
相關文章
相關標籤/搜索