世界之大,無奇不有,各種需求也是琳琅滿目,但是古人的智慧是值得敬佩的。
事件背景:當python爬蟲時,遇到JS跳轉,cookie等操作時,會比較復雜,需要對js有較深的理解才可以進行下午,但是世界在進步,任何一件事情慢慢都會趨向於大眾化,這說起來有點想Python的誕生了,哈哈,轉回正題,基於JS較為復雜,因此有了selenium,他可以控制瀏覽器進行頁面的跳轉,以及進行登錄與注冊等一系列模擬人的行為。有了selenium之后這些就變得比較簡單,只需要對前端頁面的定位了解就差不多了,慢慢的出來了驗證碼,這就對selenium不是很友好了,雖然有着超級鷹等打碼平台,但是這是收費的,並不符合爬蟲的白嫖理念,於是也有對應的解決,頁面截圖,OCR識圖等,但這就牽扯到較為復雜的層面。於是就有了接下來的控制已有的瀏覽器,事先登陸注冊等攜帶有cookie信息的瀏覽器再進行操作,豈不美哉。
接下來呢是以企查查為原型,進行的一些列操作,控制已登錄好的企查查,進行某企業的股東、股東所占比、電話郵箱、風險事件、法人代表等信息的爬取並進行Excel的格式化存儲。其中大部分較為簡單,也可直接復制運行即可,只有一個難點,為瀏覽器的句柄,因為涉及到點擊進入新頁面所以要重新獲取句柄並得到控制權,對新頁面進行信息獲取,大部分獲取不到就是沒有得到正確的句柄,所以定位不到數據。以下為詳情代碼模塊。需要自取,歡迎討論和改進,鳥叔還在成長,希望一起進步。
#首先導入selenium以及所需要的庫
from selenium import webdriver
import time
import requests
import xlrd
from docx import Document
from docx.shared import Pt
from docx.shared import Inches
from docx.oxml.ns import qn
import os
import shutil
import docx
from docx.shared import Inches
from bs4 import BeautifulSoup
import re
import datetime
import urllib.request
from selenium.webdriver.chrome.options import Options
from selenium.webdriver.common.keys import Keys
import sys
import os
import io
import pandas as pd
import numpy as np
import re
import random
import datetime
from sqlalchemy import create_engine
# 編制獲取信息函數,傳參為公司名和chromdriver對象
def getMassage(Company,driver):
datacontent = {}
datacontent['公司名稱'] = ''
datacontent['股東名稱1'] = ''
datacontent['持股比例1'] = ''
datacontent['股東名稱2'] = ''
datacontent['持股比例2'] = ''
datacontent['股東名稱3'] = ''
datacontent['持股比例3'] = ''
datacontent['股東名稱4'] = ''
datacontent['持股比例4'] = ''
datacontent['股東名稱5'] = ''
datacontent['持股比例5'] = ''
datacontent['電話'] = ''
datacontent['郵箱'] = ''
datacontent['網址'] = ''
datacontent['法人代表'] = ''
datacontent['地址'] = ''
datacontent['注冊資本'] = ''
datacontent['成立日期'] = ''
datacontent['風險信息'] = ''
datacontent['簡介'] = ''
# 獲取當前窗口句柄
now_handle = driver.current_window_handle
# print(now_handle)
driver.find_element_by_id('headerKey').clear()
time.sleep(1)
driver.find_element_by_id('headerKey').send_keys(Company)
driver.find_element_by_xpath('//span[@class="input-group-btn"]').click()
time.sleep(1)
# driver.execute_script("window.scrollBy(0,500)")
# 法定代表人
try:
Name = driver.find_element_by_xpath('//tbody[@id="search-result"]/tr[1]/td/p[@class="m-t-xs"][1]/a')
print(Name.text)
datacontent['法人代表'] = Name.text
except:
datacontent['法人代表'] = ''
# 注冊資本
try:
Money = driver.find_elements_by_xpath('//tbody[@id="search-result"]/tr[1]/td/p[@class="m-t-xs"][1]//span')
print(str(Money[0].text).split(":")[1])
datacontent['注冊資本'] = str(Money[0].text).split(":")[1]
except:
datacontent['注冊資本'] = ''
# 成立時間
try:
print(str(Money[1].text).split(":")[1])
datacontent['成立日期'] = str(Money[1].text).split(":")[1]
except:
datacontent['成立日期'] = ''
time.sleep(1)
driver.find_element_by_xpath('//*[@id="search-result"]/tr[1]//a[@class="ma_h1"]').click()
time.sleep(2)
all_handles = driver.window_handles # 獲取所有窗口句柄
for handle in all_handles:
if handle != now_handle:
# print(handle)
driver.switch_to_window(handle)
# #公司名
company = driver.find_element_by_xpath('//h1')
print(company.text)
datacontent['公司名稱'] = company.text
#
# #聯系電話
try:
linkMan = driver.find_element_by_xpath(
'//div[@class="dcontent"]//div[@class="row"][1]//span[@class="cvlu"]/span')
print(linkMan.text)
datacontent['電話'] = linkMan.text
except:
datacontent['電話'] = ''
#
# #聯系郵箱
try:
linkEmail = driver.find_element_by_xpath(
'//div[@class="dcontent"]//div[@class="row"][2]//span[@class="cvlu"]/a[@class="text-primary"]')
print(linkEmail.text)
datacontent['郵箱'] = linkEmail.text
except:
datacontent['郵箱'] = ''
print('聯系郵箱暫無')
# 官網
try:
href = driver.find_element_by_xpath(
'//div[@class="dcontent"]//div[@class="row"][1]//a[@class="text-primary"]')
print(href.text)
datacontent['網址'] = href.text
except:
datacontent['網址'] = ""
print('官網暫無')
# #地址
try:
addres = driver.find_element_by_xpath(
'//div[@class="dcontent"]//div[@class="row"][2]/span[@class="cvlu"]/a')
print(addres.text)
datacontent['地址'] = addres.text
except:
datacontent['地址'] = ""
print('地址暫無')
try:
try:
driver.find_element_by_xpath(
'//div[@class="dcontent"]//div[@class="row"][3]//span[@class="cvlu introRetract"]/a').click()
indruce = driver.find_element_by_xpath(
'//div[@class="dcontent"]//div[@class="row"][3]//span[@class="cvlu introExpand"]')
except:
# #簡介
indruce = driver.find_element_by_xpath(
'//div[@class="dcontent"]//div[@class="row"][3]//span[@class="cvlu introRetract"]')
print(indruce.text)
datacontent['簡介'] = indruce.text
except:
datacontent['簡介'] = ''
print('簡介暫無')
# 風險
Fs = driver.find_elements_by_xpath('//div[@class="bcell"]//div[@class="cont"]//span[@class="fx2-tx"]')
for i in Fs:
datacontent['風險信息'] = datacontent['風險信息'] + str(i.text) + ";"
# 股東信息
length = len(driver.find_elements_by_xpath('//*[@id="partnerslist"]/table/tbody//tr//td[@class="tx"]'))
# print(length)
if length > 5:
length = 5
for i in range(1, 6):
if i > length:
compamy1 = '空'
precent1 = '空'
else:
company1 = driver.find_element_by_xpath(
'//*[@id="partnerslist"]/table/tbody/tr[{}]//h3'.format(i + 1))
print(company1.text)
try:
datacontent['股東名稱'+str(i)] = company1.text
except:
datacontent['股東名稱' + str(i)] = ''
try:
pat = re.compile('\d+')
precent = driver.find_element_by_xpath(
'//*[@id="partnerslist"]/table/tbody/tr[{}]//td[@class="text-center"][1]'.format(i + 1))
print(pat.findall(str(precent.text))[0] + '%')
datacontent['持股比例' + str(i)] = pat.findall(str(precent.text))[0] + '%'
except:
datacontent['持股比例' + str(i)] = ''
time.sleep(1)
driver.close()
time.sleep(1)
driver.switch_to_window(now_handle)
return datacontent
# 將數據保存至excel中
def putDataIntoExcel(dataContents, fileName):
save = pd.DataFrame(dataContents, columns=titles)
file = open(fileName, "a", encoding='utf-8')
save.to_csv(file, line_terminator="\n", index=False)
file.close()
print("鳥叔的公司完成")
if __name__ == "__main__":
titles = [
'公司名稱',
'股東名稱1',
'持股比例1',
'股東名稱2',
'持股比例2',
'股東名稱3',
'持股比例3',
'股東名稱4',
'持股比例4',
'股東名稱5',
'持股比例5',
'電話',
'郵箱',
'網址',
'法人代表',
'地址',
'注冊資本',
'成立日期',
'風險信息',
'簡介',
]
#讀取csv
data11 = pd.read_excel('./鳥叔公司類表.xlsx', encoding='gb18030')
data11 = data11.iloc[:,0]
companyList = list(data11)
print(len(companyList),companyList)
sys.stdout = io.TextIOWrapper(sys.stdout.buffer, encoding='gb18030')
#獲取瀏覽器控制權
chrome_options = Options()
chrome_options.add_experimental_option("debuggerAddress", "127.0.0.1:9222")
driver = webdriver.Chrome(chrome_options=chrome_options)
listData = []
for data1 in companyList[101:]:
print(data1)
try:
message = getMassage(data1,driver)
listData.append(message)
except:
print(data11,"沒有數據")
continue
#若數據量較大,可在此進行數據的切分爬取,避免爬取進度為百分之95時出現爬取數據上限
#但是沒有進行存儲的尷尬費事費力不討好,自測三千六百左右一個賬號就會暫時不能進行正常爬取
# putDataIntoExcel(listData, './鳥叔爬取公司.csv')
# print(len(listData),listData)
#由於data直接轉excel數據格式有報錯,此處先轉成csv格式最后變成excel,可分步進行,
# data = pd.read_csv('./鳥叔爬取公司.csv',engine='python',encoding='utf8')
# # print(data)
# data.to_excel('./鳥叔爬取公司.xlsx',index=False,encoding="gb18030")