-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathcrawler.cpp
More file actions
128 lines (109 loc) · 3.63 KB
/
Copy pathcrawler.cpp
File metadata and controls
128 lines (109 loc) · 3.63 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
#include <iostream>
#include <string>
#include <map>
#include <queue>
#include "gumbo.h"
#include "utils.h"
#include "simple_curl.h"
#include "crawler.h"
/*
* Finds the URLs of all links in the page and push to queue
* Validate if URL is valid
* Validate if URL belongs to host
* Strip out params and hashes from URLs
*/
void Crawler::searchLinks(GumboNode* node, string host) {
if (node->type != GUMBO_NODE_ELEMENT) {
return;
}
GumboAttribute* href;
if (node->v.element.tag == GUMBO_TAG_A &&
(href = gumbo_get_attribute(&node->v.element.attributes, "href"))) {
if(Utils::isUrlValid(string(href->value), host)){
string url = Utils::reformatUrl(string(href->value), host, host);
if(!Utils::isExternalUrl(url, host)){
linkStore.push(url);
}
}
}
GumboVector* children = &node->v.element.children;
for (unsigned int i = 0; i < children->length; ++i) {
searchLinks(static_cast<GumboNode*>(children->data[i]), host);
}
}
/*
* Get the cleantext of a page
*/
string Crawler::cleanText(GumboNode* node) {
if (node->type == GUMBO_NODE_TEXT) {
return string(node->v.text.text);
} else if (node->type == GUMBO_NODE_ELEMENT &&
node->v.element.tag != GUMBO_TAG_SCRIPT &&
node->v.element.tag != GUMBO_TAG_STYLE) {
string contents = "";
GumboVector* children = &node->v.element.children;
for (unsigned int i = 0; i < children->length; ++i) {
const string text = cleanText((GumboNode*) children->data[i]);
if (i != 0 && !text.empty()) {
contents.append(" ");
}
contents.append(text);
}
//Remove all punctuations
for (int i = 0, len = contents.size(); i < len; i++)
{
if (ispunct(contents[i]))
{
contents.erase(i--, 1);
}
}
return contents;
} else {
return "";
}
}
/*
* Crawling Algorithm
* When the process starts a new depth, reset distance based on queue size
* Distance - 1 after every link gets processed
* Depth + 1 after distance reaches 0
* Stop the while loop if current depth is greater than defined depth or queue is empty
*/
void Crawler::crawl(string host, int depth) {
int current_depth = 0;
int distance = 1;
linkStore.push(host);
while(current_depth <= depth && !linkStore.empty()){
string url = linkStore.front();
// check if url has been processed
if ( uniqueWordsPerLink.find(url) == uniqueWordsPerLink.end() ) {
// Curl
string readBuffer = Simple_curl::curl(url);
// Get Output string
GumboOutput* output = gumbo_parse(readBuffer.c_str());
cout << "Currently Depth : " << current_depth << endl;
cout << "Distance to the next level : " << distance << endl;
// Find all links in the html
// GetLinks, insert to queue
searchLinks(output->root, host);
// reset distance and increase depth after all links of current depth have been processed
if(distance <= 1){
distance = linkStore.size();
current_depth++;
}
// Get count per word for one page
map<string,size_t> totalWords = Utils::countUniqueWords(cleanText(output->root));
// Get unique words count per url
uniqueWordsPerLink[url] = totalWords.size();
// Get unique words count in total
TotaluniqueWordsCount = Utils::countTotalUniqueWord(TotaluniqueWordsCount, totalWords);
// Print count per url
cout << url << " : " << uniqueWordsPerLink[url] << endl;
cout << "Total unique words : " << TotaluniqueWordsCount.size() << endl;
gumbo_destroy_output(&kGumboDefaultOptions, output);
}
// Pop processed link off the queue and decrease distance
linkStore.pop();
distance--;
}
}