打开http://fund.jd.com/,发现基金信息的加载是ajax类型,页面链接不变,请求基金信息时页面实际上是在后台与服务器进行了数据交互,需要的信息是JavaScript再次加载进来,并不是在html中。于是,进入开发者模式,分析xhr,多次点击刷新发现规律,爬虫程序编写如下。
# coding: utf-8
import requests
import json
import pandas as pd
import sys
import time
params = {'User-Agent':
'Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/66.0.3359.139 Safari/537.36',
'http':
'https://125.94.178.99:35380'}
# 获取该类型的总基金数量
def getNumsOfFunds(url):
reponse = requests.get(url)
if reponse.status_code == 200:
tmp = json.loads(reponse.text[1:-1])
total = tmp.get('total')
pages = tmp.get('pageCount')
return pages
return None
def sendRequest(url):
response = requests.get(url,headers=params)
if response.status_code == 200:
start = response.text.index('total')-2
return response.text[start:-1]
print('请求失败')
return None
fundTypes = {'全部':'','货币型':"60%3A200", '股票型':"60%3A202", '债券型':"60%3A201", '混合型':'60%3A203' ,'理财型':'60%3A205',
'指数型':'60%3A207' ,'QDII': '60%3A206', '养老FOF':'60%3A208', '其它型':'60%3A204'}
def main():
# 给出基金类型
userInput = input('请输入想要爬取的基金类型:')
try:
fundType =fundTypes[userInput]
except KeyError:
print('输入的基金类型不存在')
return None
rawurl = 'http://fund.jd.com/getLeftTab?callback&op=%s'%(fundType)
pages = getNumsOfFunds(rawurl)
if not pages:
print('没有获取到页数')
sys.exit('退出')
result = pd.DataFrame()
for i in range(1,pages):
time.sleep(0.5)
print('-----------------------------爬取',i,'页--------------------------------------')
url = rawurl + '&sortType=6&page=' + str(i)
r = sendRequest(url)
if not r:
print('bad')
continue
jsondata = json.loads(r)
items = jsondata.get('items')
tmp = pd.DataFrame(items)
result =pd.concat([result,tmp])
result.to_excel('D:/京东基金.xlsx',index=0)
print('完成')
if __name__ == '__main__':
main()
使用时需要选择基金类型,详见代码中的基金类型字典fundTypes,这是从网页中分析得到的。
后续考虑多进程优化,想挑战的同学可以自己试试!
欢迎留言交流指正!