Как на Си получить контент страницы сайта?
Почитал разные источники. Типа есть CURL библиотека, она это может. Но она огромная, куча не нужных мне функций. Большая часть из примеров не работает, выводит ошибку типов и т.д. из библиотек. Мне нужно всего лишь получить HTML текст странички, для дальнейшего парсинга. Пишут что можно с помощью winsock2 получить что угодно :) Но примеры тоже не работают :( Разрабатываю в CodeBlocks с компилятором MinGWx64/gcc под Windows 10 64.
Может кто уже делал подобное?
Ссылки и примеры приветствуются (РАБОЧИЕ без танцев с бубном). Я недавно занялся Си, перешел с другого ЯП.
Спасибо заранее за ответы ;)
Ответы (3 шт):
Я недавно занялся Си, перешел с другого ЯП.
Совет таков, что если вы только начали знакомиться с данным языком, то вам стоило бы сначала изучить его основы, работу со строками, как выводить текст на экран, и т.д.
В данный момент, предлагать в ответах то что вы хотите, не разумно по несколькис причинам, одна из них, это то, что у вас не указан компилятор которым вы пользуетесь, не указана ОС.
Средствами самого языка, этого сделать нельзя, здесь необходимо использовать средства которые предлагают платформа и ОС на которой вы работаете, а также некоторые библиотеки, например curl.
Есть 2 варианта получения контента страницы:
Запустить curl с параметрами вывода контента в терминал, и считать его через pipe.
Написать и подключить библиотеку curl.
В любом случае, это не то что необходимо делать начиная знакомство с языком.
#include <stdio.h>
#include <stdlib.h>
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
#include <curl/curl.h>
#ifdef __cplusplus
}
#endif /* __cplusplus */
#define REQUEST_URL ("https://curl.se/libcurl/c/CURLOPT_URL.html")
/* https://curl.se/libcurl/c/CURLOPT_WRITEFUNCTION.html */
struct memory {
char *response;
size_t size;
};
static size_t cb(void *data, size_t size, size_t nmemb, void *clientp) {
size_t realsize = size * nmemb;
struct memory *mem = (struct memory *)clientp;
char *ptr = realloc(mem->response, mem->size + realsize + 1);
if(ptr == NULL)
return 0; /* out of memory! */
mem->response = ptr;
memcpy(&(mem->response[mem->size]), data, realsize);
mem->size += realsize;
mem->response[mem->size] = 0;
return realsize;
}
void
abort_on_error_check(CURLcode code, void(*callback)(void *), void *opaque) {
if (CURLE_OK != code) {
fprintf(stderr, "CURL Error: %s\n", curl_easy_strerror(code));
callback(opaque);
exit(code);
}
}
#define abort_on_error(code) \
abort_on_error_check(code, curl_easy_cleanup, p_curl)
int
main(int argc, char *argv[]) {
CURL *p_curl;
struct memory mem = { 0 };
p_curl = curl_easy_init();
if (NULL == p_curl) {
(void) fprintf(stderr, "CURL init failed\n");
}
abort_on_error(curl_easy_setopt(p_curl, CURLOPT_URL, REQUEST_URL));
abort_on_error(curl_easy_setopt(p_curl, CURLOPT_WRITEDATA, &mem));
abort_on_error(curl_easy_setopt(p_curl, CURLOPT_WRITEFUNCTION, cb));
abort_on_error(curl_easy_perform(p_curl));
fprintf(stdout, mem.response);
free(mem.response);
curl_easy_cleanup(p_curl);
}
gcc main.c -lcurl -o test.exe
output:
evo@evo-pc UCRT64 /d/evo-i/so
$ ./a.exe
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head> <title>CURLOPT_URL</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta content="text/html; charset=UTF-8" http-equiv="Content-Type">
<link rel="stylesheet" type="text/css" href="/curl.css">
<link rel="shortcut icon" href="/favicon.ico">
<link rel="icon" href="/logo/curl-symbol.svg" type="image/svg+xml">
<link rel="alternate" type="application/rss+xml" title="cURL Releases" href="https://github.com/curl/curl/releases.atom">
<link rel="STYLESHEET" type="text/css" href="https://curl.se/manpage.css">
</head>
<body>
<div class="main">
<div class="menu">
<a href="/libcurl/c/libcurl.html" class="menuitem" title="Overview">API Overview</a>
<div class="dropdown">
....
....
....
В итоге поиска и рабочих вариантов не найдено. CURL слишком большой для моих задач и сложен в реализации. Написал на Delphi консольную программку, которая в параметре принимает https адрес и записывает в файл контент. Ну а из Си я это могу парсить и искать то что мне нужно, и сразу в ASCII кодировке.
Всем спасибо.
В принципе, тут нужно только сокеты и немного знания протокола http. И просто послать запрос. Вот как можно поиграть:
(venv) pooh@dell ~ $ telnet httpbin.org 80
Trying 3.234.71.36...
Connected to httpbin.org.
Escape character is '^]'.
GET /ip HTTP/1.1
Host: httpbin.org
HTTP/1.1 200 OK
Date: Tue, 21 Nov 2023 17:35:08 GMT
Content-Type: application/json
Content-Length: 33
Connection: keep-alive
Server: gunicorn/19.9.0
Access-Control-Allow-Origin: *
Access-Control-Allow-Credentials: true
{
"origin": "46.123.245.170"
}
Все, что после пустой строки, уже прислал сервер. Так что если простые запросы, то курл можно не тащить. Однако, если https, то все несколько сложнее…