一次简单的爬虫过程


最近期末考试和各种大作业接踵而来非常繁忙,先更新些轻松的内容,分布式存储的内容要往后推了 😩


先简单说明一下这个Easy to do系列,这个系列的主题主要是展现针对一种实际生产生活中产生的需求,去利用技术解决问题的过程。我觉得Programmer作为工程师,是利用技术去解决实际问题的,但计算机领域的知识和技术是非常丰富和庞杂的,一个人很难对所有技术都有深入的了解,而有些时候我们会遇到一些需要不太熟悉的技术来解决的问题,这时如果是很复杂深入的需求可以选择雇一个这方面的专业人士来帮助我们解决,但如果只是一个领域入门级知识就能解决的需求,那可以自己快速了解下相关领域技术来实现需求。

作为一名在校生,我深切地感受到国内高校很多课程的教学非常偏重理论,而对实践方面的内容涉及得很少。我觉得理论基础固然重要,但对于工程师而言理论最终是帮助我们更好地解决问题的。而学校和课程和很多网上的教程文章对实践过程的讲解并不完整清晰。我之前也简单学习过爬虫,当时也是为了解决自己的一个实际需求,网络上关于爬虫的教程很多,有从原理知识方面介绍的,也有实践方面的介绍。但这些呢,并没有很快很好地解决我当时的问题,因为原理知识的介绍涉及的内容很多,看完需要很多时间,而实践方面的内容呢以代码展示为主,对于当时完全是小白的我来说,缺少了一些关键步骤的指引,所以有了今天的这个系列。

这个系列更多是从一个技术领域新手的角度出发,着手于快速解决一个比较简单的需求。由于我选择的领域也都是我并不十分熟悉的,所以自然在很大程度上避免了the curse of knowledge。不过它也有相应的缺点:这并不是爬虫方向的系统教程,有很多内容并没有涉及,还有其中一些操作步骤可能是针对特定的网页数据有效,不具备普适性。但该教程展示了利用爬虫解决一个简单需求的完整过程,对于想要快速利用简单爬虫完成自己需求的朋友将有所帮助,在了解了相应的流程后,就可以着手自己的任务,如果自己实践的过程中遇到了问题可以再去查阅网络上关于爬虫知识都系统性教程,这时候将更有针对性地从中选取自己需要的信息解决自己的问题。

初步分析

正好前几天的时候,我一个小伙伴让我帮忙在淘宝商品页面上爬一个数据。他给我发过来一个URL和图片,说想用爬虫获取人气信息,如下图所示。

虽然很久没搞爬虫了,但看起来很简单于是我快速答应了下来。首先,用Chrome打开该连接然后利用控制台(F12)功能在Element里寻找该组件对应的html代码,如下图所示:

可以看到,当鼠标悬停在不同的代码片段上时,对应的元素在网页中会高亮显示出来。这样可以一点一点找到我们想要的元素对应的html代码。最终,我锁定了人气部分对应的代码,如下:

这时,我以为差不多搞定了,利用request库请求到html后再解析就可以拿到对应人气值了,我又查看了网页源代码,发现了<meta charset="gbk" />,然后快速地写下了代码:

import requests
from bs4 import BeautifulSoup

url = 'https://...........'
r = requests.get(url)
r.encoding = 'gbk'
html = r.text
soup = BeautifulSoup(html, "lxml")
target = soup.find("span", id='J_CollectCount')
print(target)

事情没有那么简单,,

但我发现输出是<span id="J_CollectCount"></span>,里面并没有人气值的数据。开始我以为是我没检索完全,可能还有一个span id ="J_CollectCount",于是在网页源代码中搜索结果只有这一个,虽然我没有学过html方面的东西,但我意识到这个值应该是动态再获取的,而不是服务器返回html时直接把值放在里面。所以关键是找到用什么方法请求了这个数值, 在html里我没找到什么头绪,然后我突然想到既然是动态请求肯定也要利用网络,那依然可以在控制台里面找线索。这次是利用network菜单栏。

可以看到控制台发现了上百个http请求,我用搜索功能最终确定了获取人气信息的请求

找到对应的URL,粘贴到浏览器中访问,果然返回了json数据包含了人气数据。其实这里也可以看到,我上面这些图片的截取时间不同,人气数据确实一直在动态变化。这个URL长这样:https://count.taobao.com/counter3?_ksTS=1623429031125_307&callback=jsonp308&keys=SM_368_dsr-2194426048,ICCP_1_526256013584

在网页源码里寻找相应的输入参数,最终我发现:"apiBeans":"//count.taobao.com/counter3?keys=SM_368_dsr-2194426048,ICCP_1_526256013584",也就是提供了keys和ICCP的数值,从而生成URL请求。我试过直接访问html里这个URL是不行的,可见_ksTS=1623429031125_307&callback=jsonp308是必不可少的,但我依然不知道这里面尤其是_ksTS对于的数据是个啥,会不会变化,于是我又换了个商品用同样的方法找到请求人气数据的URL,发现他们是不同的,而且我并没有在html里发现这个参数的存在。这就很难受了,因为没法爬取一系列不同的商品了。

好在经过我的不懈努力(各种尝试),我发现在URL中去掉那个奇妙的参数_ksTS也可以得到正确的返回结果,我大喜,最终:

https://count.taobao.com/counter3?&callback=json&keys=SM_368_dsr-2194426048,ICCP_1_526256013584只要针对不同商品更改keys和ICCP的值就可以获取人气数值了。于是承接上面的内容,继续coding如下:

reqURL = 'https://count.taobao.com/counter3?callback=json&keys='
keys = ''.join(re.findall(r"count.taobao.com/counter3\?keys=(.*?),", str(target), re.S))
ICCP = ''.join(re.findall(r"ICCP(.*?)\"", str(target), re.S))

finalURL = reqURL + keys + ',ICCP' + ICCP
r = requests.get(finalUrl)
html = r.text
result = ''.join(re.findall(r'ICCP'+field2+"\":(.*?),", html, re.S))
print(result)

终于顺利爬取到了对应的人气值,简单整理下顺利完工 👌

总结

这篇文章大致展现了我解决这个问题时的基本流程,其实从中也可以看出我对html还有爬虫不是非常熟悉,但最终还是比较顺利快速地解决了问题。我觉得首先对大致流程要了解,利用浏览器控制台功能定位想要爬虫的信息对于的html语句,在遇到问题时也不要着急,冷静地寻找解决方法。要用对工程师解决问题思路的基本把握,就可以通过猜测和尝试来定位解决路线,比如:html中没有那肯定是动态获取(后来逐渐发现人气值数据确实在短时间内不断变化,动态获取是非常有道理的),动态获取就需要通过http请求,于是可以利用控制台去搜索,找到URL后要确认参数,保证针对淘宝上不同的商品页面代码具有通用性。按照这样的思路就能不断地解决问题。

当然最后我也没明白那个奇妙参数是干啥的,不过需求是解决了,有知道的小伙伴可以给我科普下~

🌱剧透一下,下一篇文章应该是关于QUIC的内容


文章作者: Sorata
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 Sorata !
评论
  目录