Github Copilot在AI代码生成领域的地位依然无可动摇
文章目录
由头
公司内部有人前一阵推荐cursor,前一段时间windsurf又因为免费赠送PRO会员火了一阵。
分别试用了一下,交互确实很好,但是项目代码多了以后cursor和windsurf咔咔一顿乱改,经常把自己改的代码来回反复修改,无头苍蝇一样乱撞,项目代码超过300行基本就很难保证稳定了
最近vscode的Github Copilot插件更新了,也增加了和cursor类似的交互方式。试用下来,Github Copilot的代码逻辑比cursor和windsurf更加稳定,生成的代码更加符合预期。
用我个人最喜欢的一个爬虫项目来测试
给Github Copilot的指令:
创建一个rust爬虫项目
项目有几个角色
1. Requester,用来构造一个url的请求,这个角色包含url、ua、cookie、是否使用代理ip等信息
2. Downloader,用来下载一个url的内容,这个角色包含一个Requester,用来构造请求,然后下载内容,包含配置信息,可以配置并发数、间隔时间等
3. Parser,用来解析一个url的内容,这个角色包含一个Downloader,用来下载内容,然后解析内容
4. Saver,用来保存一个url的内容,这个角色包含一个Parser,用来解析内容,然后保存内容
5. Scheduler,Requester、Downloader、Parser、Saver的调度器,用来调度这几个角色的工作
然后让它补充一个README.md
补充一个README.md,内容包括项目特性、设计架构、使用示例、待办事项等
然后这个项目就一把可以上传github了,并且基本不需要太多修改就可以cargo run
了
补充中文注释
当前项目的所有rust代码增加中文注释
补充完注释基本就是一个可读性非常好的项目了,而且Github Copilot生成的代码质量和cursor、windsurf生成的代码质量相比要好很多
最终生成的代码仓库地址
Github Copilot生成的代码:https://github.com/pengxiaochao/rust_crawler
示例代码
use rust_crawler::{Downloader, Parser, Scheduler, Saver, downloader::DownloaderConfig};
use std::sync::Arc;
use anyhow::Result;
use futures::future::join_all;
/// 简单解析器:将内容直接作为字符串返回
#[derive(Clone)]
struct SimpleParser;
#[async_trait::async_trait]
impl Parser for SimpleParser {
type Output = String;
async fn parse(&self, content: &str) -> Result<Self::Output> {
Ok(content.to_string())
}
}
/// 简单保存器:打印内容长度
struct SimpleSaver;
#[async_trait::async_trait]
impl Saver<String> for SimpleSaver {
async fn save(&self, data: String) -> Result<()> {
println!("Saved content length: {}", data.len());
Ok(())
}
}
/// 主函数:启动爬虫系统
#[tokio::main]
async fn main() -> Result<()> {
// 待爬取的 URL 列表
let urls = vec![
"https://www.baidu.com".to_string(),
"https://www.163.com".to_string(),
"https://www.au92.com".to_string(),
];
// 初始化组件
let config = DownloaderConfig::new(3, 1000);
let downloader = Arc::new(Downloader::with_config(config));
let mut scheduler = Scheduler::<SimpleParser>::new(10);
let parser = Arc::new(SimpleParser);
let saver = Arc::new(SimpleSaver);
// 分离调度器
let (sender, receiver) = scheduler.split();
let sender = Arc::new(sender);
let receiver = Arc::new(tokio::sync::Mutex::new(receiver));
// 添加URLs到调度器
sender.add_requests(urls).await?;
// 启动下载任务
let download_tasks = (0..3).map(|_| {
let downloader = downloader.clone();
let receiver = receiver.clone();
let sender = sender.clone();
let parser = parser.clone();
tokio::spawn(async move {
loop {
let req = {
let mut receiver = receiver.lock().await;
receiver.get_request().await
};
match req {
Some(req) => {
if let Ok(content) = downloader.download(&req).await {
if let Ok(parsed) = parser.parse(&content).await {
let _ = sender.add_parsed_data(parsed).await;
}
}
}
None => break,
}
}
})
});
// 启动保存任务
let save_tasks = (0..3).map(|_| {
let receiver = receiver.clone();
let saver = saver.clone();
tokio::spawn(async move {
loop {
let data = {
let mut receiver = receiver.lock().await;
receiver.get_parsed_data().await
};
match data {
Some(data) => {
let _ = saver.save((*data).clone()).await;
}
None => break,
}
}
})
});
// 等待所有任务完成
let all_tasks = download_tasks.chain(save_tasks).collect::<Vec<_>>();
join_all(all_tasks).await;
Ok(())
}
文章作者 pengxiaochao
上次更新 2024-12-17
许可协议 不允许任何形式转载。