搜索引擎源码及流程



对从网络上抓取到的网页进行处理:建立网络库,分词,去重,if-tdf计算权重,归一化,然后根据查询词将文本相似度从高到低的依次返回给客户

第一阶段:python网络爬虫抓取网页,并存盘

第二阶段:对磁盘上的网页文件建立网页库,将全部网页写入网页库,并建立相应网页的偏移量索引文件(1   23   100)-->(dofid,   offset,   size),以便读取网页内容

注意的地方:1.写成格式:<doc>

<docid>1</docid> //对网页进行编号

<url>http://....</url>

<title>...</title>

<content>....

</content>

</doc>

2.处理每行的‘\r\n‘,调用tellp()  也可以用FILE*的ftell()函数,打印当前文件偏移量,

此部分代码:

pagelib.h

 1 #ifndef _PAGELIB_H_
 2 #define _PAGELIB_H_
 3 #include <iostream>
 4 #include <string>
 5 #include <vector>
 6 #include <fstream>
 7 #include <unistd.h>
 8 #include <dirent.h>
 9 #include <sys/types.h>
10 #include <sys/stat.h>
11 #include <stdio.h>
12 #include <stdlib.h>
13 #include <string.h>
14 #include <time.h>
15 #include <pwd.h>
16 #include <grp.h>
17
18 class pagelib
19 {
20     public:
21         pagelib(const std::string &dir,
22                 const std::string &libname)
23             :dir_(dir),
24             libname_(libname)
25     {}
26         void readdirname()
27         {
28             readfile(dir_);
29         }
30         void store_to_lib(const std::string&);
31     private:
32         void readfile(const std::string &);
33         void store_to_vector(const std::string&);
34         std::string dir_;
35         std::string libname_;
36         static int i;
37         std::vector<std::string> vec;
38 };
39
40 #endif /*PAGELIB_H*/ 

pagelib.cpp

 1 #include "pagelib.h"
 2 using namespace std;
 3 int pagelib::i = 1;
 4
 5 void pagelib::readfile(const string &s)
 6 {
 7     DIR *dir;
 8     struct dirent * mydir;
 9     struct stat mystat;
10     char str[256];
11     dir=opendir(s.c_str());
12     if(!dir)
13     {
14         cout << s << endl;
15         exit(-1);
16     }
17
18     while((mydir=readdir(dir))!=NULL)
19     {
20         sprintf(str, "%s/%s", s.c_str(), mydir->d_name);
21         stat(str, &mystat);
22         if(!strcmp(mydir->d_name, ".") || !strcmp(mydir->d_name, ".."))
23             continue;
24         if( mystat.st_mode & 0040000 )
25         {
26             string s1 = str;
27             readfile(s1);
28         }
29         else
30         {
31             cout << str << endl;
32             store_to_vector(str);
33         }
34     }
35 }
36
37 void pagelib::store_to_vector(const string &str)
38 {
39     string content, line;
40     ifstream is(str.c_str());
41
42     string title;
43     getline(is, title);
44     {
45         for (size_t i = 0; i < title.size(); i++) {
46             if(title[i] == ‘\r‘)
47                 title[i] = ‘ ‘;
48         }
49     }
50
51     while(getline(is, line) > 0)
52     {
53         for (size_t i = 0; i < line.size(); i++) {
54             if(line[i] == ‘\r‘)
55                 line[i] = ‘\n‘;
56         }
57         content += line;
58     }
59     char s1[5];
60     sprintf(s1, "%d", i++);
61     string doc = string("<doc>\n  <docid>") + s1 + "</docid>\n   <url>" + string(str)
62         + "</url>\n   <title>" + title + "</title>\n     <content>\n"
63         + content + "     </content>\n</doc>\n\n";
64     vec.push_back(doc);
65     is.close();
66 }
67
68 void pagelib::store_to_lib(const string& index)
69 {
70     ofstream os_lib(libname_.c_str());
71     ofstream os_index(index.c_str());
72     vector<string>::iterator it = vec.begin();
73     int j = 1;
74     os_lib << "<pagelib>\n" << endl;
75     for(; it != vec.end(); it++)
76     {
77         os_index << j++ << " " << os_lib.tellp() ;
78         os_lib << *it;
79         os_index << " " << (*it).size() << endl;
80     }
81     os_lib << "</pagelib>\n" << endl;
82     os_index.close();
83     os_lib.close();
84 }

第3阶段:对网页库中的网页进行分词,去重,关键词计算权重,归一化等操作

注意的问题:切词使用的是结巴切词:[email protected]:aa838260772/jieba.git

tf-idf计算权重,一个单词的权重跟在本文档中出现的次数成正比,跟出现此单词的文档数成反比

关键词的选取:权重,去停用词,使用priority_queue输出权重最大10个单词

文档关键词的归一化:余弦相似度,方便后面计算文本相似度。

建立倒排索引:

重新构建新的网络库和偏移索引:注意docid的变化,使用string.replace()函数

split.h

 1 #ifndef _SPLIT_H_
 2 #define _SPLIT_H_
 3 #include <utility>
 4 #include "MixSegment.hpp"
 5 #include <map>
 6 #include <string>
 7 #include <fstream>
 8 #include <queue>
 9 #include <sstream>
10 #include <set>
11 #include <algorithm>
12
13 typedef struct qelem
14 {
15     std::string word;
16     int frequence;
17     bool operator<(const qelem &other) const
18     {
19         return frequence < other.frequence;
20     }
21 }qelem;
22
23
24 class splitpagelib
25 {
26     public:
27         splitpagelib(const std::string &libname,
28                 const std::string &indexname,
29                 const std::string &stopfilename,
30                 const std::string &splitfilename
31                 )
32                 :libname_(libname),
33             indexname_(indexname),
34             stopfilename_(stopfilename),
35             splitfilename_(splitfilename)
36     {}
37         void startsplit(const std::string& dic_path,
38                         const std::string& model_path);
39         void deletesame();
40         void newindexlib(const std::string&,
41                          const std::string&);
42         void make_reverse_index(const std::string& ,
43                                 const std::string&);
44     private:
45         void compute_power();
46         bool ifsame(const std::map<std::string, int> &,
47                 const std::map<std::string, int> &);
48         void topten(int,
49                     std::ofstream &,
50                     const std::map<std::string, int> &);
51         void weightogether();
52
53         std::string libname_;//从lib文件读内容
54         std::string indexname_;//从index读每篇文档相应的offset,读出相应文章
55         std::string stopfilename_;//停用词文件
56         std::string splitfilename_;//分词后的文件
57
58         std::set<std::string> set_stop;//读入停用词
59         std::map<int, std::string> map_doc;//根据索引把每篇doc读入map
60         std::map<int, std::map<std::string, int> > map_lib;
61         std::map<std::string, int> words;//将去去重后的所有单词及频数写入map
62         std::map<int, std::map<std::string, double> >doc_word_wei;
63         std::map<std::string, std::map<int, double> >rev_index;//倒排索引
64         std::map<std::string, std::map<int, int> > map_word_fre;
65 };
66
67 #endif /*SPLIT_H*/ 

split.cpp

  1 #include "split.h"
  2 #include <stdio.h>
  3 using namespace std;
  4 using namespace CppJieba;
  5
  6 void splitpagelib::startsplit(const string &dic_path,
  7         const string &model_path)
  8 {
  9     MixSegment  segment_(dic_path, model_path);
 10     //读入停用词到set_stop中去
 11     ifstream is_stop(stopfilename_.c_str());
 12     string stopword;
 13     while(getline(is_stop, stopword) > 0)
 14     {
 15         set_stop.insert(stopword);
 16     }
 17     //通过index来将lib中文档读出并分词,统计出现最高的10个 放入map中
 18     vector<string> words;//用来存放切割后的单词
 19     ifstream is_lib(libname_.c_str());
 20     ifstream is_index(indexname_.c_str());
 21     ofstream os_split(splitfilename_.c_str());
 22     string lib_line, index_line;
 23     cout << "begin to cut word :" << indexname_
 24          <<" " << libname_ << endl;
 25     while(getline(is_index, index_line) > 0)
 26     {
 27         map<string, int> map_;
 28         int docid, offset, size;
 29         istringstream ss(index_line);
 30         ss >> docid >> offset >> size;
 31         is_lib.seekg(offset);
 32         string every_doc = "";
 33         while(is_lib.tellg() < (offset + size))
 34         {
 35             getline(is_lib, lib_line);
 36             every_doc += lib_line + "\n";
 37             for(size_t i = 0; i < lib_line.size(); i++)
 38             {
 39                 if(!(lib_line[i] & (1 << 7)))
 40                     lib_line[i] = ‘ ‘;
 41             }
 42
 43             segment_.cut(lib_line.c_str(), words);
 44             for(size_t i = 0; i < words.size(); i++)
 45             {
 46                 set<string>::iterator it = set_stop.find(words[i]);
 47                 if(it == set_stop.end() && words[i] != " ")//不去掉的话把空格当单词
 48                     ++map_[words[i]];
 49             }
 50             words.clear();
 51         }
 52         os_split << docid << endl;
 53         topten(docid, os_split, map_);
 54         os_split << endl;
 55         map_doc[docid] = every_doc;//将每篇文章读入map_doc
 56     }
 57     os_split.close();
 58     is_lib.close();
 59     is_index.close();
 60     cout << "cut word over :write to"  << splitfilename_ << endl;
 61 }
 62
 63 void splitpagelib::topten(int docid,
 64         ofstream &os,
 65         const map<string, int> &map_)
 66 {
 67     priority_queue<qelem> prique_;
 68     qelem ql;
 69     for(map<string, int>::const_iterator it = map_.begin();
 70             it != map_.end();
 71             ++it)
 72     {
 73         ql.word = it->first;
 74         ql.frequence = it->second;
 75         prique_.push(ql);
 76     }
 77
 78     int i = 0;
 79     while(i < 10 && !prique_.empty())
 80     {
 81         ql = prique_.top() ;
 82         map_lib[docid][ql.word] = ql.frequence;
 83         prique_.pop();
 84         i++;
 85         os << ql.word << " " << ql.frequence << " ";
 86     }
 87 }
 88
 89 void splitpagelib::deletesame()
 90 {    //去重
 91     cout << "begin to delete the same" << endl;
 92     int *arr = new int [map_lib.size() + 1];
 93     for (size_t i = 1; i < map_lib.size() + 1; i++)
 94     {
 95         arr[i] = 1;
 96     }
 97     size_t ix1, ix2;
 98     for(ix1 = 1; ix1 < map_lib.size() + 1; ++ix1)
 99     {
100         if(arr[ix1] == 0)
101             continue;
102         for (ix2 = ix1 +1; ix2 < map_lib.size() + 1; ix2++)
103         {
104             if(arr[ix2] == 0)
105                 continue;
106             if(ifsame(map_lib[ix1], map_lib[ix2]))
107             {
108                 arr[ix2] = 0;
109                 map_lib.erase(ix2);
110             }
111         }
112     }
113     delete [] arr;
114     cout << "delsanme over" << endl;
115 }
116
117 bool splitpagelib::ifsame(const map<string, int>& map1,
118         const map<string, int>& map2)
119 {
120     int i = 0;
121     for(map<string, int>::const_iterator it = map2.begin(); it != map2.end(); ++it)
122     {
123         if(map1.count(it->first) > 0)
124             i++;
125     }
126     if(i > 6)
127         return true;
128     else
129         return false;
130 }
131
132 void splitpagelib::newindexlib(const string& index,
133                         const string& lib)
134 {
135     ofstream os_index(index.c_str());
136     ofstream os_lib(lib.c_str());
137
138     map<int, map<string, double> >::iterator it;
139     size_t i = 1;
140     cout << "begin write to index lib" << index
141          << " " << lib <<  endl;
142     for(it = doc_word_wei.begin(); it != doc_word_wei.end(); it++)
143     {
144         os_index << i << " " << os_lib.tellp() << " " ;
145
146         int begin = map_doc[it->first].find("<docid>");
147         int end = map_doc[it->first].find("</docid>");
148         char s[10] = {0};
149         sprintf(s, "%d", i);
150         map_doc[it->first].replace(begin + 7, end - begin - 7, s);
151         os_lib << map_doc[it->first] << endl;
152
153         os_index << map_doc[it->first].size() << endl;//写index
154         i++;
155     }
156     cout << "write over" << endl;
157     os_index.close();
158     os_lib.close();
159 }
160
161 void splitpagelib::compute_power()
162 {
163     map<int, map<string, int> >::iterator it1;
164     map<string, int>::iterator it2 ;
165     for(it1 = map_lib.begin(); it1 != map_lib.end(); it1++)
166     {
167         for(it2 = it1->second.begin(); it2 != it1->second.end(); ++it2)
168         {
169             map_word_fre[it2->first][it1->first] = it2->second;
170         }
171     }
172
173     for(it1 = map_lib.begin(); it1 != map_lib.end(); it1++)
174     {
175         for(it2 = it1->second.begin(); it2 != it1->second.end(); ++it2)
176         {
177             double d = (it2->second) * log( (double)(map_word_fre.size()) / (double)(map_word_fre[it2->first].size() +1) );
178             doc_word_wei[it1->first][it2->first] = d;
179         }
180     }
181 }
182
183 void splitpagelib::make_reverse_index(const string &index,
184                                         const string &power)
185 {
186     //计算每篇中的权重
187     compute_power();
188     //对每篇文档的词作归一化
189    weightogether();
190    //建立倒排索引
191    int j = 1;
192    for(map<int, map<string, double> >::iterator it = doc_word_wei.begin();
193            it != doc_word_wei.end();
194            it++)
195    {
196        for(map<string, double>::iterator it1 = it->second.begin();
197                it1 != it->second.end();
198                ++it1)
199        {
200            rev_index[it1->first][j] = it1->second;
201        }
202        j++;
203    }
204     cout << "write reverse index" << index <<endl;
205     ofstream os_index(index.c_str());
206     for(map<string, map<int, double> >::iterator it = rev_index.begin();
207             it != rev_index.end();
208             ++it)
209     {
210         os_index << it->first << endl;
211         for(map<int, double> ::iterator it1 = it->second.begin();
212                 it1 != it->second.end();
213                 ++it1)
214         {
215             os_index << it1->first << " " << it1->second << " ";
216         }
217         os_index << endl;
218     }
219     os_index.close();
220     cout << "write reverse index over" << endl;
221
222     cout << "write doc_word_wei begin" << power << endl;
223     ofstream os_power(power.c_str());
224     map<int, map<string, double> >::iterator it = doc_word_wei.begin();
225     map<string, double>::iterator it1;
226     int i = 1;
227     for(; it != doc_word_wei.end(); ++it)
228     {
229         os_power << i << endl;
230         for(it1 = it->second.begin(); it1 != it->second.end(); ++it1)
231         {
232             os_power << it1->first << " " << it1->second << " " ;
233         }
234         os_power << endl;
235         i++;
236     }
237     os_power.close();
238     cout << "write power end" << endl;
239 }
240
241 void splitpagelib::weightogether()//归一化
242 {
243     map<int, map<string, double> >::iterator it;
244     map<string, double>::iterator it1;
245     double s;
246     for(it = doc_word_wei.begin(); it != doc_word_wei.end(); it++)
247     {
248         s = 0;
249         for(it1 = it->second.begin(); it1 != it->second.end(); it1++)
250         {
251             s += it1->second * it1->second;
252         }
253
254         for(it1 = it->second.begin(); it1 != it->second.end(); it1++)
255         {
256             it1->second /= sqrt(s);
257         }
258       }
259 }

第4阶段:对查询语句进行分词,根据倒排索引找出文档的交集,将查询句的单词进行归一化,与查询结果计算文档相似度,从大到小返回个客户

注意的地方:根据索引按行读文档时在读出的结果后面加上‘\n‘,

query.h

 1 #ifndef _QUERY_H_
 2 #define _QUERY_H_
 3
 4 #include <map>
 5 #include "MixSegment.hpp"
 6 #include <string>
 7 #include <fstream>
 8 #include <sstream>
 9 #include <queue>
10 #include <algorithm>
11
12 typedef struct simi
13 {
14     int docid;
15     double simidegre;
16     bool operator<( const simi &right)const
17     {
18         return simidegre < right.simidegre;
19     }
20 }simi;
21
22 class query
23 {
24     public:
25         query(){}
26      void read_to_map(const std::string&,
27            const std::string&,
28            const std::string&,
29            const std::string&);
30      std::string search(const std::string&);
31     private:
32      static void similar(std::map<std::string, double>&,
33                          std::map<std::string, double>&,
34                          int,
35                          std::priority_queue<simi>&);
36
37       std::string offsetfile_;
38       std::string reverseindexfile_;
39       std::string docfile_;
40       std::string doc_weifile_;
41
42       std::map<std::string, std::map<int, double> > map_reindex;//存储倒排索引
43       std::map<int, std::map<std::string, double> > map_wei;
44       std::map<int, std::string> map_doc;
45 };
46
47 #endif /*QUERY_H*/ 

query.cpp

  1 #include "query.h"
  2
  3 using namespace std;
  4 using namespace CppJieba;
  5
  6 void query::read_to_map(
  7          const string &offsetfile,
  8         const string &reverseindexfile,
  9         const string &docfile,
 10         const string &doc_weifile)
 11 {
 12   offsetfile_ = offsetfile;
 13   reverseindexfile_ = reverseindexfile;
 14   doc_weifile_ = doc_weifile;
 15   docfile_ = docfile;
 16
 17     //读倒排索引文件
 18     ifstream is_revindex(reverseindexfile_.c_str());
 19     string line;
 20     while(getline(is_revindex, line) > 0)
 21     {
 22         string word;
 23         word = line;
 24         getline(is_revindex, line) ;
 25         istringstream sstream(line);
 26         int docid;
 27         double weight;
 28         while(sstream >> docid >> weight)
 29         {
 30             map_reindex[word][docid] = weight;
 31         }
 32     }
 33     is_revindex.close();
 34
 35     //读偏移索引文件和doc文件,将每篇文档读入map
 36     ifstream is_offset(offsetfile_.c_str());
 37     ifstream is_doc(docfile_.c_str());
 38     string line_off;
 39     while(getline(is_offset, line_off) > 0)
 40     {
 41         istringstream sstream(line_off);
 42         int docid;
 43         int offset;
 44         int size;
 45         sstream >> docid >> offset >> size;
 46         is_doc.seekg(offset);
 47         string every_doc = "";
 48         while(is_doc.tellg() < (offset + size))
 49         {
 50             string line;
 51             getline(is_doc, line);
 52             every_doc += line + "\n";
 53         }
 54         map_doc[docid] = every_doc;
 55     }
 56     is_offset.close();
 57     is_doc.close();
 58     //读每篇doc归一化后的top10词文件
 59     ifstream is_map_wei(doc_weifile_.c_str());
 60     string line_wei;
 61     while(getline(is_map_wei, line_wei) > 0)
 62     {
 63         int docid;
 64         istringstream ss(line_wei);
 65         ss >> docid;
 66         getline(is_map_wei, line_wei);
 67         istringstream sstream(line_wei);
 68         string word;
 69         double weight;
 70         while(sstream >>  word >> weight)
 71         {
 72             map_wei[docid][word] = weight;
 73         }
 74     }
 75     is_map_wei.close();
 76 }
 77
 78 string query::search(const std::string &word)
 79 {
 80     priority_queue<simi> result_doc;
 81     //切词,算出单词权重存储到一个map,相当于一片doc
 82     MixSegment segment("../dict/jieba.dict.utf8",
 83             "../dict/hmm_model.utf8");
 84     vector<string> words;
 85     map<string, double> map_que;
 86     segment.cut(word, words);
 87     double d = 0;
 88     for (size_t i = 0; i < words.size(); i++)
 89     {
 90         double s = 1 * log( (double)map_reindex.size() / (double)(map_reindex[words[i]].size()+1) );
 91         cout << words[i] << s << endl;
 92         map_que[ words[i] ] = s;
 93         d += s*s;
 94     }
 95     for(size_t i = 0; i < words.size(); i++)
 96     {
 97         map_que[ words[i] ] /= sqrt(d);
 98     }
 99     //找出单词交集的docid
100     map<int, double> com(map_reindex[ words[0] ]);
101
102     for (size_t i = 1; i < words.size(); i++)
103     {
104         if(map_reindex[ words[i] ].size() == 0)
105             continue;
106         for(map<int, double>::iterator it = com.begin(); it != com.end(); ++it)
107         {
108             if(map_reindex[ words[i] ].count(it->first) == 0)
109                 com.erase(it->first);
110         }
111     }
112     cout << com.size() << endl;
113     for(map<int, double>::iterator it = com.begin(); it != com.end(); ++it)
114     {
115         similar(map_que, map_wei[it->first], it->first, result_doc);
116     }
117
118     simi si;
119     string result = "";
120     while(!result_doc.empty())
121     {
122         si = result_doc.top();
123         char s[20] = {0};
124         sprintf(s, "%d %f\n", si.docid, si.simidegre);
125         result += s + map_doc[si.docid];
126         result_doc.pop();
127     }
128     return result;
129 }
130
131 void query::similar(map<string, double> &map_doc1,
132                     map<string, double> &map_doc2,
133                     int docid,
134                     priority_queue<simi> &result_doc)
135 {
136     double s = 0;
137     for(map<string, double>::iterator it = map_doc1.begin();
138                                     it != map_doc1.end();
139                                         ++it)
140     {
141         if(map_doc2.count(it->first) > 0)
142         {
143             s += it->second * map_doc2[it->first];
144         }
145     }
146     simi si;
147     si.docid = docid;
148     si.simidegre = s;
149     result_doc.push(si);
150 }

第5阶段:可将返回结果做成xml格式返回给客户,直接以网页格式显示,

一点点想法:可以结合文本纠错,使得查询更加智能一点

时间: 2024-10-24 15:34:31

搜索引擎源码及流程的相关文章

zabbix源码安装流程及报错解决方法

zabbix源码安装流程及报错解决方法 一. zabbix的介绍 1) zabbix是什么 zabbix是一款基于web页面的.开源的.企业级的,支持分布式部署的监控软件. 2)2.zabbix的作用 监控windows和Linux主机上的软硬件状态. 监控各网络设备,如路由器.交换机.防火墙.f5.打印机等. 支持邮件短信微信等平台发送告警通知. 通过web页面及图形展示监控数据. 3)zabbix的特性 由zabbix server和agent程序协同工作,还支持分布式监控,这时需要安装za

Chromium源码--视频播放流程分析(WebMediaPlayerImpl解析)

转载请注明出处:http://www.cnblogs.com/fangkm/p/3797278.html 承接上一篇文章.媒体播放,需要指定一个源文件,html5用URL格式来指定视频源文件地址,可以是http链接,也可以使本地源文件(不能直接指定,需要借助blob二进制类型).播放网络文件比播放本地文件多了个下载流程, 所以下面直接分析网络文件的播放流程,本地文件的播放流程也就清楚了.首先分析下网络视频资源的加载流程,相关结构图如下: WebMediaPlayerImpl类有一成员Buffer

Chromium源码--视频播放流程分析(拨开云雾)

转载请注明出处: http://www.cnblogs.com/fangkm/p/3791964.html 在PC浏览器中播放视频,大部分视频网站都是采用flash播放器,这多亏了Adobe Flash Player庞大的装机量.但Flash Player对于浏览器来说就是一个插件,插件内部下载flv流.解析flv视频格式.播放视频等流程与浏览器都没有太大关系.浏览器新标准HTML5中增加了视频支持,如:<video src="movie.ogg"> </video&

GitHub超详细图文攻略 - Git客户端下载安装 GitHub提交修改源码工作流程 Git分支 标签 过滤 Git版本工作流(转载)

最近听同事说他都在使用GitHub,GitHub是程序员的社区,在里面可以学到很多书上学不到的东西,所以最近在准备入手这方面的知识去尝试学习,正好碰到这么详细完整的文章,就转载了,希望对自己和大家有帮助. GitHub操作总结 : 总结看不明白就看下面的详细讲解. GitHub操作流程 : 第一次提交 : 方案一 : 本地创建项目根目录, 然后与远程GitHub关联, 之后的操作一样; -- 初始化Git仓库 :git init ; -- 提交改变到缓存 :git commit -m 'desc

【代码管理】GitHub超详细图文攻略 - Git客户端下载安装 GitHub提交修改源码工作流程 Git分支 标签 过滤 Git版本工作流

找到一篇很详细的Git教程,真的很不错,推荐!!! GitHub操作总结 : 总结看不明白就看下面的详细讲解. . 作者 :万境绝尘  . GitHub操作流程 : 第一次提交 : 方案一 : 本地创建项目根目录, 然后与远程GitHub关联, 之后的操作一样; -- 初始化git仓库 :git init ; -- 提交改变到缓存 :git commit -m 'description' ; -- 本地git仓库关联GitHub仓库 : git remote add origin [email 

OBS源码分析流程梳理

OBS-Studio是一款非常好用的开源直播推流软件,目前已经发布了很多个版本.但是目前都没看到详细或流程清晰的源码分析介绍.所以,本文以线程为单位对OBS的采集.编码.传输流程进行梳理,一方面能够使我自己更清楚OBS架构和运行流程,另一方面也能方便新手同学.整体的粒度不会太细,但已经能够阐述OBS流程.由于水平有限,其中可能存在问题,如果有,请指出. OBS主要线程共五个: 1.主线程:主要做一些初始化工作和UI处理 2.视频渲染线程:渲染视频到窗口 3.视频编码线程:编码原始视频 4.音频编

记录mysql5.7源码安装流程

今天给别人的linux服务器安装mysql,选择使用源码安装的,在安装的过程中,还是遇到了一些问题,主要是在一下几点:1.cmake的时候,有些参数配置的路径老是报不存或是提示你查看CMakeOutput.log等日志文件.2.mysql 编译和安装完成后,初始化后,启动失败.这个就看mysql错误日子就好了,今天我就老是初始化失败.主要原因是mysql配置文件my.cnf中的basedir.datadir还有日志文件路径的问题,主要体现在权限和文件是否存在的问题. 现在就把主要流程记录下来,方

python语言磁力搜索引擎源码公开,基于DHT协议,十二分有技术含量的技术博客

之前我在写百度网盘爬虫,百度图片爬虫的时候答应网友说,抽时间要把ok搜搜的的源码公开,如今是时候兑现诺言了,下面就是爬虫的所有代码,完全,彻底的公开,你会不会写程序都可以使用,不过请先装个linux系统,具备公网条件,然后运行: python startCrawler.py 有必要提醒你,数据库字段代码中都有,请你自己建张表格,这个太简单了,就不多说了.同时我也提供一下下载地址,源码都在:下载地址1 下载地址2 代码如下: #!/usr/bin/env python # encoding: ut

python语言磁力搜索引擎源码公开,基于DHT协议

之前我在写百度网盘爬虫,百度图片爬虫的时候答应网友说,抽时间要把ok搜搜的的源码公开,如今是时候兑现诺言了,下面就是爬虫的所有代码,完全,彻底的公开,你会不会写程序都可以使用,不过请先装个linux系统,具备公网条件,然后运行: python startCrawler.py 有必要提醒你,数据库字段代码中都有,请你自己建张表格,这个太简单了,就不多说了.同时我也提供一下下载地址,源码都在:下载地址1 下载地址2 #!/usr/bin/env python # encoding: utf-8 "&