Об источниках данных
Проект был написан в начале июля 2017 года, в основном с использованием Python, сканирующего чистую ипотечную ссуду, а также все данные для анализа. Чистая ссуда дома является крупнейшей платформой данных P2P для всех двадцати крупнейших кредитных платформ Китая P2P.Адрес источника
парсинг данных
Анализ захвата пакетов
Инструмент захвата пакетов в основном использует сетевой столбец инструмента разработчика Chrome.Все данные Net Loan Home представляют собой данные json, возвращаемые ajax, в то время как Renrendai имеет как возвращаемые данные ajax, так и html-страницу для прямого генерирования данных.
экземпляр запроса
Из данных можно увидеть способ запроса данных (GET или POST), заголовки запроса и параметры запроса.Из данных запроса вы можете увидеть формат возвращаемых данных (в этом примере json), структуру данных и конкретные данные. Примечание. Это интерфейс серверной части запроса API Net Loan Home. Когда сканер был написан, интерфейс данных отличался от текущего интерфейса запроса, поэтому часть сканера данных Net Loan Home недействительна.Запрос на строительство
Сформировать запрос на основе результатов анализа перехвата пакетов. В этом проекте используйте библиотеку запросов Python для имитации http-запросов. Конкретный код:
import requests
class SessionUtil():
def __init__(self,headers=None,cookie=None):
self.session=requests.Session()
if headers is None:
headersStr={"Accept":"application/json, text/javascript, */*; q=0.01",
"X-Requested-With":"XMLHttpRequest",
"User-Agent":"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/57.0.2987.133 Safari/537.36",
"Accept-Encoding":"gzip, deflate, sdch, br",
"Accept-Language":"zh-CN,zh;q=0.8"
}
self.headers=headersStr
else:
self.headers=headers
self.cookie=cookie
//发送get请求
def getReq(self,url):
return self.session.get(url,headers=self.headers).text
def addCookie(self,cookie):
self.headers['cookie']=cookie
//发送post请求
def postReq(self,url,param):
return self.session.post(url, param).text
При настройке заголовка запроса в поле ключа устанавливается только «User-Agent», а для Wangdaijia и Renrendai мер против сканирования нет, и даже поле «Referer» не нужно устанавливать для предотвращения междоменного ошибки.
Экземпляр сканера
Ниже приведен пример обходчика
import json
import time
from databaseUtil import DatabaseUtil
from sessionUtil import SessionUtil
from dictUtil import DictUtil
from logUtil import LogUtil
import traceback
def handleData(returnStr):
jsonData=json.loads(returnStr)
platData=jsonData.get('data').get('platOuterVo')
return platData
def storeData(jsonOne,conn,cur,platId):
actualCapital=jsonOne.get('actualCapital')
aliasName=jsonOne.get('aliasName')
association=jsonOne.get('association')
associationDetail=jsonOne.get('associationDetail')
autoBid=jsonOne.get('autoBid')
autoBidCode=jsonOne.get('autoBidCode')
bankCapital=jsonOne.get('bankCapital')
bankFunds=jsonOne.get('bankFunds')
bidSecurity=jsonOne.get('bidSecurity')
bindingFlag=jsonOne.get('bindingFlag')
businessType=jsonOne.get('businessType')
companyName=jsonOne.get('companyName')
credit=jsonOne.get('credit')
creditLevel=jsonOne.get('creditLevel')
delayScore=jsonOne.get('delayScore')
delayScoreDetail=jsonOne.get('delayScoreDetail')
displayFlg=jsonOne.get('displayFlg')
drawScore=jsonOne.get('drawScore')
drawScoreDetail=jsonOne.get('drawScoreDetail')
equityVoList=jsonOne.get('equityVoList')
experienceScore=jsonOne.get('experienceScore')
experienceScoreDetail=jsonOne.get('experienceScoreDetail')
fundCapital=jsonOne.get('fundCapital')
gjlhhFlag=jsonOne.get('gjlhhFlag')
gjlhhTime=jsonOne.get('gjlhhTime')
gruarantee=jsonOne.get('gruarantee')
inspection=jsonOne.get('inspection')
juridicalPerson=jsonOne.get('juridicalPerson')
locationArea=jsonOne.get('locationArea')
locationAreaName=jsonOne.get('locationAreaName')
locationCity=jsonOne.get('locationCity')
locationCityName=jsonOne.get('locationCityName')
manageExpense=jsonOne.get('manageExpense')
manageExpenseDetail=jsonOne.get('manageExpenseDetail')
newTrustCreditor=jsonOne.get('newTrustCreditor')
newTrustCreditorCode=jsonOne.get('newTrustCreditorCode')
officeAddress=jsonOne.get('officeAddress')
onlineDate=jsonOne.get('onlineDate')
payment=jsonOne.get('payment')
paymode=jsonOne.get('paymode')
platBackground=jsonOne.get('platBackground')
platBackgroundDetail=jsonOne.get('platBackgroundDetail')
platBackgroundDetailExpand=jsonOne.get('platBackgroundDetailExpand')
platBackgroundExpand=jsonOne.get('platBackgroundExpand')
platEarnings=jsonOne.get('platEarnings')
platEarningsCode=jsonOne.get('platEarningsCode')
platName=jsonOne.get('platName')
platStatus=jsonOne.get('platStatus')
platUrl=jsonOne.get('platUrl')
problem=jsonOne.get('problem')
problemTime=jsonOne.get('problemTime')
recordId=jsonOne.get('recordId')
recordLicId=jsonOne.get('recordLicId')
registeredCapital=jsonOne.get('registeredCapital')
riskCapital=jsonOne.get('riskCapital')
riskFunds=jsonOne.get('riskFunds')
riskReserve=jsonOne.get('riskReserve')
riskcontrol=jsonOne.get('riskcontrol')
securityModel=jsonOne.get('securityModel')
securityModelCode=jsonOne.get('securityModelCode')
securityModelOther=jsonOne.get('securityModelOther')
serviceScore=jsonOne.get('serviceScore')
serviceScoreDetail=jsonOne.get('serviceScoreDetail')
startInvestmentAmout=jsonOne.get('startInvestmentAmout')
term=jsonOne.get('term')
termCodes=jsonOne.get('termCodes')
termWeight=jsonOne.get('termWeight')
transferExpense=jsonOne.get('transferExpense')
transferExpenseDetail=jsonOne.get('transferExpenseDetail')
trustCapital=jsonOne.get('trustCapital')
trustCreditor=jsonOne.get('trustCreditor')
trustCreditorMonth=jsonOne.get('trustCreditorMonth')
trustFunds=jsonOne.get('trustFunds')
tzjPj=jsonOne.get('tzjPj')
vipExpense=jsonOne.get('vipExpense')
withTzj=jsonOne.get('withTzj')
withdrawExpense=jsonOne.get('withdrawExpense')
sql='insert into problemPlatDetail (actualCapital,aliasName,association,associationDetail,autoBid,autoBidCode,bankCapital,bankFunds,bidSecurity,bindingFlag,businessType,companyName,credit,creditLevel,delayScore,delayScoreDetail,displayFlg,drawScore,drawScoreDetail,equityVoList,experienceScore,experienceScoreDetail,fundCapital,gjlhhFlag,gjlhhTime,gruarantee,inspection,juridicalPerson,locationArea,locationAreaName,locationCity,locationCityName,manageExpense,manageExpenseDetail,newTrustCreditor,newTrustCreditorCode,officeAddress,onlineDate,payment,paymode,platBackground,platBackgroundDetail,platBackgroundDetailExpand,platBackgroundExpand,platEarnings,platEarningsCode,platName,platStatus,platUrl,problem,problemTime,recordId,recordLicId,registeredCapital,riskCapital,riskFunds,riskReserve,riskcontrol,securityModel,securityModelCode,securityModelOther,serviceScore,serviceScoreDetail,startInvestmentAmout,term,termCodes,termWeight,transferExpense,transferExpenseDetail,trustCapital,trustCreditor,trustCreditorMonth,trustFunds,tzjPj,vipExpense,withTzj,withdrawExpense,platId) values ("'+actualCapital+'","'+aliasName+'","'+association+'","'+associationDetail+'","'+autoBid+'","'+autoBidCode+'","'+bankCapital+'","'+bankFunds+'","'+bidSecurity+'","'+bindingFlag+'","'+businessType+'","'+companyName+'","'+credit+'","'+creditLevel+'","'+delayScore+'","'+delayScoreDetail+'","'+displayFlg+'","'+drawScore+'","'+drawScoreDetail+'","'+equityVoList+'","'+experienceScore+'","'+experienceScoreDetail+'","'+fundCapital+'","'+gjlhhFlag+'","'+gjlhhTime+'","'+gruarantee+'","'+inspection+'","'+juridicalPerson+'","'+locationArea+'","'+locationAreaName+'","'+locationCity+'","'+locationCityName+'","'+manageExpense+'","'+manageExpenseDetail+'","'+newTrustCreditor+'","'+newTrustCreditorCode+'","'+officeAddress+'","'+onlineDate+'","'+payment+'","'+paymode+'","'+platBackground+'","'+platBackgroundDetail+'","'+platBackgroundDetailExpand+'","'+platBackgroundExpand+'","'+platEarnings+'","'+platEarningsCode+'","'+platName+'","'+platStatus+'","'+platUrl+'","'+problem+'","'+problemTime+'","'+recordId+'","'+recordLicId+'","'+registeredCapital+'","'+riskCapital+'","'+riskFunds+'","'+riskReserve+'","'+riskcontrol+'","'+securityModel+'","'+securityModelCode+'","'+securityModelOther+'","'+serviceScore+'","'+serviceScoreDetail+'","'+startInvestmentAmout+'","'+term+'","'+termCodes+'","'+termWeight+'","'+transferExpense+'","'+transferExpenseDetail+'","'+trustCapital+'","'+trustCreditor+'","'+trustCreditorMonth+'","'+trustFunds+'","'+tzjPj+'","'+vipExpense+'","'+withTzj+'","'+withdrawExpense+'","'+platId+'")'
cur.execute(sql)
conn.commit()
conn,cur=DatabaseUtil().getConn()
session=SessionUtil()
logUtil=LogUtil("problemPlatDetail.log")
cur.execute('select platId from problemPlat')
data=cur.fetchall()
print(data)
mylist=list()
print(data)
for i in range(0,len(data)):
platId=str(data[i].get('platId'))
mylist.append(platId)
print mylist
for i in mylist:
url='http://wwwservice.wdzj.com/api/plat/platData30Days?platId='+i
try:
data=session.getReq(url)
platData=handleData(data)
dictObject=DictUtil(platData)
storeData(dictObject,conn,cur,i)
except Exception,e:
traceback.print_exc()
cur.close()
conn.close
На протяжении всего процесса мы конструируем запрос, а затем разбираем ответ каждого запроса, в котором возвращаемое значение json анализируется с помощью библиотеки json, а html-страница — с помощью библиотеки BeautifulSoup (html-страница со сложной структурой — рекомендуется использовать библиотеку lxml для разбора), анализируется до Результаты сохраняются в базе данных mysql.
Код рептилии
Кодовый адрес сканера(Примечание: код сканера может запускаться как на Python2, так и на python3. Я развертываю код сканера на сервере Alibaba Cloud и запускаю его с помощью Python2)
анализ данных
Анализ данных в основном использует Python numpy, pandas и matplotlib для анализа данных, дополненный Haizhi BDP.
анализ временных рядов
чтение данных
Как правило, данные считываются в DataFrame панд для анализа. Ниже приведен пример чтения данных с проблемной платформы.
problemPlat=pd.read_csv('problemPlat.csv',parse_dates=True)#问题平台
структура данных
анализ временных рядов
например, количество проблемных платформ меняется со временем
problemPlat['id']['2012':'2017'].resample('M',how='count').plot(title='P2P发生问题')#发生问题P2P平台数量 随时间变化趋势
Графический дисплей
Географический анализ
В комплекте с Haizhi BDP (Python сложнее рисовать колеса раздачи карт, и я его еще не изучил)
Количество проблемных платформ в каждой провинции
Оборот платформы по провинциям
Анализ распределения размеров
Например, распределение оборота платформы по стране в июне код
juneData['amount'].hist(normed=True)
juneData['amount'].plot(kind='kde',style='k--')#六月份交易量概率分布
Графическое отображение ядерной плотности
Возьмем логарифмическое ядро распределения плотности оборотаnp.log10(juneData['amount']).hist(normed=True)
np.log10(juneData['amount']).plot(kind='kde',style='k--')#取 10 对数的 概率分布
Графический дисплей
Можно видеть, что после логарифмирования 10 распределение больше соответствует нормальной форме пирамиды.Корреляционный анализ
Например, тенденция изменения коэффициента корреляции между объемом транзакций Lufax и объемом транзакций на всех платформах.
lujinData=platVolume[platVolume['wdzjPlatId']==59]
corr=pd.rolling_corr(lujinData['amount'],allPlatDayData['amount'],50,min_periods=50).plot(title='陆金所交易额与所有平台交易额的相关系数变化趋势')
Графический дисплей
Сравнение классификации
Сравнение данных об объеме транзакций между платформой автокредитования и всей платформой
carFinanceDayData=carFinanceData.resample('D').sum()['amount']
fig,axes=plt.subplots(nrows=1,ncols=2,sharey=True,figsize=(14,7))
carFinanceDayData.plot(ax=axes[0],title='车贷平台交易额')
allPlatDayData['amount'].plot(ax=axes[1],title='所有p2p平台交易额')
Прогноз тренда
Например, предсказать тренд объема торгов Lufax (с помощью библиотеки Facebook Prophet)
lujinAmount=platVolume[platVolume['wdzjPlatId']==59]
lujinAmount['y']=lujinAmount['amount']
lujinAmount['ds']=lujinAmount['date']
m=Prophet(yearly_seasonality=True)
m.fit(lujinAmount)
future=m.make_future_dataframe(periods=365)
forecast=m.predict(future)
m.plot(forecast)
Графическое отображение прогноза тренда
код анализа данных
Кодовый адрес анализа данных(Примечание: код анализа данных интеллектуально работает в среде Python3)Пример после запуска кода(Вы также можете просмотреть конкретное кодовое решение в графическом виде, не устанавливая среду Python)
постскриптум
Это первый проект, который я написал после того, как переключился с веб-сайта на Java на направление данных, а также это мой первый проект на Python.Во время всего процесса я не столкнулся со многими подводными камнями.В общем, краулер и анализ данных и языковые барьеры Python очень низкий. Если вы хотите начать работу с поисковым роботом Python, порекомендуйте «Сбор сетевых данных Python».
Начало работы с Python, если вы хотите проанализировать данные, он рекомендовал «Использование Python для анализа данных».