动态网页爬虫Python实现记录-如何在不登录的情况下获取LeetCode-CN用户提交记录

之前偶然看到有位博主弄了一个打卡记录网站:地址,用户只要提交在LC上的用户名就可以自动爬取做题记录。我只弄过一个登录版的爬虫,在知道用户名和密码的情况下登录后可爬取提交代码。所以看到这个网站之后,我蠢蠢欲动,也想弄一个不需要登录的提交结果查询爬虫,以后可以联动微信群机器人实现全自动化统计打卡群成员每天的打卡结果。

 

首先去上述博主的博客和github逛了一圈,发现项目没有开源,所以只能先试试手动造轮子。

接着在未登录的情况下,随机打开一名用户的LC中国主页,可以看到在网页的中部和下部就是该用户的历史提交记录。

接着打开网页审查元素,把鼠标放在希望爬取的内容上面。

OK成了,接下来似乎只要把html文件爬取下来即可,于是参考某教程(教程链接找不到了真不好意思)得到以下代码:

import requests, urllib
from bs4 import BeautifulSoup
import json

url = 'https://leetcode-cn.com/u/awayfuture-tfjify50il/'
def open_url(url):
    head = {'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/5'
                          '37.36 (KHTML, like Gecko) Chrome/63.0.3239.132 Safari/537.36'}
    req = urllib.request.Request(url, headers=head)
    response = urllib.request.urlopen(req)

    html = response.read()
    html_str = html.decode('utf-8')
    print (html_str)


if __name__ == '__main__':
    open_url(url)

 看一看爬取下来的结果:结果

然后突然发现:咦怎么没有我之前看到的东西?

学习一番之后明白了:这是一个动态加载的网站,而我使用的是静态的爬取方法,真正的内容都是由js动态加载得到。

emmmm,行吧我再学学怎么爬动态网站。参考教程:教程

接着按照教程的指示,把审查元素调整到 Network 选项卡,然后刷新网站,观察此网站的通讯情况,如下图所示:

下一步就很无聊了,把每个后缀不是js也不是css的文件看一遍,试图寻找数据到底是从哪里传输的。

一番搜索之后终于找到了我想要的数据,如下图所示。

继续按照教程指示,根据 Preview 选项卡里的 Payload,模拟 POST 行为来得到交互链接。

所以能得到如下链接:

https://leetcode-cn.com/graphql?oprationName=recentSubmissions&variables={%22userSlug%22:%22awayfuture-tfjify50il%22}&query=query%20recentSubmissions($userSlug:%20String!){recentSubmissions(userSlug:%20$userSlug){status%20lang%20question{questionFrontendId%20title%20translatedTitle%20titleSlug%20__typename}submitTime%20__typename}}

访问这串链接试一试,恰好就是我想要的数据:结果

小改一下代码:

import requests, urllib
from bs4 import BeautifulSoup
import json

USERNAME = "awayfuture-tfjify50il"
url = "https://leetcode-cn.com/graphql?oprationName=recentSubmissions&variables={%22userSlug%22:%22" + USERNAME + "%22}&query=query%20recentSubmissions($userSlug:%20String!){recentSubmissions(userSlug:%20$userSlug){status%20lang%20question{questionFrontendId%20title%20translatedTitle%20titleSlug%20__typename}submitTime%20__typename}}"

def open_url(url):
    head = {'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/5'
                          '37.36 (KHTML, like Gecko) Chrome/63.0.3239.132 Safari/537.36'}
    req = urllib.request.Request(url, headers=head)
    response = urllib.request.urlopen(req)

    html = response.read()
    html_str = html.decode('utf-8')
    t = json.loads(html_str)

    for item in t['data']['recentSubmissions']:
        print (item)


if __name__ == '__main__':
    open_url(url)

即可得到稍微处理之后的数据:

{'status': 'A_10', 'lang': 'A_1', 'question': {'questionFrontendId': '739', 'title': 'Daily Temperatures', 'translatedTitle': '每日温度', 'titleSlug': 'daily-temperatures', '__typename': 'QuestionNode'}, 'submitTime': 1570504172, '__typename': 'FeedSubmissionNode'}
{'status': 'A_10', 'lang': 'A_1', 'question': {'questionFrontendId': '141', 'title': 'Linked List Cycle', 'translatedTitle': '环形链表', 'titleSlug': 'linked-list-cycle', '__typename': 'QuestionNode'}, 'submitTime': 1570501637, '__typename': 'FeedSubmissionNode'}
{'status': 'A_15', 'lang': 'A_1', 'question': {'questionFrontendId': '141', 'title': 'Linked List Cycle', 'translatedTitle': '环形链表', 'titleSlug': 'linked-list-cycle', '__typename': 'QuestionNode'}, 'submitTime': 1570501479, '__typename': 'FeedSubmissionNode'}
{'status': 'A_11', 'lang': 'A_1', 'question': {'questionFrontendId': '141', 'title': 'Linked List Cycle', 'translatedTitle': '环形链表', 'titleSlug': 'linked-list-cycle', '__typename': 'QuestionNode'}, 'submitTime': 1570501386, '__typename': 'FeedSubmissionNode'}
{'status': 'A_20', 'lang': 'A_1', 'question': {'questionFrontendId': '141', 'title': 'Linked List Cycle', 'translatedTitle': '环形链表', 'titleSlug': 'linked-list-cycle', '__typename': 'QuestionNode'}, 'submitTime': 1570501357, '__typename': 'FeedSubmissionNode'}
{'status': 'A_11', 'lang': 'A_1', 'question': {'questionFrontendId': '141', 'title': 'Linked List Cycle', 'translatedTitle': '环形链表', 'titleSlug': 'linked-list-cycle', '__typename': 'QuestionNode'}, 'submitTime': 1570501039, '__typename': 'FeedSubmissionNode'}
{'status': 'A_11', 'lang': 'A_1', 'question': {'questionFrontendId': '141', 'title': 'Linked List Cycle', 'translatedTitle': '环形链表', 'titleSlug': 'linked-list-cycle', '__typename': 'QuestionNode'}, 'submitTime': 1570500878, '__typename': 'FeedSubmissionNode'}
{'status': 'A_10', 'lang': 'A_1', 'question': {'questionFrontendId': '20', 'title': 'Valid Parentheses', 'translatedTitle': '有效的括号', 'titleSlug': 'valid-parentheses', '__typename': 'QuestionNode'}, 'submitTime': 1542809216, '__typename': 'FeedSubmissionNode'}
{'status': 'A_10', 'lang': 'A_1', 'question': {'questionFrontendId': '844', 'title': 'Backspace String Compare', 'translatedTitle': '比较含退格的字符串', 'titleSlug': 'backspace-string-compare', '__typename': 'QuestionNode'}, 'submitTime': 1542717452, '__typename': 'FeedSubmissionNode'}
{'status': 'A_15', 'lang': 'A_1', 'question': {'questionFrontendId': '844', 'title': 'Backspace String Compare', 'translatedTitle': '比较含退格的字符串', 'titleSlug': 'backspace-string-compare', '__typename': 'QuestionNode'}, 'submitTime': 1542717397, '__typename': 'FeedSubmissionNode'}
{'status': 'A_15', 'lang': 'A_1', 'question': {'questionFrontendId': '844', 'title': 'Backspace String Compare', 'translatedTitle': '比较含退格的字符串', 'titleSlug': 'backspace-string-compare', '__typename': 'QuestionNode'}, 'submitTime': 1542717304, '__typename': 'FeedSubmissionNode'}
{'status': 'A_10', 'lang': 'A_1', 'question': {'questionFrontendId': '155', 'title': 'Min Stack', 'translatedTitle': '最小栈', 'titleSlug': 'min-stack', '__typename': 'QuestionNode'}, 'submitTime': 1542704826, '__typename': 'FeedSubmissionNode'}
{'status': 'A_10', 'lang': 'A_1', 'question': {'questionFrontendId': '225', 'title': 'Implement Stack using Queues', 'translatedTitle': '用队列实现栈', 'titleSlug': 'implement-stack-using-queues', '__typename': 'QuestionNode'}, 'submitTime': 1542699926, '__typename': 'FeedSubmissionNode'}
{'status': 'A_10', 'lang': 'A_1', 'question': {'questionFrontendId': '232', 'title': 'Implement Queue using Stacks', 'translatedTitle': '用栈实现队列', 'titleSlug': 'implement-queue-using-stacks', '__typename': 'QuestionNode'}, 'submitTime': 1542509499, '__typename': 'FeedSubmissionNode'}
{'status': 'A_10', 'lang': 'A_1', 'question': {'questionFrontendId': '682', 'title': 'Baseball Game', 'translatedTitle': '棒球比赛', 'titleSlug': 'baseball-game', '__typename': 'QuestionNode'}, 'submitTime': 1542379983, '__typename': 'FeedSubmissionNode'}
{'status': 'A_20', 'lang': 'A_1', 'question': {'questionFrontendId': '682', 'title': 'Baseball Game', 'translatedTitle': '棒球比赛', 'titleSlug': 'baseball-game', '__typename': 'QuestionNode'}, 'submitTime': 1542377590, '__typename': 'FeedSubmissionNode'}
{'status': 'A_10', 'lang': 'A_1', 'question': {'questionFrontendId': '496', 'title': 'Next Greater Element I', 'translatedTitle': '下一个更大元素 I', 'titleSlug': 'next-greater-element-i', '__typename': 'QuestionNode'}, 'submitTime': 1542026974, '__typename': 'FeedSubmissionNode'}
{'status': 'A_10', 'lang': 'A_1', 'question': {'questionFrontendId': '557', 'title': 'Reverse Words in a String III', 'translatedTitle': '反转字符串中的单词 III', 'titleSlug': 'reverse-words-in-a-string-iii', '__typename': 'QuestionNode'}, 'submitTime': 1541684697, '__typename': 'FeedSubmissionNode'}
{'status': 'A_12', 'lang': 'A_1', 'question': {'questionFrontendId': '557', 'title': 'Reverse Words in a String III', 'translatedTitle': '反转字符串中的单词 III', 'titleSlug': 'reverse-words-in-a-string-iii', '__typename': 'QuestionNode'}, 'submitTime': 1541683934, '__typename': 'FeedSubmissionNode'}
{'status': 'A_11', 'lang': 'A_1', 'question': {'questionFrontendId': '557', 'title': 'Reverse Words in a String III', 'translatedTitle': '反转字符串中的单词 III', 'titleSlug': 'reverse-words-in-a-string-iii', '__typename': 'QuestionNode'}, 'submitTime': 1541683208, '__typename': 'FeedSubmissionNode'}
{'status': 'A_10', 'lang': 'A_1', 'question': {'questionFrontendId': '344', 'title': 'Reverse String', 'translatedTitle': '反转字符串', 'titleSlug': 'reverse-string', '__typename': 'QuestionNode'}, 'submitTime': 1541680402, '__typename': 'FeedSubmissionNode'}
{'status': 'A_10', 'lang': 'A_1', 'question': {'questionFrontendId': '657', 'title': 'Robot Return to Origin', 'translatedTitle': '机器人能否返回原点', 'titleSlug': 'robot-return-to-origin', '__typename': 'QuestionNode'}, 'submitTime': 1541679592, '__typename': 'FeedSubmissionNode'}
{'status': 'A_10', 'lang': 'A_1', 'question': {'questionFrontendId': '709', 'title': 'To Lower Case', 'translatedTitle': '转换成小写字母', 'titleSlug': 'to-lower-case', '__typename': 'QuestionNode'}, 'submitTime': 1541679003, '__typename': 'FeedSubmissionNode'}
{'status': 'A_10', 'lang': 'A_1', 'question': {'questionFrontendId': '169', 'title': 'Majority Element', 'translatedTitle': '多数元素', 'titleSlug': 'majority-element', '__typename': 'QuestionNode'}, 'submitTime': 1541468091, '__typename': 'FeedSubmissionNode'}
{'status': 'A_10', 'lang': 'A_1', 'question': {'questionFrontendId': '169', 'title': 'Majority Element', 'translatedTitle': '多数元素', 'titleSlug': 'majority-element', '__typename': 'QuestionNode'}, 'submitTime': 1541467993, '__typename': 'FeedSubmissionNode'}
{'status': 'A_11', 'lang': 'A_1', 'question': {'questionFrontendId': '169', 'title': 'Majority Element', 'translatedTitle': '多数元素', 'titleSlug': 'majority-element', '__typename': 'QuestionNode'}, 'submitTime': 1541467975, '__typename': 'FeedSubmissionNode'}
{'status': 'A_10', 'lang': 'A_1', 'question': {'questionFrontendId': '905', 'title': 'Sort Array By Parity', 'translatedTitle': '按奇偶排序数组', 'titleSlug': 'sort-array-by-parity', '__typename': 'QuestionNode'}, 'submitTime': 1541467166, '__typename': 'FeedSubmissionNode'}
{'status': 'A_10', 'lang': 'A_1', 'question': {'questionFrontendId': '56', 'title': 'Merge Intervals', 'translatedTitle': '合并区间', 'titleSlug': 'merge-intervals', '__typename': 'QuestionNode'}, 'submitTime': 1541304121, '__typename': 'FeedSubmissionNode'}
{'status': 'A_15', 'lang': 'A_1', 'question': {'questionFrontendId': '56', 'title': 'Merge Intervals', 'translatedTitle': '合并区间', 'titleSlug': 'merge-intervals', '__typename': 'QuestionNode'}, 'submitTime': 1541303998, '__typename': 'FeedSubmissionNode'}
{'status': 'A_10', 'lang': 'A_1', 'question': {'questionFrontendId': '524', 'title': 'Longest Word in Dictionary through Deleting', 'translatedTitle': '通过删除字母匹配到字典里最长单词', 'titleSlug': 'longest-word-in-dictionary-through-deleting', '__typename': 'QuestionNode'}, 'submitTime': 1541133662, '__typename': 'FeedSubmissionNode'}

数据的初步获取就到此结束了。

  • 3
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
Python合法网页爬虫工具项目分享 内容概览: 这个分享包涵了我开发的Python爬虫工具项目,主要用于合法爬取某些网页信息。以下是主要内容: 源代码:包括Python代码和相关脚本。这些代码展示了如何使用Python进行网页抓取、解析和数据提取。 项目文件:除了代码,我还分享了整个项目的文件,包括设计稿、图标、图片等资源。这些资源对于理解项目背景和设计思路至关重要。 文档与操作手册:为了方便他人理解和使用我的作品,我编写了详细的操作手册和使用说明,同时提供了一份Markdown格式的文档,概述了项目的主要功能和特点。 学习笔记:在项目开发过程中,我记录了大量的学习笔记和心得体会。这些笔记不仅有助于理解项目的开发过程,还能为学习Python爬虫技术提供宝贵的参考资料。 适用人群: 这份项目合集适用于所有对Python爬虫开发感兴趣的人,无论你是学生、初学者还是有一定经验的开发者。无论你是想学习新的技术,还是想了解一个完整的项目开发流程,这份资料都将为你提供极大的帮助。 使用建议: 按部就班地学习:建议从基础的Python爬虫开发开始,逐步深入到实际应用中。通过实践,逐步掌握Python爬虫开发的各项技能。 参考项目文件和笔记:项目文件和笔记提供了丰富的背景信息和开发经验。在学习的过程中,不妨参考这些资料,以帮助你更好地理解和学习。 动手实践:Python爬虫开发是一门实践性很强的技能。通过实际操作,你可以更好地掌握Python爬虫开发的各项技能,并提高自己的实践能力。Python合法网页爬虫工具项目分享 内容概览: 这个分享包涵了我开发的Python爬虫工具项目,主要用于合法爬取某些网页信息。以下是主要内容: 源代码:包括Python代码和相关脚本。这些代码展示了如何使用Python进行网页抓取、解析和数据提取。 项目文件:除了代码,我还分享了整个项目的文件,包括设计稿、图标、图片等资源。这些资源对于理解项目背景和设计思路至关重要。 文档与操作手册:为了方便他人理解和使用我的作品,我编写了详细的操作手册和使用说明,同时提供了一份Markdown格式的文档,概述了项目的主要功能和特点。 学习笔记:在项目开发过程中,我记录了大量的学习笔记和心得体会。这些笔记不仅有助于理解项目的开发过程,还能为学习Python爬虫技术提供宝贵的参考资料。 适用人群: 这份项目合集适用于所有对Python爬虫开发感兴趣的人,无论你是学生、初学者还是有一定经验的开发者。无论你是想学习新的技术,还是想了解一个完整的项目开发流程,这份资料都将为你提供极大的帮助。 使用建议: 按部就班地学习:建议从基础的Python爬虫开发开始,逐步深入到实际应用中。通过实践,逐步掌握Python爬虫开发的各项技能。 参考项目文件和笔记:项目文件和笔记提供了丰富的背景信息和开发经验。在学习的过程中,不妨参考这些资料,以帮助你更好地理解和学习。 动手实践:Python爬虫开发是一门实践性很强的技能。通过实际操作,你可以更好地掌握Python爬虫开发的各项技能,并提高自己的实践能力。Python合法网页爬虫工具项目分享 内容概览: 这个分享包涵了我开发的Python爬虫工具项目,主要用于合法爬取某些网页信息。以下是主要内容: 源代码:包括Python代码和相关脚本。这些代码展示了如何使用Python进行网页抓取、解析和数据提取。 项目文件:除了代码,我还分享了整个项目的文件,包括设计稿、图标、图片等资源。这些资源对于理解项目背景和设计思路至关重要。 文档与操作手册:为了方便他人理解和使用我的作品,我编写了详细的操作手册和使用说明,同时提供了一份Markdown格式的文档,概述了项目的主要功能和特点。 学习笔记:在项目开发过程中,我记录了大量的学习笔记和心得体会。这些笔记不仅有助于理解项目的开发过程,还能为学习Python爬虫技术提供宝贵的参考资料。 适用人群: 这份项目合集适用于所有对Python爬虫开发感兴趣的人,无论你是学生、初学者还是有一定经验的开发者。无论你是想学习新的技术,还是想了解一个完整的项目开发流程,这份资料都将为你提供极大的帮助。 使用建议: 按部就班地学习:建议从基础的Python爬虫开发开始,逐步深入到实际应用中。通过实践,逐步掌握Python爬虫开发的各项技能。 参考项目文件和笔记:项目文件和笔记提供了丰富的背景信息和开发经验。在学习的过程中,不妨参考这些资料,以帮助你更好地理解和学习。 动手实践:Python爬虫开发是一门实践性很强的技能。通过实际操作,你可以更好地掌握Python爬虫开发的各项技能,并提高自己的实践能力。Python合法网页爬虫工具项目分享 内容概览: 这个分享包涵了我开发的Python爬虫

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值