下面是我写的一个爬虫程序。此程序主要功能就是爬取网页,并且可以保存上次爬取过的网页和待爬的URL,以便于下一次可以继续上一次的爬取工作。第一次的爬取没问题,但是第二次运行的时候程序就莫名其妙的退出。80%是线程的问题。
解决问题者有分
void CTest1Dlg::OnOK() 
{
// TODO: Add extra validation here
//first标志判断是否是第一次爬取
int first = 1;
char readbuffer[256];      //读文件用到的缓冲区
CString readURL = "";
UpdateData(TRUE) ;
PageSavePath = m_Path; if( m_seedsFile.IsEmpty() || m_Path.IsEmpty() )
return ;
try
{
//读文件,m_URLDonePath是文件名,该文件存取以前爬取过的网页URL记录
//将他们添加进树中,以防止重复爬取
         //第一次爬取时不执行以下两段代码
         ifstream URLDoneFile( m_URLDonePath );
assert(URLDoneFile);
URLDoneFile>>readbuffer;
if( !URLDoneFile.eof() ) {
readURL = readbuffer;
Tree.inserthelp( Tree.root, readURL );
while( !URLDoneFile.eof() && URLDoneFile>>readbuffer )
{
readURL = readbuffer;
Tree.inserthelp( Tree.root, readURL );
}
// first=0;
}
URLDoneFile.close();

//读取上次爬取时保存的待爬取的URL记录文件,将读到的URL入队列
ifstream ToFetchURLFile( m_URLToFetchPath );
assert(ToFetchURLFile);
unsigned int nread = 0;
ToFetchURLFile>>nread;
if( !ToFetchURLFile.eof() ) {
whole_filename = nread;
while( !ToFetchURLFile.eof() && ToFetchURLFile>>readbuffer )
{
readURL = readbuffer;
m_Queue.push( readURL );
}
first=0;
}
ToFetchURLFile.close();
}
catch(CException* e)
{
e->ReportError();
e->Delete();
}
//如果是第一次爬取,就从种子文件seeds.txt中读取初始URL
if( first == 1 )
{
CString str = "F:\\seeds.txt";
ifstream seedfile( str );
assert( seedfile );
while(!seedfile.eof() && seedfile>>readbuffer)
{
readURL = readbuffer;
m_Queue.push( readURL ) ;
AfxBeginThread( threadFun, NULL ) ;
thread_count++ ;
}
seedfile.close();
}
//否则就开10个线程
else{
int i;
for( i=0;i<10;i++ )
AfxBeginThread(threadFun,NULL);// while( thread_count++ < 10 )
// threadFun(NULL);
// AfxBeginThread(threadFun, NULL );
}
//CDialog::OnOK();
}
//下面是线程函数
UINT threadFun(LPVOID pParam)
{try
{
CString tempstr; myURL *m_URL;
m_URL = new myURL; while(!m_Queue.empty()) {
g_CriticalSection.Lock() ; //每次都从队列里读取URL,再判断是否在树里出现过,若已出现过,则继续从队列里取URL
CString tempURL = m_Queue.front();
m_Queue.pop();
ConvertToEffectiveURL( tempURL );  //此函数去掉URL结尾的'/'
while( Tree.findhelp( Tree.root, tempURL ) != NULL )
{
if( m_Queue.empty() )
{
delete m_URL;
return 0;
}
tempURL = m_Queue.front();
m_Queue.pop();
ConvertToEffectiveURL( tempURL );
}
Tree.inserthelp( Tree.root, tempURL );  //将从队列中取出的未曾爬过的URL加入BST树中
g_CriticalSection.Unlock() ;
m_URL->m_strURL = tempURL;
try
{
m_URL->m_pFile = (CInternetFile *)m_URL->m_pSession.OpenURL(m_URL->m_strURL) ;
}
catch(CInternetException *pEx)
{
m_URL->m_pFile = NULL ;
pEx->Delete() ;
continue;
}
//以下是保存HTTP服务器发过来的HTTP文件的过程
//GetHttpFile  GetTextAndLink两个函数没有问题
m_URL->GetHttpFile() ;
if(m_URL->m_strContents.GetLength()!=0)
{
if(m_URL->GetTextAndLink(PageSavePath))
{
tempstr = m_URL->m_strURL;
g_CriticalSection.Lock() ;
//将爬过的URL写入文件,保存起来
URLDoneFile<<LPCTSTR(tempstr);
URLDoneFile<<"\r\n";
g_CriticalSection.Unlock() ;
}
}
m_URL->m_strContents = "";
} delete m_URL;
}
catch(CException* e)
{
e->ReportError();
e->Delete();
}
return 0 ;
}