您好,登录后才能下订单哦!
密码登录
登录注册
点击 登录注册 即表示同意《亿速云用户服务条款》
# 如何使用Scrapy+Splash+Lua滚动爬取CSDN
## 前言
在当今数据驱动的时代,网络爬虫技术成为获取互联网信息的重要手段。对于CSDN这类技术社区,传统的爬虫可能无法有效抓取动态加载的内容。本文将详细介绍如何通过Scrapy+Splash+Lua的组合方案,实现对CSDN页面的滚动爬取,解决JavaScript渲染难题。
## 技术栈介绍
### 1. Scrapy框架
Scrapy是一个用Python编写的开源网络爬虫框架,具有以下特点:
- 高性能的异步处理
- 内置数据提取工具(XPath/CSS选择器)
- 完善的中间件和管道系统
- 可扩展的架构设计
### 2. Splash服务
Splash是一个JavaScript渲染服务,基于Qt WebKit开发,主要功能包括:
- 执行页面中的JavaScript代码
- 模拟鼠标滚动、点击等交互行为
- 返回渲染后的HTML或截图
- 支持Lua脚本控制浏览器行为
### 3. Lua脚本
Lua是一种轻量级脚本语言,在Splash中用于:
- 控制页面加载流程
- 执行复杂的交互操作
- 处理页面等待逻辑
- 返回自定义格式的数据
## 环境搭建
### 1. 安装Scrapy
```bash
pip install scrapy
推荐使用Docker快速部署:
docker pull scrapinghub/splash
docker run -p 8050:8050 scrapinghub/splash
pip install scrapy-splash
在settings.py
中添加以下配置:
SPLASH_URL = 'http://localhost:8050'
DOWNLOADER_MIDDLEWARES = {
'scrapy_splash.SplashCookiesMiddleware': 723,
'scrapy_splash.SplashMiddleware': 725,
'scrapy.downloadermiddlewares.httpcompression.HttpCompressionMiddleware': 810,
}
SPIDER_MIDDLEWARES = {
'scrapy_splash.SplashDeduplicateArgsMiddleware': 100,
}
DUPEFILTER_CLASS = 'scrapy_splash.SplashAwareDupeFilter'
scrapy startproject csdn_crawler
cd csdn_crawler
scrapy genspider csdn "csdn.net"
创建scroll.lua
文件:
function main(splash, args)
-- 设置页面加载超时时间
splash:set_timeout(60)
-- 访问目标URL
assert(splash:go(args.url))
-- 等待页面初始加载
splash:wait(2)
-- 获取页面高度并初始化滚动位置
local scroll_to = splash:jsfunc("window.scrollTo")
local get_body_height = splash:jsfunc(
"function() {return document.body.scrollHeight;}"
)
local scroll_height = get_body_height()
local scroll_step = 500
local current_position = 0
-- 模拟滚动操作
while current_position < scroll_height do
scroll_to(0, current_position)
splash:wait(1) -- 等待内容加载
current_position = current_position + scroll_step
-- 动态更新页面高度(应对懒加载)
scroll_height = get_body_height()
end
-- 最终滚动到底部确保所有内容加载
scroll_to(0, scroll_height)
splash:wait(3)
-- 返回渲染后的HTML和截图
return {
html = splash:html(),
png = splash:png(),
har = splash:har(),
}
end
修改csdn.py
文件:
import scrapy
from scrapy_splash import SplashRequest
class CsdnSpider(scrapy.Spider):
name = 'csdn'
allowed_domains = ['csdn.net']
def start_requests(self):
urls = [
'https://blog.csdn.net/nav/python',
'https://blog.csdn.net/nav/ai',
'https://blog.csdn.net/nav/bigdata'
]
for url in urls:
yield SplashRequest(
url,
self.parse,
endpoint='execute',
args={
'lua_source': open('scroll.lua').read(),
'timeout': 90,
'images': 1
}
)
def parse(self, response):
# 提取文章列表
for article in response.css('article.blog-list-box'):
yield {
'title': article.css('h4 a::text').get().strip(),
'url': article.css('h4 a::attr(href)').get(),
'author': article.css('.user-name::text').get(),
'publish_time': article.css('.time::text').get(),
'read_count': article.css('.read-num::text').get(),
}
# 分页处理(示例)
next_page = response.css('.ui-pager a:contains("下一页")::attr(href)').get()
if next_page:
yield SplashRequest(
response.urljoin(next_page),
self.parse,
endpoint='execute',
args={
'lua_source': open('scroll.lua').read(),
'timeout': 90
}
)
配置pipelines.py
实现数据清洗和存储:
import pymongo
class CsdnPipeline:
def __init__(self, mongo_uri, mongo_db):
self.mongo_uri = mongo_uri
self.mongo_db = mongo_db
@classmethod
def from_crawler(cls, crawler):
return cls(
mongo_uri=crawler.settings.get('MONGO_URI'),
mongo_db=crawler.settings.get('MONGO_DATABASE')
)
def open_spider(self, spider):
self.client = pymongo.MongoClient(self.mongo_uri)
self.db = self.client[self.mongo_db]
def close_spider(self, spider):
self.client.close()
def process_item(self, item, spider):
# 数据清洗
if item.get('read_count'):
item['read_count'] = int(item['read_count'].replace('阅读数:', ''))
# 存储到MongoDB
self.db['csdn_articles'].update_one(
{'url': item['url']},
{'$set': dict(item)},
upsert=True
)
return item
在settings.py
中添加:
DEFAULT_REQUEST_HEADERS = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36',
'Accept': 'text/html,application/xhtml+xml',
'Accept-Language': 'zh-CN,zh;q=0.9',
}
DOWNLOAD_DELAY = 3
RANDOMIZE_DOWNLOAD_DELAY = True
推荐使用scrapy-rotating-proxies
:
ROTATING_PROXY_LIST = [
'ip1:port',
'ip2:port',
# ...
]
使用scrapy-redis
实现分布式爬取:
SCHEDULER = "scrapy_redis.scheduler.Scheduler"
DUPEFILTER_CLASS = "scrapy_redis.dupefilter.RFPDupeFilter"
REDIS_URL = 'redis://localhost:6379'
通过Scrapy+Splash+Lua的组合,我们成功实现了对CSDN动态内容的滚动爬取。这种方案不仅适用于CSDN,还可以扩展到其他JavaScript渲染的网站。在实际应用中,请务必遵守网站的robots.txt协议,合理控制爬取频率,避免给目标网站造成过大负担。
注意:本文仅供技术学习参考,请勿用于非法爬取或商业用途。实际应用中应遵守相关法律法规和网站的使用条款。 “`
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。