curl не захватывает страницу на втором проходе, а возвращает пустую строку? - PullRequest
0 голосов
/ 29 июня 2011

У меня есть следующий код:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <curl/curl.h>

char * return_next(char *link, int rand_flag);
char* strip_parens(char* string);
char* strip_itals(char* string);
char* strip_tables(char* string);

struct MemoryStruct {
    char *memory;
    size_t size;
};


static size_t
WriteMemoryCallback(void *ptr, size_t size, size_t nmemb, void *data)
{
size_t realsize = size * nmemb;
struct MemoryStruct *mem = (struct MemoryStruct *)data;

mem->memory = realloc(mem->memory, mem->size + realsize + 1);
if (mem->memory == NULL) {
    /* out of memory! */ 
    printf("not enough memory (realloc returned NULL)\n");
    exit(EXIT_FAILURE);
}

memcpy(&(mem->memory[mem->size]), ptr, realsize);
mem->size += realsize;
mem->memory[mem->size] = 0;

return realsize;
}


int main(void)
{



char *page = malloc(1000);
page = strcpy(page, "http://en.wikipedia.org/wiki/Literature");
char *start = malloc(1000);
start = strcpy(start, page);
printf("%s\n\n", page);
int i = 0, rand_flag = 0;
while(strcmp(page, "http://en.wikipedia.org/wiki/Philosophy")){
    i++;
    page = return_next(page, rand_flag);
    printf("deep: %d, %s\n\n", i, page);
    rand_flag = 0;
}
printf("start link: %s, is %d clicks from philosophy", start, i);

return 0;

}


char * return_next(char *link, int rand_flag){
CURL *curl_handle;
struct MemoryStruct chunk;
chunk.memory = malloc(1); 
chunk.size = 0;    

curl_global_init(CURL_GLOBAL_ALL);
curl_handle = curl_easy_init();
curl_easy_setopt(curl_handle, CURLOPT_URL, link);
curl_easy_setopt(curl_handle, CURLOPT_WRITEFUNCTION, WriteMemoryCallback);
curl_easy_setopt(curl_handle, CURLOPT_WRITEDATA, (void *)&chunk);
curl_easy_setopt(curl_handle, CURLOPT_USERAGENT, "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.1.1) Gecko/20061204 Firefox/2.0.0.1");
if(rand_flag){
    curl_easy_setopt(curl_handle, CURLOPT_FOLLOWLOCATION, 1);   
}
curl_easy_perform(curl_handle);
curl_easy_cleanup(curl_handle);

char *theString = malloc(strlen(chunk.memory)+1);

char *theString1 = malloc(strlen(theString) + 1);

theString = strstr(chunk.memory, "div id=\"body");

theString1 = strip_tables(theString);

if(chunk.memory)
    free(chunk.memory);

theString = strstr(theString1, "<p>");

theString1 = strip_itals(theString);

theString = strip_parens(theString1);

curl_global_cleanup();

return theString;
}

char* strip_parens(char* string) {
long len = strlen(string);
char* result = malloc(len + 1);
int num_parens = 0;
int i, j = 0;
for(i=0; i < len; i++) {
    char c = string[i];
    if(c == '(') {
        num_parens++;
    }
    else if(c == ')' && num_parens > 0) {
        num_parens--;
    }
    else if(num_parens == 0) {
        if(c == '<'){
            if (string[i+1] == 'a'){
                if (string[i+2] == ' ') {
                    if(string[i+3] == 'h'){
                        i = i+9;

                        for(;string[i] != '"'; i++){

                            result[j] = string[i];
                            j++;
                        }
                        result[j] = '\0';
                        len = strlen("http://en.wikipedia.org");
                        char *final = malloc(j+len);
                        final = strcpy(final, "http://en.wikipedia.org");
                        return strcat(final, result);
                    }
                }
            }
        }
    }
}
result[j] = '\0';
return result;
}

char* strip_itals(char* string) {
long len = strlen(string);
char* result = malloc(len + 1);
int inside = 0;
int i, j = 0;
for(i=0; i < len; i++) {
    //printf(".%d, %c, %d\n", i, string[i], inside);
    char c = string[i];
    if(c == '<' && inside == 0) {
        if (string[i+1] == 'i'){
            if (string[i+2] == '>') {
                inside++;
                i = i+2;
            }
        }
    }
    else if(c == '<' && inside > 0) {
        //printf("first if\n");
        if (string[i+1] == '/'){
            if (string[i+2] == 'i') {
                inside--;
                i=i+3;
            }
        }
    }
    if(inside == 0) {
        result[j] = c;
        j++;
    }
}
result[j] = '\0';
return result;
}

char* strip_tables(char* string) {
//printf("%s\n", string);
long len = strlen(string);
//long len = 1000000;

char* result = malloc(len + 1);
int inside = 0;
int i, j = 0;
for(i=0; i < len; i++) {
    //printf(".%d, %c, %d\n", i, string[i], inside);
    char c = string[i];
    if(c == '<' && inside == 0) {
        if (string[i+1] == 't'){
            if (string[i+2] == 'a') {
                if (string[i+3] == 'b') {
                    if (string[i+4] == 'l') {
                        inside++;
                        i = i+4;
                    }
                }
            }
        }
    }
    else if(c == '<' && inside > 0) {
        //printf("first if\n");
        if (string[i+1] == '/'){
            if (string[i+2] == 't') {
                if (string[i+3] == 'a') {
                    if (string[i+4] == 'b') {
                        if (string[i+5] == 'l') {
                            inside--;
                            i=i+7;
                        }
                    }
                }
            }
        }
    }
    if(inside == 0) {
        result[j] = c;
        j++;
    }
}
result[j] = '\0';
return result;
}

При наличии ссылки на статью вики возвращается первая ссылка, затем в основном я перебираю эту функцию, пока не приду к указанной статье. Я выбежал из какой-то случайной статьи и обнаружил, что когда она проходит над «Литературой», на следующей странице появляется «Искусство», но когда она переходит к поиску, «Искусство» curl возвращает пустую строку - если я печатаю («% s», chunk.memory) после звонка я получаю (ноль). Если я вручную заставляю функцию запускаться в искусстве, она работает нормально, тянется до философии. Что касается жизни, я не вижу никаких отличий ... Я вставил несколько диагностических printfs и получил следующее -

это адрес ~>! http://en.wikipedia.org/wiki/Art!, rand flag = 0

Имея ссылку между восклицательными знаками, я знаю, что она правильно обрабатывает ссылку, и в данный момент rand_flag всегда имеет значение 0.

Любые советы, указатели или решения высоко ценится.

Ответы [ 2 ]

1 голос
/ 29 июня 2011

Как правило, невозможно что-либо сказать о программе, если все, что у вас есть, является некомпилируемым фрагментом кода. Поэтому я собираюсь дать некоторые общие рекомендации.

  1. Проверьте возвращаемые значения ваших функций.
  2. Настройте обратные вызовы для libcurl, чтобы вы могли печатать каждый байт, входящий и выходящий, одним щелчком переключателя (очень похоже на curl -v - посмотрите на его источник, если вам нужно руководство).
  3. Наблюдай за сетевым трафиком.
  4. Если вы видите, что запрос вообще не отправляется или отправляется, но данные не возвращаются, вы немного сузили проблему.
0 голосов
/ 29 июня 2011

Код завершен и не будет работать. Позвольте мне проиллюстрировать это фрагментом кода и комментарием:

char * theString = таНос (STRLEN (chunk.memory) +1);

char * theString1 = malloc (strlen (theString) + 1);

Выполнение strlen (theString) вызовет strlen () для указателя, который указывает на неинициализированную память. Может быть что угодно. А затем вы выделяете этот размер и вставляете второй указатель ...

theString = strstr (chunk.memory, "div ID = \ "тело");

... и все же вы снова присваиваете 'theString' позиции в области памяти 'chunk.memory'.

theString1 = strip_tables (theString);

И вы снова присваиваете 'theString1' какой-то позиции в пределах 'theString'.

Теперь вы вытекли два ваших mallocs.

если (chunk.memory) бесплатно (chunk.memory);

И посмотрите, теперь вы освободили данные, на которые указывают два указателя. Теперь они указывают на мусор.

theString = strstr (theString1, "

");

... и теперь вы ищете в данных, которые вы уже освободили.

Мне нужно сказать больше?

...