AI网络爬虫:用GraphQL查询爬取动态网页数据

任务:爬取网站www.skillshare.com搜索结果页面数据:

查看网站的请求信息:

请求网址:

https://www.skillshare.com/api/graphql

请求方法:

POST

状态代码:

200 OK

远程地址:

127.0.0.1:10809

引荐来源网址政策:

strict-origin-when-cross-origin

请求载荷:

{"operationName":"GetClassesQuery","variables":{"query":"ChatGPT","where":{"level":["ALL_LEVELS","BEGINNER","INTERMEDIATE","ADVANCED"]},"analyticsTags":["src:browser","src:browser:search","disc_cls_idx_mig","user-agent:Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/125.0.0.0 Safari/537.36"],"after":"191","first":24},"query":"fragment ClassFields on Class {\n badges {\n type\n __typename\n }\n durationInSeconds\n id\n publishTime\n largeCoverUrl\n sku\n sourceLanguage\n studentCount\n teacher {\n id\n name\n username\n vanityUsername\n __typename\n }\n title\n url\n viewer {\n hasSavedClass\n __typename\n }\n __typename\n}\n\nquery GetClassesQuery($query: String!, $where: SearchFiltersV2!, $analyticsTags: [String!], $after: String!, $first: Int!, $sort: SortParameters) {\n search: searchV2(query: $query, where: $where, analyticsTags: $analyticsTags, after: $after, first: $first, sort: $sort) {\n totalCount\n searchId\n algorithmId\n pageInfo {\n startCursor\n endCursor\n hasNextPage\n hasPreviousPage\n __typename\n }\n edges {\n cursor\n node {\n ...ClassFields\n __typename\n }\n __typename\n }\n __typename\n }\n}\n"}

{"operationName":"GetClassesQuery","variables":{"query":"ChatGPT","where":{"level":["ALL_LEVELS","BEGINNER","INTERMEDIATE","ADVANCED"]},"analyticsTags":["src:browser","src:browser:search","disc_cls_idx_mig","user-agent:Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/125.0.0.0 Safari/537.36"],"after":"167","first":24},"query":"fragment ClassFields on Class {\n badges {\n type\n __typename\n }\n durationInSeconds\n id\n publishTime\n largeCoverUrl\n sku\n sourceLanguage\n studentCount\n teacher {\n id\n name\n username\n vanityUsername\n __typename\n }\n title\n url\n viewer {\n hasSavedClass\n __typename\n }\n __typename\n}\n\nquery GetClassesQuery($query: String!, $where: SearchFiltersV2!, $analyticsTags: [String!], $after: String!, $first: Int!, $sort: SortParameters) {\n search: searchV2(query: $query, where: $where, analyticsTags: $analyticsTags, after: $after, first: $first, sort: $sort) {\n totalCount\n searchId\n algorithmId\n pageInfo {\n startCursor\n endCursor\n hasNextPage\n hasPreviousPage\n __typename\n }\n edges {\n cursor\n node {\n ...ClassFields\n __typename\n }\n __typename\n }\n __typename\n }\n}\n"}

这段请求载荷是一个GraphQL查询,用于获取与搜索查询 "ChatGPT" 相关的不同方面的数据(facets)。下面是对这段查询的详细解释:

- `operationName`: "GetFacets",这指定了操作的名称,用于标识这个特定的查询操作。

- `variables`: 这是一个对象,包含了查询所需的变量:

- `analyticsTags`: 一个包含多个字符串的数组,用于分析目的。

- `query`: 搜索查询的关键字,这里是 "ChatGPT"。

- `where_type`, `where_language`, `where_level`, `where_length`, `where_with`, `where_publish`, `where_rating`: 这些字段包含了搜索过滤条件,每个字段都设置为相同的值,即包含所有级别("ALL_LEVELS", "BEGINNER", "INTERMEDIATE", "ADVANCED")的数组。这些过滤条件用于指定搜索的不同维度。

- `query`: 这是GraphQL查询的主体,它定义了要获取的数据:

- `fragment FacetsData on SearchResultItemConnectionV2`: 这是一个片段,定义了搜索结果项连接的类型,包括总数量(totalCount)和方面(facets)。

- `totalCount`: 搜索结果的总数。

- `facets`: 一个包含不同方面选项的对象数组,每个选项都有计数(count)和名称(name)。

- 接下来的部分定义了多个 `searchV2` 查询,每个查询都针对不同的搜索维度(type, language, level, length, with, publish, rating),并使用上面定义的片段 `FacetsData` 来获取每个维度的总数量和方面数据。

这个查询的主要目的是为搜索 "ChatGPT" 提供一个多维度的概览,包括不同类别(如类型、语言、难度级别等)的统计信息和选项。通过这种方式,用户可以了解每个维度下的课程分布情况,从而帮助他们进行更精确的搜索和选择。

找了两段不同的请求载荷,主要区别在于`variables`对象中的`after`字段的值不同。

两个请求载荷的共同点:

- `operationName`:两个请求都使用了相同的操作名称 `"GetClassesQuery"`。

- `variables`中的其他字段:`query`、`where`、`analyticsTags`、`first` 在两个请求中都是相同的。

- `query`:两个请求中的GraphQL查询字符串是相同的。

以下是两个请求载荷的不同点:

- `variables`中的`after`字段:

- 第一个请求的`after`字段值是 `"191"`。

- 第二个请求的`after`字段值是 `"167"`。

`after`字段通常用于分页,它指定了从哪个点开始获取数据。在这个GraphQL查询中,它决定了从搜索结果的哪一条记录开始返回数据。因此,第一个请求将从记录191开始获取数据,而第二个请求将从记录167开始获取数据。

这意味着两个请求将返回不同的数据集,即使它们都是基于相同的查询和过滤条件。第一个请求可能是为了获取第一页或后续某页的数据,而第二个请求可能是为了获取另一页的数据。其他字段如`first`指定了每页返回的记录数,在这种情况下,都是24条记录。

再继续查看其他请求载荷的after字段:-1、47、 71、95

搜索结果是205 个,显然`after`字段值是从-1开始,每次递增24,以215结束

在chatgpt中输入提示词:

你是一个Python专家,要完成一个编写爬虫的Python脚本,具体步骤:

请求网址:

https://www.skillshare.com/api/graphql

请求方法:

POST

状态代码:

200 OK

远程地址:

127.0.0.1:10809

引荐来源网址政策:

strict-origin-when-cross-origin

请求标头:

Accept:

*/*

Accept-Encoding:

gzip, deflate, br, zstd

Accept-Language:

zh-CN,zh;q=0.9,en;q=0.8

Content-Length:

1302

Content-Type:

application/json

Origin:

https://www.skillshare.com

Priority:

u=1, i

Referer:

https://www.skillshare.com/en/search/classes?query=ChatGPT

Sec-Ch-Ua:

"Google Chrome";v="125", "Chromium";v="125", "Not.A/Brand";v="24"

Sec-Ch-Ua-Mobile:

?0

Sec-Ch-Ua-Platform:

"Windows"

Sec-Fetch-Dest:

empty

Sec-Fetch-Mode:

cors

Sec-Fetch-Site:

same-origin

User-Agent:

Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/125.0.0.0 Safari/537.36

请求载荷:

{"operationName":"GetClassesQuery","variables":{"query":"ChatGPT","where":{"level":["ALL_LEVELS","BEGINNER","INTERMEDIATE","ADVANCED"]},"analyticsTags":["src:browser","src:browser:search","disc_cls_idx_mig","user-agent:Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/125.0.0.0 Safari/537.36"],"after":"{pagenumber}","first":24},"query":"fragment ClassFields on Class {\n badges {\n type\n __typename\n }\n durationInSeconds\n id\n publishTime\n largeCoverUrl\n sku\n sourceLanguage\n studentCount\n teacher {\n id\n name\n username\n vanityUsername\n __typename\n }\n title\n url\n viewer {\n hasSavedClass\n __typename\n }\n __typename\n}\n\nquery GetClassesQuery($query: String!, $where: SearchFiltersV2!, $analyticsTags: [String!], $after: String!, $first: Int!, $sort: SortParameters) {\n search: searchV2(query: $query, where: $where, analyticsTags: $analyticsTags, after: $after, first: $first, sort: $sort) {\n totalCount\n searchId\n algorithmId\n pageInfo {\n startCursor\n endCursor\n hasNextPage\n hasPreviousPage\n __typename\n }\n edges {\n cursor\n node {\n ...ClassFields\n __typename\n }\n __typename\n }\n __typename\n }\n}\n"}

其中,"after"键对应的字段值"{pagenumber}"是从-1开始,每次递增24,以215结束。

获取网页响应的json数据,打印出来;

提取"data"键中嵌套的"search"键嵌套的"edges"键的内容;

"edges"键对应的值是一个json数据;

将这个json数据所有的键名作为Excel表格的表头,键对应的值作为Excel表格的列数据,全部写入Excel表格中;

保存Excel表格到文件夹“F:\AI自媒体内容\AI行业数据分析”,文件名为:skillshareChatgptcourse20240604.xlsx

注意:每一步信息都要输出到屏幕上

ChatGPT生成的Python源代码:

import requests

import json

import pandas as pd

# 请求网址和请求头

url = "https://www.skillshare.com/api/graphql"

headers = {

'Accept': '*/*',

'Accept-Encoding': 'gzip, deflate, br, zstd',

'Accept-Language': 'zh-CN,zh;q=0.9,en;q=0.8',

'Content-Length': '1302',

'Content-Type': 'application/json',

'Origin': 'https://www.skillshare.com',

'Priority': 'u=1, i',

'Referer': 'https://www.skillshare.com/en/search/classes?query=ChatGPT',

'Sec-Ch-Ua': '"Google Chrome";v="125", "Chromium";v="125", "Not.A/Brand";v="24"',

'Sec-Ch-Ua-Mobile': '?0',

'Sec-Ch-Ua-Platform': '"Windows"',

'Sec-Fetch-Dest': 'empty',

'Sec-Fetch-Mode': 'cors',

'Sec-Fetch-Site': 'same-origin',

'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/125.0.0.0 Safari/537.36'

}

# 定义请求载荷的模板

payload_template = {

"operationName": "GetClassesQuery",

"variables": {

"query": "ChatGPT",

"where": {

"level": ["ALL_LEVELS", "BEGINNER", "INTERMEDIATE", "ADVANCED"]

},

"analyticsTags": [

"src:browser",

"src:browser:search",

"disc_cls_idx_mig",

"user-agent:Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/125.0.0.0 Safari/537.36"

],

"after": "",

"first": 24

},

"query": """

fragment ClassFields on Class {

badges {

type

__typename

}

durationInSeconds

id

publishTime

largeCoverUrl

sku

sourceLanguage

studentCount

teacher {

id

name

username

vanityUsername

__typename

}

title

url

viewer {

hasSavedClass

__typename

}

__typename

}

query GetClassesQuery($query: String!, $where: SearchFiltersV2!, $analyticsTags: [String!], $after: String!, $first: Int!, $sort: SortParameters) {

search: searchV2(query: $query, where: $where, analyticsTags: $analyticsTags, after: $after, first: $first, sort: $sort) {

totalCount

searchId

algorithmId

pageInfo {

startCursor

endCursor

hasNextPage

hasPreviousPage

__typename

}

edges {

cursor

node {

...ClassFields

__typename

}

__typename

}

__typename

}

}

"""

}

# 初始化数据列表

all_data = []

# 循环请求每一页的数据

for i in range(-1, 216, 24):

payload = payload_template.copy()

payload['variables']['after'] = str(i)

response = requests.post(url, headers=headers, json=payload)

if response.status_code == 200:

print(f"Page {i//24 + 1} data fetched successfully.")

data = response.json()

print(json.dumps(data, indent=2)) # 打印响应的JSON数据

# 提取我们需要的部分

edges = data.get('data', {}).get('search', {}).get('edges', [])

all_data.extend([edge['node'] for edge in edges])

else:

print(f"Failed to fetch page {i//24 + 1}. Status code: {response.status_code}")

break

# 将数据转换为DataFrame

df = pd.DataFrame(all_data)

print(df.head()) # 打印表格的前几行

# 保存DataFrame到Excel

output_path = "F:/AI自媒体内容/AI行业数据分析/skillshareChatgptcourse20240604.xlsx"

df.to_excel(output_path, index=False)

print(f"Data saved to {output_path}")

Vscode中运行程序,获取所有查询结果数据:

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/web/22354.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

一篇文章讲透数据结构之树and二叉树

一.树 1.1树的定义 树是一种非线性的数据结构,它是有n个有限结点组成的一个具有层次关系的集合。把它叫做树是因为它看起来像一棵倒挂的树,也就是说它是根在上,叶在下的。 在树中有一个特殊的结点,称为根结点,根结点…

免费工具扫描 Linux 中已知威胁

首发公众号网络研究观,关注获取更多。 卡巴斯基为 Linux 平台发布了一款名为 KVRT 的新病毒清除工具,允许用户免费扫描他们的系统并清除恶意软件和其他已知威胁。 尽管人们普遍误以为 Linux 系统本质上是安全的,不会受到威胁,但不…

如何使用Vuforia AR进行增强现实技术的开发?

前言 今天是坚持写博客的第17天,很高兴自己可以一直坚持下来。我们今天来讲讲怎么使用Vuforia AR进行增强现实的开发。 我们需要在今天的开发中用到Vuforia AR和2018版的Unity3d 什么是Vuforia AR Vuforia AR是基于实时计算摄影机影像的位置及角度,并…

Kubernetes ingress

目录 一.ingress 1.ingress简介 2.实现外部应用能访问内部集群服务的方法 (1)NodePort: (2)LoadBalancer: (3)externalIPs: (4)ingress&am…

【会议征稿,ACM独立出版】第三届机器人、人工智能与信息工程国际学术会议(RAIIE 2024,7月05-07)

2024年第二届机器人、人工智能与信息工程国际学术会议(RAIIE 2024)将于2024年7月5-7日在新加坡举行。本次会议主要围绕“机器人”、“智能仿生”和“信息科学”的最新研究进展展开,会议汇聚了该领域内国际学者、专家、研究人员及相关从业人员…

274 基于matlab的随机粗糙表面对微气体轴承内气体压强分布的影响

基于matlab的随机粗糙表面对微气体轴承内气体压强分布的影响。采用差分法求解气体轴承的雷诺方程,通过尺寸参数、分形维数对粗糙度表面设置,滑流参数设置,实现气压分布可视化结果显示。程序已调通,可直接运行。 274 气体轴承 随机…

基于websocket与node搭建简易聊天室

一、前言 上一篇文章介绍了websocket的详细用法与工具类的封装,本篇就基于websocket搭建一个简易实时的聊天室。 在本篇开始之前也可以去回顾一下websocket详细用法:WebSocket详解与封装工具类 二、基于node搭建后台websocket服务 首先确认本机电脑中…

c# 操作Microsoft Access数据库

数据库结构为: public static string connting "数据库路径:如:D:\\xxx.mdb";//插入public bool InsertToFile(string casenumber, int lastrowid, int pagecount){bool result true;try{string connString $"ProviderMicr…

在nodeJS 中实现langchain 的Agent (实验笔记)

在nodeJS 中实现langchain 的Agent 实验过程记录如下: 1 构建一个Agent ,使用两个工具 Calculator和TavilySearchResults 2 Tavily Search的API key 的获取 之前一直找不到一个合适的搜索引擎,Google Search 被墙,bing Search …

【Linux】进程(5):命令行参数

大家好,我是苏貝,本篇博客带大家了解Linux进程(5):命令行参数,如果你觉得我写的还不错的话,可以给我一个赞👍吗,感谢❤️ 目录 (A)为什么要有命令…

Paraformer解读(1)基于self-attention和dfsmn的encoder

DFSMN SAN-M python实现 import torch import torch.nn as nn import torch.nn.functional as Fclass PositionalEncoding(nn.Module):def __init__(self, d_model, dropout0.1, max_len5000):super(PositionalEncoding, self).__init__()self.dropout nn.Dropout(pdropout)p…

你管这破玩意儿叫负载均衡?

你管这破玩意儿叫负载均衡? 那么四层负载均衡器是如何工作的呢总结 相信大家都听过这样的一道经典面试题:「请说出在淘宝网输入一个关键词到最终展示网页的整个流程,越详细越好」 这个问题很难,涉及到 HTTP,TCP,网关…

Python第二语言(二、Python语言基础)

目录 1. python中常用的6中数据类型 2. Print语句(输出程序) 3. 字面量 4. 注释 5. 变量 6. 数据类型 7. type()语句:查询数据类型 8. 数据类型转换语句 9. 标识符 10. 算术运算符 11. 赋值运算符 && 复合赋值运算符 12. …

3. redis常见部署架构

redis常见部署架构 一、redis常见部署架构1、常见部署架构2、多实例部署2.1 规划安装目录、配置文件2.2.2 编辑实例配置文件2.2.3 启动实例2.2.4 测试数据读写 3、redis主从复制3.1 规划3.2 从服务器配置3.3 验证主从状态3.4 主从角色切换 4、分片集群4.1 原理4.2 分片集群的部…

CSAPP Lab02——Bomb Lab完成思路详解

看见的看不见的 瞬间的永恒的 青草长啊大雪飘扬 ——月亮之上 完整代码见:CSAPP/bomb at main SnowLegend-star/CSAPP (github.com) 01 字符串比较 简单的把输入的字符串和地址“0x402400”内早已存储的字符串相比较。如果两个字符串相等则函数返回,否…

【Git】如何不管本地文件,强制git pull

要在 Git 中强制执行 git pull 操作,忽略本地文件的更改,可以按照以下步骤操作: 保存当前工作状态:如果你有未提交的更改,可以使用 git stash 将这些更改存储起来。 git stash强制拉取最新代码:使用 git re…

ffmpeg视频编码原理和实战-(2)视频帧的创建和编码packet压缩

源文件&#xff1a; #include <iostream> using namespace std; extern "C" { //指定函数是c语言函数&#xff0c;函数名不包含重载标注 //引用ffmpeg头文件 #include <libavcodec/avcodec.h> } //预处理指令导入库 #pragma comment(lib,"avcodec.…

9.抽象类和接口

抽象类 抽象类概念 在面向对象的概念中&#xff0c;所有的对象都是通过类来描绘的&#xff0c;但是反过来&#xff0c;并不是所有的类都是用来描绘对象的&#xff0c;如果一个类中没有包含足够的信息来描绘一个具体的对象&#xff0c;这样的类就是抽象类 比如&#xff1a; 我…

error /var/lib/jenkins/workspace/*/node_modules/node-sass: Command failed.

原因&#xff1a;node-sass版本不一致 版本图&#xff1a; 解决方案&#xff1a; 进入到jenkins项目目录下&#xff0c;修改package.json文件 将7.0.1改成6.0.1版本

鸿蒙Ability Kit(程序框架服务)【UIExtensionAbility】

UIExtensionAbility 概述 [UIExtensionAbility]是UI类型的ExtensionAbility组件&#xff0c;需要与[UIExtensionComponent]一起配合使用&#xff0c;开发者可以在UIAbility的页面中通过UIExtensionComponent嵌入提供方应用的UIExtensionAbility提供的UI。UIExtensionAbility会…