LinuxC/C++网络爬虫(1)

版权声明:本文为博主原创文章,遵循 CC 4.0 by-sa 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/hjf161105/article/details/72860095

  网络爬虫(Web Crawler),是一种按照一定的规则,自动的抓取万维网信息的程序或者脚本,有时候又称网络蚂蚁,是搜索引擎(例如:BaiduGoogle……)的重要组成部分。随着Internet的快速发展,网站数量剧增意味着后台数据量的剧增,在这样的情况下,用户能不能通过搜索引擎来及时地得到包含他要查找内容的网页,能不能实现定向搜索……,这些对传统的搜索引擎必然是个巨大的考验。以上这些都是网络爬虫所关心的问题,通过改变网络爬虫的搜索策略,分析策略等,就能在很大程度上解决以上问题。

  传统的网络爬虫一般从一个或若干初始网页的URL开始,抓取初始网页,然后通过URL分析策略,提取已抓取页面上的URL,然后继续重复以上过程,不断从当前页面上抽取新的URL放入队列,直到满足一定的停止条件。

目前已经发布的网络爬虫有

RBSE Eichmann1994)是第一个发布的爬虫。

WebCrawlerPinkerton1994)是第一个公开可用的用来建立全文索引的一个子程序,他使用库www来下载页面。

World Wide Web Worm (McBryan, 1994)是一个用来为文件建立包括标题和URL简单索引的爬虫。索引可以通过grep式的Unix命令来搜索。

GNU Wget是一个在GPL许可下,使用C语言编写的命令行式的爬虫。它主要用于网络服务器和FTP服务器的镜像。

Heritrix是一个互联网档案馆级的爬虫,设计的目标为对大型网络的大部分内容的定期存档快照,是使用java编写的。

  大家常用的搜索引擎,例如BaiduGoogle也都有自己的网络爬虫来帮他们抓取Internet海洋中的网页。这里稍微插一段题外话,其实网络爬虫和网站维护经常都是对立的,因为有些爬虫刷新时间短,有些爬虫比较“笨”,会在网站里迷失了路等情况,引起给网站服务器发送大量请求,造成服务器压力过大而崩溃。但话又说回来,一个设计良好的网络爬虫,再加上使用者良好的素质,是完全可以避免以上情况的。总得来说,网络爬虫带来的好处远远大于它自身和使用者带来的坏处。


  因为刚开始接触这个网络爬虫的缘故,本人对爬虫了解并不是太深,这两天写了一个小程序,实现了通过URL来获取网页源代码。这两天找了很多资料,但是绝大部分的爬虫资料都是Python编写的,少数是JAVA和c#写的,C/C++的版本少之又少,还是需要我继续去学习啊。

#include <iostream>
#include <string>
#include <string.h>
#include <netdb.h>
#include <stdlib.h>

using namespace std;

#define ERROR    -1
#define OK          0
#define PORT      80

void GetUrlAndPath(const string url, string &HostUrl, string &PagePath)
{
    HostUrl = url;
    PagePath = "/";
    //去除 http:// 字符串
    int pos = HostUrl.find("http://");
    if(pos != -1)
    {
        HostUrl = HostUrl.replace(pos, 7, "");
    }

    //去除 https:// 字符串
    pos = HostUrl.find("https://");
    if(pos != -1)
    {
        HostUrl = HostUrl.replace(pos, 8, "");
    }

    //提取主机端口和路径
    pos = HostUrl.find("/");
    if(pos != -1)
    {
        PagePath = HostUrl.substr(pos);
        HostUrl = HostUrl.substr(0, pos);
    }
}

string getpagecontent(const string url)
{
    //记录主机的信息,包括主机名、别名、地址类型、地址长度和地址列表
    struct hostent *host;
    string HostUrl, PagePath;

    //从url获取主机url和路径
    GetUrlAndPath(url, HostUrl, PagePath);

    //通过主机名连接主机
    host = gethostbyname(HostUrl.c_str());
    if(host == 0)
    {
        cout<<"gethostbyname error";
        exit(1);
    }

    struct sockaddr_in addr;
    bzero(&addr, sizeof(addr));
    addr.sin_family = AF_INET;
    addr.sin_port = htons(PORT);
    addr.sin_addr.s_addr = ((struct in_addr*) (host->h_addr))->s_addr;
    int sfd = socket(AF_INET, SOCK_STREAM, 0);
    if(sfd == -1)
    {
        cout<<"create sfd error"<<endl;
        exit(1);
    }

    string requestHeader;
    requestHeader   = "GET " + PagePath + " HTTP/1.1\r\n";
    requestHeader += "Host: " + HostUrl + "\r\n";
    requestHeader += "Accept: */*\r\n";
    requestHeader += "User-Agent: Mozilla/4.0(compatible)\r\n";
    requestHeader += "connection:Keep-Alive\r\n";
    requestHeader += "\r\n";

    int ret = connect(sfd, (const sockaddr*)&addr, sizeof(addr));
    if(ret == -1)
    {
        cout<<"connect error"<<endl;
        exit(1);
    }

    ret = send(sfd, requestHeader.c_str(), requestHeader.size(), 0);
    if(ret == -1)
    {
        cout<<"send error"<<endl;
        exit(1);
    }

    struct timeval timeout = {1, 0};
    setsockopt(sfd, SOL_SOCKET, SO_RCVTIMEO, (char*) &timeout, sizeof(struct timeval));
    char c;
    bool flag = true;
    while(recv(sfd, &c, 1, 0))
    {
        if(c == '\r')
        {
            continue;
        }
        else if(c == '\n')
        {
            if(flag == false)
                break;
            flag = false;
        }
        else
        {
            flag = true;
        }
    }

    int len, BUFFERSIZE = 512;
    char buffer[BUFFERSIZE];
    string pagecontent = "";
    while((len = recv(sfd, buffer, BUFFERSIZE-1, 0)) > 0)
    {
        buffer[len] = '\0';
        pagecontent += buffer;
    }

    return pagecontent;
}

int main()
{
    cout<<getpagecontent("http://www.baidu.com")<<endl;

    return 0;
}


展开阅读全文

没有更多推荐了,返回首页