爬取网贷之家数据
导入相关模块
import requests
import pandas as pd
import time
from fake_useragent import UserAgent
from bs4 import BeautifulSoup
import concurrent
import random
fake_useragent模块可以模拟请求头中地useragent信息,在使用request.get函数时相当于加入了浏览器地版本信息,这样远程服务器就不会简单地认定你为爬虫了。
这里使用ua = UserAgent()来调用。
concurrent模块是多线程模块,加入多线程可以提高爬取效率,具体使用过程以后再分析~
解析网页数据
先抛代码
def scrape_detail(url):
result=pd.DataFrame(columns=['平台名称','平均利率','待还余额','注册地','上线时间','网友印象','综合评分','标签'])
time.sleep(random.uniform(0,2))
print('正在下载 : %s' %url)
headers={'User-Agent' : ua.random,
'Cookie':cookies}
data=requests.get(url,headers=headers)
soup = BeautifulSoup(data.content,'lxml')
data_list=soup.find_all('li',{'class':'item'})
for each in data_list:
item={}
item['平台名称']=each.find('h2').get_text().replace('\n','')
item['平均利率']=each.find('div',{'class':'itemConBox'}).find('em').get_text()
item['待还余额']=each.find_all('div',{'class':'itemConBox'})[1].get_text().split(':')[1]
item['注册地']=each.find_all('div',{'class':'itemConBox'})[2].get_text().split(':')[1]
item['上线时间']=each.find_all('div',{'class':'itemConBox'})[3].get_text().split(':')[1]
impression=each.find('div',{'class':'itemConBox bgBox'}).find_all('span')
impression_list=[]
for everyone in impression:
impression_list.append(everyone.get_text())
item['网友印象']=impression_list
item['综合评分']=each.find('div',{'class':'itemConBox bgBox'}).find('strong').get_text()
tag=each.find_all('div',{'class':'itemTitleTag tag'})
tag_list=[]
for everyone in tag:
tag_list.append(everyone.find('em').get_text())
item['标签']=tag_list
result=result.append(item,ignore_index=True)
return result
把爬取网页信息封装成函数,方便后面地调用。 本次我们准备爬取网贷之家中所有p2p平台(www.wdzj.com/dangan/sear…)的基础信息,首先要观察一下网页的结构,然后再进行爬取分析。
在网页中我们看到平台的信息包括平台名称、平均利率、待还余额等等,把这些都作为到result的列名称,然后用BeautifulSoup模块中的函数进行爬取。BeautifulSoup模块是常见的分析网页HTML代码结构的工具,类似的还有pyquery,两者使用方法基本相同,具体使用方法后续有时间再做解析。
构建线程池
def Myfutures(func,url_list,num_of_max_works=10):
with concurrent.futures.ThreadPoolExecutor(max_workers=num_of_max_works) as executor:
res=[executor.submit(func, i) for i in url_list]
return res
构建线程池,提高爬取效率。这里默认使用了10个线程,同时能够返回每一个线程的运行结果。
爬取运营中、停业或转型、问题平台
### 爬取运营中平台
def platform_running():
print('正在下载“运营中”的平台信息'.center(60,'='))
result=pd.DataFrame(columns=['平台名称','平均利率','待还余额','注册地','上线时间','网友印象','综合评分','标签'])
url_list=['https://www.wdzj.com/dangan/search?filter=e1&sort=1¤tPage=' + str(i) for i in range(1,14)]
for i in url_list:
data=scrape_detail(i)
result=pd.concat([result,data])
time.sleep(2)
print('“运营中”的平台信息下载完成'.center(60,'='))
return result
### 爬取停业或者转型平台
def platform_closed_or_Transformation():
print('正在下载“停业或转型”的平台信息'.center(60,'='))
result=pd.DataFrame(columns=['平台名称','平均利率','待还余额','注册地','上线时间','网友印象','综合评分','标签'])
url_list=['https://www.wdzj.com/dangan/search?filter=e2&sort=1¤tPage=' + str(i) for i in range(1,130)]
res=Myfutures(scrape_detail,url_list)
for future in concurrent.futures.as_completed(res):
data=future.result()
result=pd.concat([result,data])
print('“停业或转型”的平台信息下载完成'.center(60,'='))
return result
### 爬取问题平台
def platform_introuble():
print('正在下载“出现问题”的平台信息'.center(60,'='))
result=pd.DataFrame(columns=['平台名称','平均利率','待还余额','注册地','上线时间','网友印象','综合评分','标签'])
url_list=['https://www.wdzj.com/dangan/search?filter=e3&sort=1¤tPage=' + str(i) for i in range(1,118)]
res=Myfutures(scrape_detail,url_list)
for future in concurrent.futures.as_completed(res):
data=future.result()
result=pd.concat([result,data])
print('“出现问题”的平台信息下载完成'.center(60,'='))
return result
每一个函数中都调用了前面定义的scrape_detail函数,三个函数结构基本相同,区别是第一个函数并没有加入多线程,最后在运行代码阶段,以此来对比一下是否加入多线程对爬取效果的影响。
存储数据并运行
def save_data():
with pd.ExcelWriter(r'网贷之家1.xlsx') as writer:
sheet_list=['运营中','停业或转型','问题平台']
result=platform_running()
result.to_excel(writer,index=None,sheet_name=sheet_list[0])
result=platform_closed_or_Transformation()
result.to_excel(writer,index=None,sheet_name=sheet_list[1])
result=platform_introuble()
result.to_excel(writer,index=None,sheet_name=sheet_list[2])
if __name__ == '__main__':
save_data()
把爬取出的数据表都放入到一个excel中,表名分别为运营中,停业或转型,问题平台,开始运行,运行时间大概在2~3分钟。
全部代码如下:
# -*- coding: utf-8 -*-
"""
Created on Fri Apr 24 16:18:28 2020
@author: wangyan
"""
import requests
import pandas as pd
import time
from fake_useragent import UserAgent
from bs4 import BeautifulSoup
import concurrent
import random
cookies='JSESSIONID=65389AB324B502E2336723462331362C; __jsluid_s=6987a7bb2700b9aa213e68fb221f8a78; __jsluid_h=0b27cd8385354fa0949042062c783d67; wdzj_session_source=https%253A%252F%252Fwww.wdzj.com%252Fdangan%252Fsearch%253Ffilter%253De1%2526currentPage%253D1; WDZJptlbs=1; Hm_lvt_9e837711961994d9830dcd3f4b45f0b3=1587711532; _pk_ses.1.b30f=*; gr_user_id=7dd31ff2-6d1b-4f1e-8fd5-7d8641798352; gr_session_id_1931ea22324b4036a653ff1d3a0b4693=793a392e-21c7-46fb-861d-8c9616e94f02; gr_session_id_1931ea22324b4036a653ff1d3a0b4693_793a392e-21c7-46fb-861d-8c9616e94f02=true; _ga=GA1.2.844346962.1587711532; _gid=GA1.2.198712134.1587711532; PHPSESSID=lsf4g1044lqk8rqs8ajin318h3; Hm_lpvt_9e837711961994d9830dcd3f4b45f0b3=1587712229; _pk_id.1.b30f=3a9dbc19cb62c72c.1587711532.1.1587712229.1587711532.; _gat=1'
ua = UserAgent()
### 解析网页信息
def scrape_detail(url):
result=pd.DataFrame(columns=['平台名称','平均利率','待还余额','注册地','上线时间','网友印象','综合评分','标签'])
time.sleep(random.uniform(0,2))
print('正在下载 : %s' %url)
headers={'User-Agent' : ua.random,
'Cookie':cookies}
data=requests.get(url,headers=headers)
soup = BeautifulSoup(data.content,'lxml')
data_list=soup.find_all('li',{'class':'item'})
for each in data_list:
item={}
item['平台名称']=each.find('h2').get_text().replace('\n','')
item['平均利率']=each.find('div',{'class':'itemConBox'}).find('em').get_text()
item['待还余额']=each.find_all('div',{'class':'itemConBox'})[1].get_text().split(':')[1]
item['注册地']=each.find_all('div',{'class':'itemConBox'})[2].get_text().split(':')[1]
item['上线时间']=each.find_all('div',{'class':'itemConBox'})[3].get_text().split(':')[1]
impression=each.find('div',{'class':'itemConBox bgBox'}).find_all('span')
impression_list=[]
for everyone in impression:
impression_list.append(everyone.get_text())
item['网友印象']=impression_list
item['综合评分']=each.find('div',{'class':'itemConBox bgBox'}).find('strong').get_text()
tag=each.find_all('div',{'class':'itemTitleTag tag'})
tag_list=[]
for everyone in tag:
tag_list.append(everyone.find('em').get_text())
item['标签']=tag_list
result=result.append(item,ignore_index=True)
return result
### 构建线程池
def Myfutures(func,url_list,num_of_max_works=10):
with concurrent.futures.ThreadPoolExecutor(max_workers=num_of_max_works) as executor:
res=[executor.submit(func, i) for i in url_list]
return res
### 爬取运营中平台
def platform_running():
print('正在下载“运营中”的平台信息'.center(60,'='))
result=pd.DataFrame(columns=['平台名称','平均利率','待还余额','注册地','上线时间','网友印象','综合评分','标签'])
url_list=['https://www.wdzj.com/dangan/search?filter=e1&sort=1¤tPage=' + str(i) for i in range(1,14)]
for i in url_list:
data=scrape_detail(i)
result=pd.concat([result,data])
time.sleep(2)
print('“运营中”的平台信息下载完成'.center(60,'='))
return result
### 爬取停业或者转型平台
def platform_closed_or_Transformation():
print('正在下载“停业或转型”的平台信息'.center(60,'='))
result=pd.DataFrame(columns=['平台名称','平均利率','待还余额','注册地','上线时间','网友印象','综合评分','标签'])
url_list=['https://www.wdzj.com/dangan/search?filter=e2&sort=1¤tPage=' + str(i) for i in range(1,130)]
res=Myfutures(scrape_detail,url_list)
for future in concurrent.futures.as_completed(res):
data=future.result()
result=pd.concat([result,data])
print('“停业或转型”的平台信息下载完成'.center(60,'='))
return result
### 爬取问题平台
def platform_introuble():
print('正在下载“出现问题”的平台信息'.center(60,'='))
result=pd.DataFrame(columns=['平台名称','平均利率','待还余额','注册地','上线时间','网友印象','综合评分','标签'])
url_list=['https://www.wdzj.com/dangan/search?filter=e3&sort=1¤tPage=' + str(i) for i in range(1,118)]
res=Myfutures(scrape_detail,url_list)
for future in concurrent.futures.as_completed(res):
data=future.result()
result=pd.concat([result,data])
print('“出现问题”的平台信息下载完成'.center(60,'='))
return result
### 存储数据
def save_data():
with pd.ExcelWriter(r'网贷之家1.xlsx') as writer:
sheet_list=['运营中','停业或转型','问题平台']
result=platform_running()
result.to_excel(writer,index=None,sheet_name=sheet_list[0])
result=platform_closed_or_Transformation()
result.to_excel(writer,index=None,sheet_name=sheet_list[1])
result=platform_introuble()
result.to_excel(writer,index=None,sheet_name=sheet_list[2])
if __name__ == '__main__':
save_data()
最后,代码写的比较匆忙,也没有加入代理信息,确实有点糙,以后再改进。
python小白,不喜勿喷!