Suck the cat with code! This paper is participating in[Cat Essay Campaign].

Get cute cat memes with Rust.

The required depend on

The dependencies used in this article are Hyper, hyper-TLS, scraper, and Tokio

  • hyper: HTTPUnderlying implementation library
  • hyper-tls: HTTPSTo realize library
  • scraper: parsinghtmllibrary
  • tokioThe asynchronous runtime of the Rust programming language provides an asynchronous event-driven platform for building fast, reliable and lightweight web applications

You don’t need to rely on Hyper-TLS if the target site is not HTTPS. To create a client, use client ::new()

steps

  1. Create a project

Create a Rust project by running the Cargo New project name command in a command window

  1. Join the rely on

Add the dependencies described above to the Cargo. Toml file. Cargo. Toml as follows:

[package]
edition = "2021"
name = "cat"
version = "0.1.0 from"

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
hyper = {version = "0.14", features = ["full"]}
hyper-tls = "0.5.0"
scraper = "0.12.0"
tokio = {version = "1", features = ["full"]}

Copy the code
  1. Analyze target websites

Search for cats on emoji sites and press F12 to analyze the page structure. Use the Location button to locate a random emoji element. The left click is responsible for that element in the options that appearThe selector

Paste the copied selector into the text as follows: Thumbnail > a > img: #post_container > li:nth-child(2) > div. Thumbnail > a > img: #post_container > li:nth-child(2) > div. Thumbnail > a > img

  1. Construct and initiatehttp/httpsRequest to get page data
// Build the requesting client
let https = HttpsConnector::new();
let client = Client::builder().build::<_, hyper::Body>(https);

let url = "http://www.*********.com/?s=%E7%8C%AB%E5%92%AA";
// Initiate a request for web page data,
letresponse = client.get(url.parse()?) .await? ;Copy the code
  1. usescraperParsing response data
// Get the response data
let bytes = body::to_bytes(response.into_body()).await? ;/ / parse HTML
let document = Html::parse_document(String::from_utf8(bytes.to_vec()).unwrap().as_ref());
Copy the code
  1. useCSS selectorsFind the elements you need
let selector = Selector::parse("div.thumbnail > a > img").unwrap();

// Loop through the selected IMG tag
for element in document.select(&selector) {
}
Copy the code
  1. Of the elementsrcandaltattribute
  • src: The Internet address of the emoji
  • alt: Used to rename emojis
// Get the SRC attribute of the img tag
let src = element.value().attr("src").unwrap();
let alt = element.value().attr("alt").unwrap().to_string();
Copy the code
  1. Create the name of the storage directory and build the emoji
/** * Concatenates the file save path ** / according to the IMG tag Alt attribute
fn get_file_name(alt: &String) - >String {
    let mut tmp_dir = "E:\\img\\".to_string();

    // The target is created if it does not exist
    fs::create_dir_all(&tmp_dir).unwrap();

    let names: Vec<_> = alt.split("[").collect();
    let name = names.first().unwrap();
    let name = name.trim();
    let name = name.replace("?"."");
    tmp_dir += &name;
    tmp_dir += &".gif";

    return tmp_dir;
}
Copy the code
  1. Get emojis and save them locally

Request the address obtained by the SRC attribute above and save the emoji locally using the fs::write method

 // Request the network address of the emoticons to get the emoticons file
letresponse = client.get(src.parse()?) .await? ;let body = hyper::body::to_bytes(response).await? ;// Write the file to local diskfs::write(&tmp_dir, body.iter())? ;Copy the code

The complete code

use hyper::body;
use hyper::Client;
use hyper_tls::HttpsConnector;
use scraper::Html;
use scraper::Selector;
use std::fs;

#[tokio::main(flavor = "current_thread")]
async fn main() - >Result< (),Box<dyn std::error::Error>> {
    // Build the requesting client
    let https = HttpsConnector::new();
    let client = Client::builder().build::<_, hyper::Body>(https);

    let url = "http://www.*********.com/?s=%E7%8C%AB%E5%92%AA";
    // Initiate a request for web page data,
    letresponse = client.get(url.parse()?) .await? ;ifres.status() ! =200 {
        panic!("Request failed");
    }

    // Get the response data
    let bytes = body::to_bytes(res.into_body()).await? ;/ / parse HTML
    let document = Html::parse_document(String::from_utf8(bytes.to_vec()).unwrap().as_ref());
    let selector = Selector::parse("div.thumbnail > a > img").unwrap();

    // Loop through the selected IMG tag
    for element in document.select(&selector) {
        println!("{:? }", element.value());

        // Get the SRC attribute of the img tag
        let src = element.value().attr("src").unwrap();
        let alt = element.value().attr("alt").unwrap().to_string();

        // Concatenate the file save path according to the Alt attribute of the IMG tag
        let tmp_dir = get_file_name(&alt);
        println!("path: {}", tmp_dir);

        // Request the network address of the emoticons to get the emoticons file
        letresponse = client.get(src.parse()?) .await? ;let body = hyper::body::to_bytes(response).await? ;// Write the file to local diskfs::write(&tmp_dir, body.iter())? ; }Ok(())}/** * Concatenates the file save path ** / according to the IMG tag Alt attribute
fn get_file_name(alt: &String) - >String {
    let mut tmp_dir = "E:\\img\\".to_string();
    // The target is created if it does not exist
    fs::create_dir_all(&tmp_dir).unwrap();

    let names: Vec<_> = alt.split("[").collect();
    let name = names.first().unwrap();
    let name = name.trim();
    let name = name.replace("?"."");
    tmp_dir += &name;
    tmp_dir += &".gif";

    return tmp_dir;
}
Copy the code

Running effect