在windows在下面C++由Http协议抓取网页的内容:

首先介绍了两个重要的包(平时linux在开源包,在windows下一个被称为动态链接库dll):curl包和pthreads_dll,其中curl包解释为命令行浏览器。通过调用内置的curl_easy_setopt等函数就可以实现特定的网页内容获取(正确的编译导入的curl链接库,还须要另外一个包C-ares)。pthreads是多线程控制包,其中包括了相互排斥变量加锁和解锁。

程序进程分配等函数。

下载地址:点击打开链接。当中要正确的导入外接动态链接库,须要步骤:1,项目->属性->配置属性->C/C++->常规->附加包括文件夹(加入include的路径),2。项目->属性->配置属性->连接器->常规->附加库文件夹(加入lib包括的路径);3,在链接器->输入->附加依赖项(libcurld.lib ;pthreadVC2.lib;ws2_32.lib。winmm.lib;wldap32.lib;areslib.lib加入)4,在c/c++->预处理器->预处理器定义(_CONSOLE;BUILDING_LIBCURL;HTTP_ONLY)

详细实现过程介绍:

1:自己定义hashTable结构。用以存储获取的string字符。以hashTable类的形式实现。包括hash表set类型,以及add、find和几种常见的string哈希方式函数

Code:

///HashTable.h
#ifndef HashTable_H
#define HashTable_H #include <set>
#include <string>
#include <vector> class HashTable
{
public:
HashTable(void);
~HashTable(void);
unsigned int ForceAdd(const std::string& str);
unsigned int Find(const std::string& str); /*string的常见的hash方式*/
unsigned int RSHash(const std::string& str);
unsigned int JSHash (const std::string& str);
unsigned int PJWHash (const std::string& str);
unsigned int ELFHash (const std::string& str);
unsigned int BKDRHash(const std::string& str);
unsigned int SDBMHash(const std::string& str);
unsigned int DJBHash (const std::string& str);
unsigned int DEKHash (const std::string& str);
unsigned int BPHash (const std::string& str);
unsigned int FNVHash (const std::string& str);
unsigned int APHash (const std::string& str); private:
std::set<unsigned int> HashFunctionResultSet;
std::vector<unsigned int> hhh;
};
#endif
/////HashTable.cpp
#include "HashTable.h" HashTable::HashTable(void)
{
} HashTable::~HashTable(void)
{
} unsigned int HashTable::ForceAdd(const std::string& str)
{
unsigned int i=ELFHash(str);
HashFunctionResultSet.insert(i);
return i;
} unsigned int HashTable::Find(const std::string& str)
{
int ff=hhh.size();
const unsigned int i=ELFHash(str);
std::set<unsigned int>::const_iterator it;
if(HashFunctionResultSet.size()>0)
{
it=HashFunctionResultSet.find(i);
if(it==HashFunctionResultSet.end())
return -1;
}
else
{
return -1;
}
return i;
} /*几种常见的字符串hash方式实现函数*/
unsigned int HashTable::APHash(const std::string& str)
{
unsigned int hash=0xAAAAAAAA;
for(std::size_t i=0;i<str.length();i++)
{
hash^=((i & 1) == 0) ? ( (hash << 7) ^ str[i] * (hash >> 3)) :
(~((hash << 11) + str[i] ^ (hash >> 5)));
}
return hash;
} unsigned int HashTable::BKDRHash(const std::string& str)
{
unsigned int seed=131; //31 131 1313 13131 131313 etc
unsigned int hash=0;
for(std::size_t i=0;i<str.length();i++)
{
hash=(hash*seed)+str[i];
}
return hash;
} unsigned int HashTable::BPHash(const std::string& str)
{
unsigned int hash = 0;
for(std::size_t i = 0; i < str.length(); i++)
{
hash = hash << 7 ^ str[i];
}
return hash;
} unsigned int HashTable::DEKHash(const std::string& str)
{
unsigned int hash = static_cast<unsigned int>(str.length());
for(std::size_t i = 0; i < str.length(); i++)
{
hash = ((hash << 5) ^ (hash >> 27)) ^ str[i];
}
return hash;
} unsigned int HashTable::DJBHash(const std::string& str)
{
unsigned int hash = 5381; for(std::size_t i = 0; i < str.length(); i++)
{
hash = ((hash << 5) + hash) + str[i];
}
return hash;
} unsigned int HashTable::ELFHash(const std::string& str)
{
unsigned int hash=0;
unsigned int x=0;
for(std::size_t i = 0; i < str.length(); i++)
{
hash=(hash<<4)+str[i];
if((x = hash & 0xF0000000L) != 0)
hash^=(x>>24);
hash&=~x;
}
return hash;
} unsigned int HashTable::FNVHash(const std::string& str)
{
const unsigned int fnv_prime = 0x811C9DC5;
unsigned int hash = 0;
for(std::size_t i = 0; i < str.length(); i++)
{
hash *= fnv_prime;
hash ^= str[i];
}
return hash;
} unsigned int HashTable::JSHash(const std::string& str)
{
unsigned int hash = 1315423911;
for(std::size_t i = 0; i < str.length(); i++)
{
hash ^= ((hash << 5) + str[i] + (hash >> 2));
}
return hash;
} unsigned int HashTable::PJWHash(const std::string& str)
{
unsigned int BitsInUnsignedInt = (unsigned int)(sizeof(unsigned int) * 8);
unsigned int ThreeQuarters = (unsigned int)((BitsInUnsignedInt * 3) / 4);
unsigned int OneEighth = (unsigned int)(BitsInUnsignedInt / 8);
unsigned int HighBits = (unsigned int)(0xFFFFFFFF) << (BitsInUnsignedInt - OneEighth);
unsigned int hash = 0;
unsigned int test = 0; for(std::size_t i = 0; i < str.length(); i++)
{
hash = (hash << OneEighth) + str[i];
if((test = hash & HighBits) != 0)
hash = (( hash ^ (test >> ThreeQuarters)) & (~HighBits));
}
return hash;
} unsigned int HashTable::RSHash(const std::string& str)
{
unsigned int b = 378551;
unsigned int a = 63689;
unsigned int hash = 0; for(std::size_t i = 0; i < str.length(); i++)
{
hash = hash * a + str[i];
a = a * b;
}
return hash;
} unsigned int HashTable::SDBMHash(const std::string& str)
{
unsigned int hash = 0;
for(std::size_t i = 0; i < str.length(); i++)
{
hash = str[i] + (hash << 6) + (hash << 16) - hash;
}
return hash;
}

2:实现进程间的相互排斥处理函数(另外提供进行当前操作的进程ID,以便加锁机制)。以SingleTone类实现。该类仅仅能有静态函数Instance建立一个唯一的类对象。以相互排斥的方式实现对hashTable的基本操作。其中的变量加锁和解锁有mutex类来实现,详细參见代码:

////mutex.h
#ifndef mutex_H
#define mutex_H #pragma once #include "pthread.h" class mutex
{
pthread_mutex_t& m_mutex;
public:
mutex(pthread_mutex_t& m):m_mutex(m)
{
pthread_mutex_lock(&m_mutex);
} ~mutex(void)
{
pthread_mutex_unlock(&m_mutex);
}
};
#endif
////SingleTone.h
#ifndef SingleTone_H
#define SingleTone_H #include <string>
#include <list>
#include <map>
#include "Constants.h"
#include "HashTable.h"
#include "pthread.h"
#include "curl/curl.h" class SingleTone{ public:
static SingleTone* Instance();
void push_back(std::string s);
void pop_back();
int size();
std::list<std::string>::reference back();
std::list<std::string>::iterator begin();
std::list<std::string>::iterator end();
void push_front(std::string s);
bool empty(); unsigned int Get_m_UniqueMap_ForceAdd(const std::string& key,const std::string& url);
unsigned int Get_m_UniqueMap_Find(const std::string& key,const std::string& url);
HashTable Get_m_UniqueMap(const std::string& key);
void Set_m_UniqueMap(const std::string& key,HashTable& hash);
CURL* GetpCurl(); protected:
SingleTone();
~SingleTone();
pthread_mutex_t m_singleton_mutex; private:
static SingleTone* m_pSingleTone;
std::list<std::string> m_LinkStack;
std::map<std::string,HashTable> m_UniqueMap;
CURL *m_pcurl;
};
#endif
#include "SingleTone.h"
#include "mutex.h" SingleTone* SingleTone::m_pSingleTone=NULL; SingleTone::SingleTone()
{
pthread_mutex_init(&m_singleton_mutex,NULL);
m_pcurl=curl_easy_init();
} SingleTone::~SingleTone()
{
pthread_mutex_destroy(&m_singleton_mutex);
} SingleTone* SingleTone::Instance()
{
if(m_pSingleTone==NULL){
m_pSingleTone=new SingleTone();
}
return (m_pSingleTone);
} void SingleTone::push_back(std::string s)
{
mutex m(m_singleton_mutex);
return m_LinkStack.push_back(s);
} void SingleTone::pop_back()
{
mutex m(m_singleton_mutex);
return m_LinkStack.pop_back();
} int SingleTone::size()
{
return m_LinkStack.size();
} std::list<std::string>::iterator SingleTone::begin()
{
return m_LinkStack.begin();
} std::list<std::string>::reference SingleTone::back()
{
mutex m(m_singleton_mutex);
return m_LinkStack.back();
} std::list<std::string>::iterator SingleTone::end()
{
return m_LinkStack.end();
} void SingleTone::push_front(std::string s)
{
mutex m(m_singleton_mutex);
return m_LinkStack.push_front(s);
} bool SingleTone::empty()
{
return m_LinkStack.empty();
} unsigned int SingleTone::Get_m_UniqueMap_ForceAdd(const std::string& key,const std::string& url)
{
mutex m(m_singleton_mutex);
return m_UniqueMap[key].ForceAdd(url);
} unsigned int SingleTone::Get_m_UniqueMap_Find(const std::string& key,const std::string& url)
{ HashTable hss = m_UniqueMap[key];
unsigned int uiRet =hss.Find(url);
//unsigned int uiRet = m_UniqueMap[key]->Find(url);
return uiRet;
} HashTable SingleTone::Get_m_UniqueMap(const std::string& key)
{
return m_UniqueMap[key];
} void SingleTone::Set_m_UniqueMap(const std::string& key,HashTable& hash)
{
m_UniqueMap[key] = hash; } CURL* SingleTone::GetpCurl()
{
return m_pcurl;
}

3:实现HTTP对网页内容的获取:功能包括初始网页内容的获取,和URL设置等函数。这个过程要求是相互排斥的,所以引入SingleTone类的内容。

Code:

/////Http.h
#ifndef Http_H
#define Http_H #include "curl/curl.h"
#include "pthread.h"
#include <string> using namespace std; class Http
{
public:
Http(void);
~Http(void);
bool InitCurl(void);
bool InitCurl(const std::string& url, std::string& szbuffer);
bool DeInitCurl();
void setUrl(const std::string& url);
string setUrl();
const string getBuffer(); private:
static void writer(void* buffer,size_t size,size_t nmemb,void* f);
int setBuffer(char* buffer,size_t size,size_t nmemb);
CURL *m_pcurl;
char m_errorBuffer[CURL_ERROR_SIZE];
string m_szbuffer;
string m_szUrl;
pthread_mutex_t m_http_mutex;
};
#endif
#include "Http.h"
#include "SingleTone.h"
#include "mutex.h" Http::Http(void)
{
m_pcurl=SingleTone::Instance()->GetpCurl();
} Http::~Http(void)
{
} bool Http::InitCurl(void)
{
return false;
} int Http::setBuffer(char *buffer, size_t size, size_t nmemb)
{
int result = 0;
if (buffer!=NULL)
{
m_szbuffer.append(buffer, size * nmemb);
result = size * nmemb;
}
buffer = NULL ;
return result;
} void Http::writer(void *buffer, size_t size, size_t nmemb,void* f)
{
static_cast<Http*>(f)->setBuffer((char*)buffer,size,nmemb);
} bool Http::InitCurl(const std::string& url, std::string& szbuffer)
{
pthread_mutex_init(&m_http_mutex,NULL);
Http::m_szUrl=url;
CURLcode result;
if(m_pcurl)
{
curl_easy_setopt(m_pcurl, CURLOPT_ERRORBUFFER, Http::m_errorBuffer);
curl_easy_setopt(m_pcurl, CURLOPT_URL,m_szUrl.c_str());
curl_easy_setopt(m_pcurl, CURLOPT_HEADER, 0);
curl_easy_setopt(m_pcurl, CURLOPT_FOLLOWLOCATION, 1);
curl_easy_setopt(m_pcurl, CURLOPT_WRITEFUNCTION,Http::writer);
curl_easy_setopt(m_pcurl, CURLOPT_WRITEDATA,this); result = curl_easy_perform(m_pcurl);
}
if(result!=CURLE_OK)
return false;
szbuffer=m_szbuffer;
m_szbuffer.clear();
m_szUrl.clear();
pthread_mutex_destroy(&m_http_mutex);
return true;
} bool Http::DeInitCurl()
{
curl_easy_cleanup(m_pcurl);
curl_global_cleanup();
m_pcurl = NULL; return true;
} const string Http::getBuffer()
{
return m_szbuffer;
} string Http::setUrl()
{
return Http::m_szUrl;
} void Http::setUrl(const std::string& url)
{
Http::m_szUrl = url;
}

当中 m_szbuffer存放网页的内容。

初始网页的内容存放在Init形函数参数。

版权声明:本文博客原创文章。博客,未经同意,不得转载。

网络爬虫WebCrawler(1)-Http网页内容抓取的更多相关文章

  1. iOS—网络实用技术OC篇&网络爬虫-使用java语言抓取网络数据

    网络爬虫-使用java语言抓取网络数据 前提:熟悉java语法(能看懂就行) 准备阶段:从网页中获取html代码 实战阶段:将对应的html代码使用java语言解析出来,最后保存到plist文件 上一 ...

  2. iOS开发——网络实用技术OC篇&网络爬虫-使用java语言抓取网络数据

    网络爬虫-使用java语言抓取网络数据 前提:熟悉java语法(能看懂就行) 准备阶段:从网页中获取html代码 实战阶段:将对应的html代码使用java语言解析出来,最后保存到plist文件 上一 ...

  3. [Python]网络爬虫(一):抓取网页的含义和URL基本构成

    一.网络爬虫的定义 网络爬虫,即Web Spider,是一个很形象的名字. 把互联网比喻成一个蜘蛛网,那么Spider就是在网上爬来爬去的蜘蛛.网络蜘蛛是通过网页的链接地址来寻找网页的. 从网站某一个 ...

  4. Python网络爬虫(Get、Post抓取方式)

    简单的抓取网页 import urllib.request url="http://google.cn/" response=urllib.request.urlopen(url) ...

  5. Python_网络爬虫(新浪新闻抓取)

    爬取前的准备: BeautifulSoup的导入:pip install BeautifulSoup4 requests的导入:pip install requests 下载jupyter noteb ...

  6. 爬虫学习一系列:urllib2抓取网页内容

    爬虫学习一系列:urllib2抓取网页内容 所谓网页抓取,就是把URL地址中指定的网络资源从网络中读取出来,保存到本地.我们平时在浏览器中通过网址浏览网页,只不过我们看到的是解析过的页面效果,而通过程 ...

  7. python爬虫构建代理ip池抓取数据库的示例代码

    爬虫的小伙伴,肯定经常遇到ip被封的情况,而现在网络上的代理ip免费的已经很难找了,那么现在就用python的requests库从爬取代理ip,创建一个ip代理池,以备使用. 本代码包括ip的爬取,检 ...

  8. python爬虫之分析Ajax请求抓取抓取今日头条街拍美图(七)

    python爬虫之分析Ajax请求抓取抓取今日头条街拍美图 一.分析网站 1.进入浏览器,搜索今日头条,在搜索栏搜索街拍,然后选择图集这一栏. 2.按F12打开开发者工具,刷新网页,这时网页回弹到综合 ...

  9. python3下scrapy爬虫(第三卷:初步抓取网页内容之抓取网页里的指定数据)

    上一卷中我们抓取了网页的所有内容,现在我们抓取下网页的图片名称以及连接 现在我再新建个爬虫文件,名称设置为crawler2 做爬虫的朋友应该知道,网页里的数据都是用文本或者块级标签包裹着的,scrap ...

随机推荐

  1. 基于CentOS 5.4搭建nginx+php+spawn-fcgi+mysql高性能php平台

    一.安装准备 1.1平台环境: CentOS 5.4 x86_64 GNU/Linux nginx-0.8.21 php-5.2.9 spawn-fcgi-1.6.3 mysql-5.1.34 .2系 ...

  2. JavaScript 常见陷阱

    JavaScript中的一些特性和通常我们想象的不太一样.这里我总结了一些有悖直觉的语言特性. 1 数组 1.1 数组的遍历 在直接支持for a in b的语言中,比方Python/Ruby里的a的 ...

  3. WCF扩展之实现ZeroMQ绑定和protocolBuffer消息编码(三)实现ReplyChannel(2016-03-15 12:35)

    这是这个系列的第三篇,其他的文章请点击下列目录 WCF扩展之实现ZeroMQ绑定和protocolBuffer消息编码(一)概要设计 WCF扩展之实现ZeroMQ绑定和protocolBuffer消息 ...

  4. [转载]使用python上传图片到 yeelink

    #/bin/env python # -*-coding:utf=8 -*- import os,time,subprocess,shlex import urllib2 def upload_yee ...

  5. SQL Server数据库视图

    1:什么是视图 2:视图和查询的区别 3:视图的优点 4:如何创建和管理视图 5:如何通过视图修改基本表的数据 6:如何通过视图实现数据的安全性 A:什么是视图: 视图(view):从一个或几个基本表 ...

  6. 使用ThinkPHP框架高速发展网站(多图)

    使用ThinkPHP框架高速搭建站点 这一周一直忙于做实验室的站点,基本功能算是完毕了.比較有收获的是大概了解了ThinkPHP框架.写一些东西留作纪念吧.假设对于相同是Web方面新手的你有一丝丝帮助 ...

  7. js多个物体运动问题2

    问题1 http://www.cnblogs.com/huaci/p/3854216.html 在上一讲问题1,我们可以整理出2点: 1,定时器作为运动物体的属性 2,startMove方法,参数要传 ...

  8. Entity Framework mvc Code First data migration

    1. Code First 可以先在代码里写好数据模型,自动生成DB.下一次启动的时候会根据__MigrationHistory判断 数据库是否和模型一致. 详情参考:http://blogs.msd ...

  9. android存储阵列数据SharedPreferences

    假设要数组数据(如boolean[] .int[]等)到SharedPreferences时,我们能够先将数组数据组织成json数据存储到SharedPreferences,读取时则对json数据进行 ...

  10. 【Java基金会】Java整理面试问题和评论(一)

    1. ArrayList,Vector, LinkedList 存储性能及特点 ArrayList 和 Vector 都是使用数组方式存储数据,此数组元素数大于实际存储的数据以便添加和插入元素,它们都 ...