python 使用BeautifulSoup爬取天天基金网主要数据

前言:最近基金火热,此代码仅供学习娱乐,本人初学python,代码还有不少问题,鉴于能力有限,无法解决,希望各位大神多多指教。

目标:抓取编号,基本信息,评级, 夏普率等数据

所用模块:requests库,BeautifulSoup,re正则,协程模块,csv等

编写思路:requests库获取信息
BeautifulSoup和re正则清洗所需数据
csv 用于存储数据
time 计时与延时
gevent协程提速

话不多说,直接上代码

import requests
import csv
from bs4 import BeautifulSoup
import re
import gevent
from gevent import monkey
import time
from gevent.queue import Queue
listtask=[]                                                                                                             #协程工作列表
listallxiap2=['--','--']                                                                                                #空列表用于补充xiapu
fundcode_list = []                                                                                                      #编号列表
fundcodeurl_list2= []                                                                                                   #fund网址
fundcodexiapu_list=[]                                                                                                   #xiapu指标网址
grade_list = []                                                                                                         #fund总信息列表
grade_list1 = []                                                                                                        #写入列表存fund基本信息
grade_list2 = []                                                                                                        #写入列表存fund评价
grade_list3 = []                                                                                                        #写入列表存fundxiap
grade_list4 = []                                                                                                        #写入列表存fund编码
keypointfund_list=[]                                                                                                    #fund信息列列表
xpandbzc_list=[]                                                                                                        #xiapu和bzc信息列表
xpandbzc_list2=[]                                                                                                       #xiapu总列表
sevengrade_list=[]                                                                                                      #存评级
headers = {"Referer": "http://fund.eastmoney.com/fund.html",
           "User-Agent": "                            "
           }                                                                                                            		#伪装代码,根据自己的ip进行添加
work = Queue()
def fundcode(p,e):                                                                                                        #函数(funds的网站)
    res_funds=requests.get('http://fund.eastmoney.com/allfund.html',headers=headers)                                    #获取网站
    bs_funds=BeautifulSoup(res_funds.text.encode('ISO-8859-1').decode('gb18030'),'html.parser')                         #解析网站
    number_funds1=bs_funds.find('div',class_="data-list m_b").find_all('li')                                            #找funds编码路径
    for number_funds2 in number_funds1:
        number_funds3=number_funds2.find('a')
        number_funds5=str(number_funds3)
        r1 = re.findall('\d+', number_funds5)                                                                           #正则找编码
        fundcode_list.append(r1)
    fundcode_list5 = [x for x in fundcode_list if x != []]                                                              #删除空列表
    print(len(fundcode_list5))
    for i in range(p):                                                                                                  # 依次取出列表中fund编号
        try:
            number_funds3 =fundcode_list5[i+e][0]                                                     # 取出列表内的编号6500为一组,funds总数/2
            grade_list4.append(str(number_funds3))
            #print(str(number_funds3))
            url = 'http://fund.eastmoney.com/' + number_funds3 + '.html'                                                    #各个fund基本信息的网址
            xiapuurl='http://fundf10.eastmoney.com/tsdata_'+number_funds3+'.html'                                           #xiapu等信息的网址
            fundcodexiapu_list.append(xiapuurl)                                                                             #xiapu和bzc的信息网址存进列表
            fundcodeurl_list2.append(url)                                                                                   #单个fund的网址
        except IndexError:
            print("无数据")
    for s in range(p):
        try:
            fundcodeurl = fundcodeurl_list2[s]                                                                              # 从fundurl列表中提取网址
            xiapuurl1 = fundcodexiapu_list[s]                                                                               # 从fundxiapu列表中提取网址
            work.put_nowait(fundcodeurl)
            work.put_nowait(xiapuurl1)
        except IndexError:
            print("无数据")
    with open('D://python//items1//items//ttjj//ttjjbianhao.csv', 'w', encoding='utf-8-sig',newline='') as tt:          #打开新csv
        writer = csv.writer(tt)
        header = ['FUND编号']
        writer.writerow(header)
        writer.writerows(grade_list4)                                                                                   #写入编码进csv(编码有bug,会写入3遍)
    return
def fundall(p):
        for s in range(p):                                                                                              #设置网址个数
            time.sleep(1)
            fundcodeurl=fundcodeurl_list2[s]                                                                            #从fundurl列表中提取网址
            xiapuurl1=fundcodexiapu_list[s]                                                                             #从fundxiapu列表中提取网址
            headers1 = {"Referer": "http://fund.eastmoney.com/"+"str(number_funds3)"+".html",
                       "User-Agent": "                             "
                       }
                           #伪装代码,根据自己的ip进行添加
            headers2 = {"Referer": "http://fund.eastmoney.com/tsdata_"+"str(number_funds3)"+".html",
                       "User-Agent": "                                      "
                       }
                   #伪装代码,根据自己的ip进行添加
            fundcodeurl=work.get_nowait()
            xiapuurl1=work.get_nowait()
            print(fundcodeurl)
            print(xiapuurl1)
            res_fundcodeurl=requests.get(fundcodeurl,headers=headers1)                                                   #基本信息网址代码
            bs_fundcodeurl=BeautifulSoup(res_fundcodeurl.text.encode('ISO-8859-1').decode('utf-8'),'html.parser')       #清洗代码
            number_grade=bs_fundcodeurl.find('li',class_="increaseAmount")                                              #未处理的基本信息
            fundscale0= bs_fundcodeurl.find('div',class_="infoOfFund")                                                  #同上
            res_xiapufundurl=requests.get(xiapuurl1,headers=headers2)                                                    #获取xiapu网址信息代码
            bs_xiapufindurl=BeautifulSoup(res_xiapufundurl.text,'html.parser')                                          #清洗代码
            xia1=bs_xiapufindurl.find('div',class_="box").find_all("tr")                                                #获取未处理的xia的信息
            for m in range(6):
                fundscale1=fundscale0.find_all('td')[m].text                                                            #获取基本的信息
                keypointfund_list.append(fundscale1)                                                                    #信息添加进基本信息列表
            for number_grade1 in number_grade:
                sevengrade=number_grade1.find_all('h3')                                                                 #获得需要的评级
                #print(sevengrade)
                for f in range(8):
                    sevengrade2=sevengrade[f].text.replace("<h3>",' ')
                    sevengrade3=sevengrade2.replace("</h3>",' ')
                    #print(sevengrade3)
                    sevengrade_list.append(sevengrade3)
                #print(sevengrade_list)
            for xia2 in xia1:
                for k in range(2):
                    xia3=xia2.find_all(class_="num")[k].text                                                            #获得xia的信息
                    xpandbzc_list.append(xia3)                                                                          #将xia的信息存进xia的列表
            xpandbzc_list2.append(xpandbzc_list)
            #print(len(xpandbzc_list2[s]))
            print(((len(xpandbzc_list2[s]))+2)/8)
            if (len(xpandbzc_list2[s])<8*(s+1)):
                xpandbzc_list2[s].extend(listallxiap2)
            else:
                pass
def open1():
    with open('D://python//items1//items//ttjj//ttjj1.csv','w',encoding='utf-8-sig',newline='') as tt:                       #打开csv存基本信息
        writer=csv.writer(tt)
        header=['基金类型','基金规模','基金经理','成 立 日','管 理 人','基金评级']
        writer.writerow(header)
        for t in range(int(q)):
            a=int(6*t)
            b=int (6*t+6)
            keypo1=keypointfund_list[a:b]
            grade_list1.append(keypo1)
        writer.writerows(grade_list1)
    return
def open2():
    with open('D://python//items1//items//ttjj//ttjj2.csv','w',encoding='utf-8-sig',newline='') as tt:
        writer=csv.writer(tt)
        header=['近一周','近一月','近三月','近六月','今年来','近一年','近两年','今年来']
        writer.writerow(header)
        for t in range(8):
            seve=sevengrade_list[t]
            grade_list2.append(seve)
        writer.writerow(grade_list2)
    return
def open3():
    with open('D://python//items1//items//ttjj//ttjj3.csv','w',encoding='utf-8-sig',newline='') as tt:
        writer=csv.writer(tt)
        header=[' ','','标准差(近一年)','标准差(近两年)','夏普率(近一年)','夏普率(近两年)','信息比率(近一年)','信息比率(近两年)']
        writer.writerow(header)
        for t in range(int(q)):
            a=int(8*t)
            b=int(8*t+8)
            fundcodexiap=xpandbzc_list2[t][a:b]
            grade_list3.append(fundcodexiap)
        writer.writerows(grade_list3)
    return


start = time.time()
q=input("请输入总数funds个数:")
e=input("请输入已抓取的总数:")#因为没有ip代理池,避免封ip,采取多次抓取数据


fundcode(int(q),int(e))
for l in range(2):
    task=gevent.spawn(fundcode(int(q),int(e)))
    listtask.append(task)
gevent.joinall(listtask)
fundall(int(q))
open1()
open2()
open3()
end = time.time()
print(start-end)

python 使用BeautifulSoup爬取天天基金网主要数据

经过手动处理的效果图,勉强完成目标
最后:
此程序无ip代理池,需要多次分开抓取,
无多线程,运行极慢,
数据抓入csv后需要手动处理,为避免出现IndexError空列表错误,需要在csv删除最后重复的基金编码数据
(ps:一直没找到为什么基金编码会重复抓三次的原因)

希望各位大神多多指教,第一次写代码,自知很多不足,还请指正!!!

上一篇:实用的 Pandas 技巧,估计 80% 的人不知道


下一篇:run `npm fund` for details found 16 vulnerabilities (2 low, 8 moderate, 6 high) run `npm audit fi