Skip to content

Instantly share code, notes, and snippets.

@paulohrpinheiro
Last active December 7, 2016 17:37
Show Gist options
  • Save paulohrpinheiro/888b35913d4a491ec77dffa53f84c568 to your computer and use it in GitHub Desktop.
Save paulohrpinheiro/888b35913d4a491ec77dffa53f84c568 to your computer and use it in GitHub Desktop.
//! Crawler — My own crawler in Rust!
extern crate hyper; // biblioteca (crate) não padrão
use std::env; // argumentos env::args
use std::io::{Read, Write}; // para IO de arquivos
use std::fs::File; // para criar arquivos
use std::path::Path; // configurar nome de arquivo
use std::thread; // concorrência
const ROBOT_NAME: &'static str = "paulohrpinheiro-crawler";
const BUFFER_SIZE: usize = 512;
fn download_content(url: &str) -> Result<String, String> {
// Somos um respeitável e conhecido bot
let mut headers = hyper::header::Headers::new();
headers.set(hyper::header::UserAgent(ROBOT_NAME.to_string()));
// Pega cabeçalhos (e possivelmente algum dado já)
let client = hyper::Client::new();
let mut response;
match client.get(url).headers(headers).send() {
Err(error) => return Err(format!("{:?}", error)),
Ok(res) => response = res,
}
// Cria arquivo para salvar conteúdo
let filename = Path::new(&url).file_name().unwrap();
let mut localfile;
match File::create(filename) {
Err(error) => return Err(format!("{:?}", error)),
Ok(filehandle) => localfile = filehandle,
}
// pega conteúdo e salva em arquivo
loop {
let mut buffer = [0; BUFFER_SIZE];
match response.read(&mut buffer) {
Err(read_error) => return Err(format!("{:?}", read_error)),
Ok(bytes_read) => {
if bytes_read == 0 {
// não tem mais o que ler
break;
}
// vamos tentar escrever o que pegamos
match localfile.write(&buffer[0..bytes_read]) {
Err(write_error) => return Err(format!("{:?}", write_error)),
Ok(bytes_write) => {
if bytes_write != bytes_read {
return Err("Error in write.".to_string());
}
},
}
},
}
}
return Ok(String::from(filename.to_str().unwrap()));
}
fn main() {
// Pega os argumentos, mas ignorando o primeiro
// que é o nome do programa.
let mut args = env::args();
args.next();
// vetor para as threads que serão criadas
let mut workers = vec![];
// Pega o conteúdo de cada URL
for url in args {
workers.push(thread::spawn(move || {
print!("{} - ", url);
match download_content(&url) {
Err(error) => println!("{:?}", error),
Ok(filename) => println!("{:?}", filename),
}
print!("\n\n");
}));
}
// espera cada thread acabar
for worker in workers {
let _ = worker.join();
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment