2014-10-17 21 views
5

Vì vậy, tôi đã viết một chương trình scraper trang web trong C# bằng cách sử dụng gói HTML Agility. Điều này khá thẳng về phía trước. Ngay cả khi tính toán sự mâu thuẫn trong định dạng trên trang web, nó vẫn chỉ mất một vài giờ để làm việc.Tôi làm cách nào để loại bỏ một trang web bằng cách sử dụng C?

Bây giờ, tôi phải triển khai lại chương trình này trong C để có thể chạy trong môi trường Linux. Đây là một cơn ác mộng lớn.

Tôi có thể kéo lại trang nhưng khi nói đến việc theo dõi qua trang đó để rút ra những phần tôi quan tâm - tôi vẽ rất nhiều khoảng trống. Ban đầu, tôi đã chết trên cố gắng thực hiện một giải pháp tương tự như tùy chọn HTML Agility của tôi trong C# ngoại trừ việc sử dụng Tidy và một số thư viện XML khác để tôi có thể giữ logic của mình nhiều hơn hoặc ít hơn.

Điều này không hiệu quả lắm. Thư viện XML mà tôi có quyền truy cập không xuất hiện để hỗ trợ xpath và tôi không thể cài đặt thư viện đó. Vì vậy, tôi đã sử dụng để cố gắng tìm ra cách đọc qua trang bằng cách sử dụng chuỗi phù hợp để tìm dữ liệu tôi muốn. Tôi không thể không cảm thấy rằng phải có một cách tốt hơn để làm điều này.

Dưới đây là những gì tôi có:

#define HTML_PAGE "codes.html" 

int extract() 
{ 

    FILE *html; 

    int found = 0; 
    char buffer[1000]; 
    char searchFor[80], *cp; 

    html = fopen(HTML_PAGE, "r"); 

    if (html) 
    { 

     // this is too error prone, if the buffer cuts off half way through a section of the string we are looking for, it will fail! 
     while(fgets(buffer, 999, html)) 
     { 
      trim(buffer); 

      if (!found) 
      { 
       sprintf(searchFor, "<strong>"); 
       cp = (char *)strstr(buffer, searchFor); 
       if(!cp)continue; 

       if (strncmp(cp + strlen(searchFor), "CO1", 3) == 0 || strncmp(cp + strlen(searchFor), "CO2", 3) == 0) 
       { 
        got_code(cp + strlen(searchFor)); 
       } 
      } 
     } 
    } 

    fclose(html); 

    return 0; 
} 

got_code(html) 
    char *html; 
{ 
    char code[8]; 
    char *endTag; 
    struct _code_st *currCode; 
    int i; 

    endTag = (char *)strstr(html, "</strong>"); 
    if(!endTag)return; 

    sprintf(code, "%.7s", html); 

    for(i=0 ; i<Data.Codes ; i++) 
     if(strcasecmp(Data.Code[i].Code, code)==0) 
      return; 

    ADD_TO_LIST(currCode, _code_st, Data.Code, Data.Codes); 
    currCode->Code = (char *)strdup(code); 

    printf("Code: %s\n", code); 
} 

Ở trên không hoạt động đúng. Tôi nhận được rất nhiều các mã tôi quan tâm nhưng như tôi đã đề cập ở trên, nếu bộ đệm cắt giảm tại các điểm sai tôi bỏ lỡ một số.

Tôi đã thử đọc toàn bộ đoạn html Tôi quan tâm đến một chuỗi nhưng tôi không thể tìm ra cách xoay vòng thông qua đó - Tôi không thể nhận được bất kỳ mã nào được hiển thị.

Có ai biết cách tôi có thể giải quyết vấn đề này không?

EDIT: Tôi đã suy nghĩ về điều này một số chi tiết. Có cách nào tôi có thể nhìn về phía trước trong tệp và tìm kiếm kết thúc của mỗi 'khối' văn ​​bản mà tôi đang phân tích cú pháp và đặt kích thước bộ đệm là trước khi tôi đọc nó không? Tôi có cần một con trỏ tệp khác vào cùng một tệp không? Điều này sẽ (hy vọng) ngăn chặn các vấn đề của bộ đệm cắt tại những nơi bất tiện.

+0

Có thể chạy bằng Mono? –

+5

C là rất tốt, nhưng không phải cho loại nhiệm vụ này. Sử dụng cái gì khác thay vào đó, như Perl hoặc Python. Địa ngục, ngay cả PHP cũng sẽ làm. –

+0

Vâng, tôi phải đồng ý. Nó chỉ cảm thấy như công cụ sai cho công việc. –

Trả lời

5

Được rồi, vì vậy sau nhiều cú đập đầu vào tường cố gắng tìm ra cách để làm cho mã trên của tôi hoạt động, tôi quyết định thử một cách tiếp cận hơi khác.

Vì tôi biết rằng dữ liệu trên trang tôi đang cào được chứa trên một dòng lớn, tôi đã thay đổi mã của mình để tìm kiếm thông qua tệp cho đến khi tìm thấy nó. Sau đó, tôi tiến xuống dòng tìm kiếm các khối tôi muốn. Điều này làm việc đáng ngạc nhiên tốt và một khi tôi đã có mã đọc một số các khối, nó đã được dễ dàng để thực hiện sửa đổi nhỏ để giải thích cho sự mâu thuẫn trong HTML. Phần mất nhiều thời gian nhất là tìm cách giải cứu một khi tôi đến cuối dòng và tôi giải quyết điều đó bằng cách đạt tới đỉnh để đảm bảo rằng có một khối khác để đọc.

Đây là mã của tôi (đó là xấu xí nhưng chức năng):

#define HTML_PAGE "codes.html" 
#define START_BLOCK "<strong>" 
#define END_BLOCK "</strong>" 

int extract() 
{ 

    FILE *html; 

    int found = 0; 
    char *line = NULL, *endTag, *startTag; 
    size_t len = 0; 
    ssize_t read; 

    char searchFor[80]; 

    html = fopen(HTML_PAGE, "r"); 

    if (html) 
    { 
     while((read = getline(&line, &len, html)) != -1) 
     { 
      if (found) // found line with codes we are interested in 
      { 
       char *ptr = line; 
       size_t nlen = strlen (END_BLOCK); 

       while (ptr != NULL) 
       { 
        sprintf(searchFor, START_BLOCK); 
        startTag = (char *)strstr(ptr, searchFor); 
        if(!startTag) 
        { 
         nlen = strlen (START_BLOCK); 
         ptr += nlen; 
         continue; 
        } 

        if (strncmp(startTag + strlen(searchFor), "CO1", 3) == 0 || strncmp(startTag + strlen(searchFor), "CO2", 3) == 0) 
         got_code(startTag + strlen(searchFor), code); 
        else { 
         nlen = strlen (START_BLOCK); 
         ptr += nlen; 
         continue; 
        } 

        sprintf(searchFor, END_BLOCK); 
        ptr = (char *)strstr(ptr, searchFor); 

        if (!ptr) { found = 0; break; } 

        nlen = strlen (END_BLOCK);     
        ptr += nlen; 

        if (ptr) 
        { 
         // look ahead to make sure we have more to pull out 
         sprintf(searchFor, END_BLOCK); 
         endTag = (char *)strstr(ptr, searchFor); 
         if (!endTag) { break; } 
        } 
       } 

       found = 0; 
       break; 
      } 

      // find the section of the downloaded page we care about 
      // the next line we read will be a blob containing the html we want 
      if (strstr(line, "wiki-content") != NULL) 
      { 
       found = 1; 
      } 
     } 

     fclose(html); 
    } 

    return 0; 
} 

got_code(char *html) 
{ 
    char code[8]; 
    char *endTag; 
    struct _code_st *currCode; 
    int i; 

    endTag = (char *)strstr(html, "</strong>"); 
    if(!endTag)return; 

    sprintf(code, "%.7s", html); 

    for(i=0 ; i<Data.Codes ; i++) 
     if(strcasecmp(Data.Code[i].Code, code)==0) 
      return; 

    ADD_TO_LIST(currCode, _code_st, Data.Code, Data.Codes); 
    currCode->Code = (char *)strdup(code); 

    printf("Code: %s\n", code); 
} 

Gần như không thanh lịch hoặc mạnh mẽ như C# chương trình của tôi nhưng ít nhất nó kéo lại tất cả thông tin mà tôi muốn.

Các vấn đề liên quan