携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第23天,点击查看活动详情
写在前面
最近查阅 github 的时候,发现一个网站http://glidedsky.com/,竟然是一个爬虫练习的网站,作为一个爬虫爱好者,还是有必要挑战一下的,而且看了一下网站的定位,感觉非常棒。
以下内容来源 glidedsky.com 网站 About
定位 镀金的天空是一个互联网技能认证网站,要保证用户解出一道题目就意味着拥有了解决类似问题相应的技能,所以会激励以下行为:
解决题目证明自己拥有题目所考核的相关技能。 协助他人学习掌握题目所考核的相关技能。 对应的,会惩罚以下行为:
不具备题目所考核的相关技能的情况下,包括但不限于抄袭答案,代码等形式通过题目。 协助他人在不具备题目所考核的技能的情况下,通过题目。 在题目的设置上,追求:
实用性,题目考察的技能有具体的使用场景。 体系性,一个领域会出一系列题目,保证该领域有全面的认识。
挑战一下,虽然不知道最终可否把全部内容答完,以纯实验的心态来吧。第一步注册一个账号。
答题走起
1. 爬虫-基础 1
请看题目
作为一个答题效率者,部分源码以得到正确答案为主,代码会尽量保持美观,哈哈哈
第一题就比较简单了,通过筛选 Cookie,发现只有glidedsky_session用来判断是否登录状态,那这就比较简单了,直接从开发者工具里面赋值过来即可。当然作者的原意应该是让我们模拟登录一下。
代码如下,最终的结果自行计算
import requests
from lxml import etree
# 访问页面为 http://glidedsky.com/level/web/crawler-basic-1
# 注意到如果没有登录,无法访问
headers = {
'Host': 'glidedsky.com',
'Referer': 'http://glidedsky.com/level/crawler-basic-1',
'User-Agent': 'Mozilla/5.0 填写自己的UA',
'Cookie':'glidedsky_session=从开发者工具将Cookie的值复制一份'
}
def run(url):
res = requests.get(url,headers=headers)
html = etree.HTML(res.text)
numbers = html.xpath("//div[@class='col-md-1']/text()")
totle = 0
for number in numbers:
totle+=int(number)
print(totle)
if __name__ == "__main__":
run('http://glidedsky.com/level/web/crawler-basic-1')
2. 爬虫-基础 2
和第二题同时出现的还有一个关注 VX 的任务,大家关注下,记得在 VX 那里也要发送才可以授权,看一下第二题的内容
1000 页,页数不是很多,其实这道题最佳解法是多线程,但是作为一个懒惰的爬虫代码编写者,我直接循环走起~
想要学习多线程的,可以参考我之前写的博客 ,本篇博客前后都是关于多线程的
懒人参考代码,为了快速得到结果,我没有做代码的优化哦~千万不要吐槽,当然执行还是比较耗时的,我执行了 1 分多钟,才运行出正确的结果。
import requests
from lxml import etree
# 访问页面为 http://glidedsky.com/level/web/crawler-basic-1
# 注意到如果没有登录,无法访问
headers = {
'Host': 'glidedsky.com',
'Referer': 'http://glidedsky.com/level/crawler-basic-1',
'User-Agent': 'Mozilla/5.0 填写自己的UA',
'Cookie':'glidedsky_session=从开发者工具将Cookie的值复制一份'
}
def run(url):
res = requests.get(url,headers=headers)
html = etree.HTML(res.text)
numbers = html.xpath("//div[@class='col-md-1']/text()")
totle = 0
for number in numbers:
totle+=int(number)
return totle
if __name__ == "__main__":
COUNT = 0
for i in range(1,1001):
url = f'http://glidedsky.com/level/web/crawler-basic-2?page={i}'
COUNT +=run(url)
print(COUNT)
写完这道题的答案之后,瞬间出来好多题目...考试恐惧症的我,瞬间不想做了
3. 爬虫-IP 屏蔽 1
查看题目,结果 打开待爬取的页面,呦呵,给我直接屏蔽了,越来越有意思了
屏蔽效果图
这题明显的限制 IP 访问,不过有点意思的是,IP 使用一次就不能再用了,那我们需要系统的调整一下代码了,好,最后这个案例好好的写一下,写完收工。
题目中说是总共 1000 页,那么我们需要 1000 个可用的代理 ip 才可以,这就比较麻烦了,代码没有难度。 一开始,我尝试使用免费的 IP,使用搜索引擎可以找到很多免费的,但是找了半天,最终的结果就是没有好用的,最后尝试的方案是找一些出售代理 ip 的网站,然后进行,最终的方案也是修改了比较多的版本
部分代码如下,我尽量在代码注释中对问题进行整体的描述
import requests
import time
from lxml import etree
def get_one_ip():
# 这个函数为你自己获取IP的方式,我后来找到的是一些代理平台,使用的是限时免费使用,用来测试一下这个题,时间足够了
# 最后返回一个ips的列表
return ips
# 计算函数
def calc(text, page):
html = etree.HTML(text)
numbers = html.xpath("//div[@class='col-md-1']/text()")
write_numbers = []
totle = 0
for number in numbers:
write_numbers.append(str(int(number)))
totle += int(number)
# print(write_numbers) 这里主要为了写入文件,防止出现问题,实际的图在代码后
with open(f"./nos.csv", "a+", encoding='utf-8') as f:
f.write(','.join(write_numbers)+'\t page '+str(page)+' \n')
return totle
def run():
headers = {
'User-Agent': 'Mozilla/5.0 填写你自己的UA',
'Cookie': 'glidedsky_session=填写你自己的Cookie'
}
# 定义一个起始页码
ips = get_one_ip() # 获取到IP,我使用的平台一次会返回5个IP,所以下面部分判断是按照数字5进行区分的
ip_index = 0 # ip序号范围,0~4
page_index = 1 # 页码
COUNT = 0 # 计算最终的结果
while True:
proxies = {'http': ips[ip_index],
'https': ips[ip_index]} # 从0开始
print(proxies) # 打印一下IP
url = f'http://glidedsky.com/level/web/crawler-ip-block-1?page={page_index}' # 从第1页开始爬取
print("正在抓取:" + url)
try:
res = requests.get(
url, headers=headers, proxies=proxies, timeout=3) # 通过代理爬取
text = res.text
print(f"正在计算第:{page_index} 页")
totle = calc(text, page_index)
print("当前的totle值为:"+str(totle))
# 此处有时没有计算到totle的值,需要在重新抓取数据
if totle == 0:
if ip_index < 4:
ip_index += 1 # 序号增加
else:
ips = get_one_ip() # IP使用完毕,重新获取
ip_index = 0 # 序号从0继续开始
else:
COUNT += totle
print("计算完毕,目前的结果为:"+str(COUNT))
page_index += 1 # 页码增加
if ip_index < 4:
ip_index += 1 # 序号增加
else:
ips = get_one_ip()
ip_index = 0
except Exception as e:
print(e)
print(f"./{url} 爬取失败")
# 重新抓取
if ip_index < 4:
ip_index += 1 # 序号增加
else:
ips = get_one_ip()
ip_index = 0
if __name__ == "__main__":
run()
nos.csv文件截图,注意到数据有时会出现问题,需要做一些调整,在上述代码中也有相应的说明
运行效果图
4. 最终结果
没有用多线程,因为一个 IP 只能访问一次,本身限制就比较严格了,所以这个地方跑个 10 几分钟得到结果就 OK 了
最终得到结果之后,输入,通过,然后出现了 IP 限制问题 2。下一篇博客在说吧
写在后面
glidedsky 网站整体设计的还是比较有意思的,从简单到困难,有一些小门槛,有兴趣的可以研究研究。我们下一篇博客见~