爬取私募排排网历史净值和破解加密数值(下)
共 4735字,需浏览 10分钟
·
2021-08-16 18:36
“阅读本文大概需要6分钟”
二、对每个基金处理
经过上一步解析网页之后,得到每个基金的网站。现在循环处理这些网址,爬取数据。
1. 解析每个基金网页
解析每个基金网页还是运用 driver.get
加载网页,利用 page_source
解析网页。
driver.execute_cdp_cmd("Page.addScriptToEvaluateOnNewDocument", {
"source": """
Object.defineProperty(navigator, 'webdriver', {
get: () => undefined
})
"""
})
for ind in range(len(list_name)):
driver.get(list_url[ind]) # 加载网站
不过在 page_source
解析网页之前,有一个东西必须要注意!
那就是如果直接解析网页得到的历史净值只有一小部分,是因为历史净值是一个动态的,我们在解析之前需要利用selenium将历史净值这个内嵌框下滑到底,而且这个内嵌框是一个异步加载的(滑动完后,又会出来一段),使用需要多个滑动才能满足条件。
解决问题要点:首先得将历史净值点击,然后定位历史净值框。
如图已经定位到了内嵌框,下面就开滑动
driver.find_element(By.XPATH,'//div/div[2]/div[2]/div[1]/div[2]/div[1]/div[1]/a[2]').click() # 点击历史净值
for i in range(50):
js = 'document.getElementsByClassName("tbody")[0].scrollTop=100000' # 在历史净值中滑动,这里滑动50应该是都够了的,如果不够加大就行
driver.execute_script(js)
time.sleep(0.1) # 防止滑动太快,没有读取到结果
page_url = driver.page_source # 解析当前网页
注意 getElementsByClassName("tbody")[0]
这里是查找属性class的属性值为 tbody ,中的第一个元素(一定要带上后面这个 0,因为返回的是一个集合。如果滑动的是 4 个元素就是后面就是 3)
下面就是定位 docment 对象的方法,和 css 定位一样。
感兴趣可以看看 JavaScript 学习链接 http://www.runoob.com/jsref/dom-obj-document.html
2. 解密历史净值中的隐藏值
(1)隐藏值原理
经过上一步就得到了每个基金的网页,接下来就来开始解密。
在解密前我们先来看看它是怎么加密的吧!
可以看到在 html 中存在着网页中没有的内容,这个就是加密。
说实话,在这里花费了不少的时间。我先来说说我的思路吧。
找规律
在开始尝试找规律,最开始规律就是每个值中的span一定是有用的,但是后来发现有的没有span,然后,然后就没有然后了,直接放弃这种想法了。
css 偏移
然后就是 css 偏移就是利用 css 样式将网页中正常的值乱序。但是发现我们这里的值顺序是正常的,只是多了部分值,所以页排除这种想法。
存在隐藏值,最后发现了规律,存在的值(网页上显示的值)
不存在的值(网页上不显示的值)
会发现网页上面不存在的值多了 font: 0/0 a 这个值。
当把 font: 0/0 a 这个边框不勾选了,就会发现网页中会有很多的值中间是有空格的,那么可以得出结论 html中多出来的值并不是多余的,它也是存在网页中的,但是它被隐藏了。
然后我们就抓住在这个特点继续找下去。
当我们发现 ENCODE_STYLE 对应的内容就是和找到的规律一样。
.m440e0{font: 0/0 a;color: transparent;text-shadow: none;background-color: transparent;border: 0;}.m446e7{font: 0/0 a;color: transparent;text-shadow: none;background-color: transparent;border: 0;}.m48eb7{text-shadow: none;background-color: transparent;border: 0;}.m45029{text-shadow: none;background-color: transparent;border: 0;}.m41fd7{font: 0/0 a;color: transparent;text-shadow: none;background-color: transparent;border: 0;}.m4dec4{text-shadow: none;background-color: transparent;border: 0;}.m44109{text-shadow: none;background-color: transparent;border: 0;}
可以去验证,以 m440e0 为属性值去找元素,可以发现全是隐藏值。同理,m48eb7 为属性值去找元素全是真实值。
结论:html中多出来的值并不是多余的,它也是存在网页中的,但是它被隐藏了。这些隐藏值以及真实值在ENCODE_STYLE属性中。所以只需要在ENCODE_STYLE中找存在font: 0/0 a的属性值,即为隐藏值。
(2)代码实现
# 找到隐藏的属性值
def getHideIds(htmlEtree):
encode_styles = "".join(htmlEtree.xpath('//div[@id="ENCODE_STYLE"]/style/text()')).replace("\n", "")
# 清洗数据,去除连续的空格
new_encode_styles = re.sub(" +", "", encode_styles)
# 获取全部被隐藏的id
hideIds1 = re.findall("\.(\w+) {font: 0/0 a;", new_encode_styles) # 格式化后的html
hideIds2 = re.findall("\.(\w+){font: 0/0 a;", new_encode_styles) # 未格式化的html
result = set(hideIds1 + hideIds2)
return result
定义一个函数,调用 xpath 解析的 page_source,返回值为隐藏值的属性值。即类似于 m440e0,m41fd7 的值。
然后只需要将隐藏值对应的元素找出来就行了。
htmlEtree = etree.HTML(text=htmlData)
# 获取被隐藏的id
hideIds = getHideIds(htmlEtree)
# 处理数据
divList = htmlEtree.xpath('//div[@class="tr flex-h-center"]')
# print(divList)
tdDivs = []
for div in divList:
nextDivs = div.xpath('./div[@class="td flex-h-center"]')
for nextDiv in nextDivs:
if nextDivs.index(nextDiv) == 0:
continue
tdDivs.append(nextDiv)
resultList = []
for tdDiv in tdDivs:
labels = tdDiv.xpath("./*")
nowResultList = []
for label in labels:
classStr = label.xpath("./@class")[0]
if classStr not in hideIds:
nowResultList.append(label.xpath("./text()")[0])
resultList.append("".join(nowResultList))
# print(resultList)
# for reslut in resultList:
# print(reslut)
三、将所有数据写入excel
最后再将净值日期和净值变动找到(这两个没有掺杂隐藏值,很简单就能找到),然后利用pandas写入excel中。
write = pandas.ExcelWriter(r"C:\Users\86178\Desktop\私募排排网历史净值爬取.xlsx") # 新建xlsx文件。
list_info.append([list_date[index], resultList[i], resultList[i + 1], resultList[i + 2], list_net[index]]) # 分别对应净值日期,单位净值,累计净值,累计净值,净值变动
pd = pandas.DataFrame(list_info, columns=['净值日期', '单位净值', '累计净值(分红再投资)', '累计净值(分红不投资)', '净值变动'])
# print(pd)
pd.to_excel(write, sheet_name=list_name[ind], index=False)
write.save() # 这里一定要保存
最后得到结果
四、总结
本文主要是讲的selenium的一些基本操作,例如鼠标事件、键盘事件和鼠标悬停。然后就是解密隐藏值。
我在这里遇见了很多的坑,思考了一个下午才把思路想到。我很庆幸在我最艰难的时候,没有说放弃,其实这次更大的收获是让自己对爬虫有更加深刻的见解。
AI悦创·推出辅导班啦,包括「Python 语言辅导班、C++辅导班、算法/数据结构辅导班、少儿编程、pygame 游戏开发」,全部都是一对一教学:一对一辅导 + 一对一答疑 + 布置作业 + 项目实践等。QQ、微信在线,随时响应!V:Jiabcdefh