使用Scrapy爬取掘金热门文章的分析和实现
一、分析掘金网页1. 获取浏览器URL直接页面选择30内最热门的文章可得到URL地址为 https://juejin.im/timeline?sort=monthly_hottest 查看该网页Dom元素发现并没有文章的数据,可得知此为动态网页。2. 获得数据API由此得到获取文章的API为 https://web-api.juejin.im/query3. 分析请求参数在登录状态下...
一、分析掘金网页
1. 获取浏览器URL
直接页面选择30内最热门的文章可得到URL地址为 https://juejin.im/timeline?sort=monthly_hottest 查看该网页Dom元素发现并没有文章的数据,可得知此为动态网页。
2. 获得数据API
由此得到获取文章的API为 https://web-api.juejin.im/query
3. 分析请求参数
在登录状态下访问该接口的 Header
中自定义的参数有:
X-Agent: Juejin/Web
X-Legacy-Device-Id: 1575538149621
X-Legacy-Token: eyJhY2Nlc3NfdG9rZWS4iOiJjMHFEbFBnZ1pFMmZtN3NxIiwicmVmcmVzaF90b2tlbiI6IkVoSXJPSlhvTEhRYlRBZmgiLCJ0b2tlbl90eXBlIjoibWFjIiwiZXhwaXJlX2luIjoyNTkyMDAwfDGQ==
X-Legacy-Uid: 5b502c73f265da0f9d19fc58
POST
的参数为:
{
"operationName":"",
"query":"",
"variables":{
"tags":[
],
"category":"5562b415e4b00c57d9b94ac8",
"first":20,
"after":"",
"order":"MONTHLY_HOTTEST"
},
"extensions":{
"query":{
"id":"653b587c5c7c8a00ddf67fc66f989d42"
}
}
}
未登陆状态下的 Header
自定义参数为:
X-Agent: Juejin/Web
X-Legacy-Device-Id:
X-Legacy-Token:
X-Legacy-Uid:
POST
的参数为:
{
"operationName":"",
"query":"",
"variables":{
"tags":[
],
"category":"5562b415e4b00c57d9b94ac8",
"first":20,
"after":"",
"order":"MONTHLY_HOTTEST"
},
"extensions":{
"query":{
"id":"653b587c5c7c8a00ddf67fc66f989d42"
}
}
}
从上对比得出Header中 X-Legacy-Device-Id
、 X-Legacy-Token
、 X-Legacy-Uid
不必要,只需要 X-Agent: Juejin/Web
即可。 Post
的参数从中推出
Category: 5562b415e4b00c57d9b94ac8 // 此为前端分类的标识
Query : id // 顶部搜索条件
order : // 排序方式
First: // 第一页条数
tags: // Category下的标签
after: //推测为滚动条距离底部的距离 分页相关
返回的数据结构为:
数据结构
{
data: {
articleFeed: {
items: {
edges: [] ,
pageInfo: {
}
}
}
}
}
最终取值应为 edges[index][nodes]
二、抓取数据
1. 使用scrapy创建项目,项目中 item
根据需求配置 item
## 此处我是用的项目名为project_002
class Project002Item(scrapy.Item):
title = scrapy.Field()
content = scrapy.Field()
url = scrapy.Field()
like = scrapy.Field()
user = scrapy.Field()
category = scrapy.Field()
updated_date = scrapy.Field()
article_id = scrapy.Field()
pass
2. 使用命令 scrapy genspider 文件名 网址
生成爬虫文件。
生成后需改造爬虫文件
添加 Header
参数
headers = {
"X-Agent": "Juejin/Web",
"User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.108 Safari/537.36",
"Content-Type": "application/json",
"Host": "web-api.juejin.im",
"Origin": "https://juejin.im"
}
重写 start_requests
方法,由于是直接爬取前100条,就在 first
直接写上100,不做分页处理。
def start_requests(self):
url = 'https://web-api.juejin.im/query'
query_data = {"operationName":"","query":"","variables":{"first":100,"after":"","order":"MONTHLY_HOTTEST"},"extensions":{"query":{"id":"21207e9ddb1de777adeaca7a2fb38030"}}}
response = scrapy.Request(url, method="POST",headers=self.headers, body=json.dumps(query_data),callback=self.parse_item)
yield response
回调方法处理
def parse_item(self, response):
item = Project002Item()
edges = json.loads(response.text)['data']['articleFeed']['items']['edges']
temp = []
for edge in edges:
node = edge['node']
temp.append({"title": node['title'], "url": node['originalUrl'], "like": node['likeCount'], 'content': node['content'], 'user': node['user']['username'], 'updated_date': node['updatedAt'], 'category': node['category']['name'], 'article_id': node['id']})
item = temp
return item
三、储存到数据库
将配置文件的 ITEM_PIPELINES
选项打开,在 pipelines
写入以下代码(数据库需要设计相应字段的表):
def __init__(self):
db = {
'host': '127.0.0.1',
'port': 3306,
'user': 'root',
'password': 'root',
'database': 'spiders',
'charset': 'utf8'
}
self.conn = pymysql.connect(**db)
self.cursor = self.conn.cursor()
def process_item(self, item, spider):
self.cursor.execute("""INSERT IGNORE INTO juejin (id,title,`url`,`like`,content,category,user,updated_date,article_id)
VALUES (null,%s,%s,%s,%s,%s,%s,%s,%s)""",
(item['title'],
item['url'],
item['like'], item['content'], item['category'], item['user'],
item['updated_date'],
item['article_id']
)
)
self.conn.commit()
使用 scrapy crawl 爬虫名
即可存储相应数据
总结
掘金的爬虫相对比较简单,反爬机制几乎没有,非常适合入门练手。
完整代码
更多推荐
所有评论(0)