2008-12-23 34 views
26

Tôi muốn viết một chương trình trong C/C++ sẽ tự động đọc một trang web và trích xuất thông tin từ nó. Ví dụ, hãy tưởng tượng nếu bạn muốn viết một ứng dụng để theo dõi và đăng nhập một phiên đấu giá ebay. Có cách nào dễ dàng để lấy trang web không? Một thư viện cung cấp chức năng này? Và có cách nào dễ dàng để phân tích trang để nhận dữ liệu cụ thể không?Lập trình đọc một trang web

+6

RẤT khó khăn trong C/C++. Nó thậm chí còn gây phiền nhiễu ngay cả trong các ngôn ngữ có hỗ trợ mở rộng cho các biểu thức chính quy, phân tích cú pháp XML, các phương thức HTTP, v.v. (ví dụ Java). Đối với Ebay nó có một API bạn nên sử dụng. – cletus

Trả lời

35

Có một cái nhìn tại cURL library:

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

int main(void) 
{ 
    CURL *curl; 
    CURLcode res; 

    curl = curl_easy_init(); 
    if(curl) { 
    curl_easy_setopt(curl, CURLOPT_URL, "curl.haxx.se"); 
    res = curl_easy_perform(curl); 
     /* always cleanup */ 
    curl_easy_cleanup(curl); 
    } 
    return 0; 
} 

BTW, nếu C++ không cần chặt chẽ. Tôi khuyến khích bạn thử C# hoặc Java. Nó dễ dàng hơn nhiều và có một cách tích hợp sẵn.

+4

+1 cho cURL - Tôi đã sử dụng cURL trong một trong các ứng dụng C++ của mình và nó hoạt động tốt, ngay cả với proxy và tất cả các chướng ngại vật khác mà bạn có thể gặp phải. – BlaM

+0

Bạn nên sử dụng đúng công cụ cho công việc! – xtofl

+2

Nó sẽ là tốt hơn để trả về một lỗi nếu curl là null (trong ví dụ trên). –

2

Bạn có thể làm điều đó với lập trình socket, nhưng thật khó để thực hiện các phần của giao thức cần thiết để tìm nạp một trang đáng tin cậy. Tốt hơn là sử dụng thư viện, chẳng hạn như neon. Điều này có thể được cài đặt trong hầu hết các bản phân phối Linux. Trong FreeBSD, hãy sử dụng thư viện tìm nạp.

Để phân tích cú pháp dữ liệu, vì nhiều trang không sử dụng XML hợp lệ, bạn cần triển khai chẩn đoán, chứ không phải trình phân tích cú pháp dựa trên yacc thực. Bạn có thể thực hiện chúng bằng cách sử dụng cụm từ thông dụng hoặc máy chuyển tiếp trạng thái. Như những gì bạn đang cố gắng để làm liên quan đến rất nhiều thử và lỗi bạn tốt hơn bằng cách sử dụng một ngôn ngữ kịch bản, như Perl. Do độ trễ mạng cao, bạn sẽ không thấy bất kỳ sự khác biệt nào về hiệu suất.

+0

Mặc dù chúng không hợp lệ XML, nhiều ngôn ngữ có thư viện có trình phân tích cú pháp HTML, cho phép bạn sử dụng giao diện DOM để phân tích cú pháp tài liệu HTML. –

+0

Vâng, neon cũng đẹp quá (nhưng hầu hết kinh nghiệm của tôi là với curl, như đã đề cập trong câu trả lời của m3rLinEz. – bortzmeyer

2

Thử sử dụng thư viện, như Qt, có thể đọc dữ liệu từ trên mạng và lấy dữ liệu ra khỏi tài liệu xml. This là ví dụ về cách đọc nguồn cấp dữ liệu xml. Bạn có thể sử dụng nguồn cấp dữ liệu ebay chẳng hạn.

2

Có một thư viện TCP/IP miễn phí cho Windows hỗ trợ HTTP và HTTPS - sử dụng nó rất đơn giản.

Ultimate TCP/IP

CUT_HTTPClient http; 
http.GET("http://folder/file.htm", "c:/tmp/process_me.htm");  

Bạn cũng có thể GET tập tin và lưu trữ chúng trong một bộ nhớ đệm (thông qua CUT_DataSource các lớp thừa kế). Tất cả các hỗ trợ HTTP thông thường là có - PUT, HEAD, vv Hỗ trợ cho các máy chủ proxy là một khoe, như là các ổ cắm an toàn.

3

Bạn không đề cập đến bất kỳ nền tảng nào, vì vậy tôi cung cấp cho bạn câu trả lời cho Win32.

Một cách đơn giản để tải xuống mọi thứ từ Internet là URLDownloadToFile với thông số IBindStatusCallback được đặt thành NULL. Để làm cho hàm hữu ích hơn, giao diện gọi lại cần được triển khai.

14

mã Windows:

#include <winsock2.h> 
#include <windows.h> 
#include <iostream> 
#pragma comment(lib,"ws2_32.lib") 
using namespace std; 
int main(){ 
    WSADATA wsaData; 
    if (WSAStartup(MAKEWORD(2,2), &wsaData) != 0) { 
     cout << "WSAStartup failed.\n"; 
     system("pause"); 
     return 1; 
    } 
    SOCKET Socket=socket(AF_INET,SOCK_STREAM,IPPROTO_TCP); 
    struct hostent *host; 
    host = gethostbyname("www.google.com"); 
    SOCKADDR_IN SockAddr; 
    SockAddr.sin_port=htons(80); 
    SockAddr.sin_family=AF_INET; 
    SockAddr.sin_addr.s_addr = *((unsigned long*)host->h_addr); 
    cout << "Connecting...\n"; 
    if(connect(Socket,(SOCKADDR*)(&SockAddr),sizeof(SockAddr)) != 0){ 
     cout << "Could not connect"; 
     system("pause"); 
     return 1; 
    } 
    cout << "Connected.\n"; 
    send(Socket,"GET/HTTP/1.1\r\nHost: www.google.com\r\nConnection: close\r\n\r\n", strlen("GET/HTTP/1.1\r\nHost: www.google.com\r\nConnection: close\r\n\r\n"),0); 
    char buffer[10000]; 
    int nDataLength; 
    while ((nDataLength = recv(Socket,buffer,10000,0)) > 0){   
     int i = 0; 
     while (buffer[i] >= 32 || buffer[i] == '\n' || buffer[i] == '\r') { 
      cout << buffer[i]; 
      i += 1; 
     } 
    } 
    closesocket(Socket); 
     WSACleanup(); 
    system("pause"); 
    return 0; 
} 
+1

Hãy cẩn thận khi đăng bản sao và dán các câu trả lời soạn sẵn/trả lời đúng cho nhiều câu hỏi, những câu hỏi này có xu hướng bị cộng đồng gắn cờ là "spam". Nếu bạn đang làm điều này thì điều đó thường có nghĩa là các câu hỏi là các bản sao để gắn cờ chúng như vậy: http://stackoverflow.com/a/12374407/419 – Kev

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