add site search, highlighting
[phinde.git] / bin / crawl.php
1 #!/usr/bin/env php
2 <?php
3 namespace phinde;
4 require_once __DIR__ . '/../src/init.php';
5
6 $supportedCrawlTypes = array(
7     'text/html', 'application/xhtml+xml'
8 );
9
10
11 if ($argc < 2) {
12     echo "No URL given\n";
13     exit(1);
14 }
15
16 $es = new Elasticsearch($GLOBALS['phinde']['elasticsearch']);
17
18 $url = $argv[1];
19 if (!Helper::isUrlAllowed($url)) {
20     echo "Domain is not allowed; not crawling\n";
21     exit(2);
22 }
23
24
25 $req = new \HTTP_Request2($url);
26 //FIXME: send supported mime types in header
27 $res = $req->send();
28 if ($res->getStatus() !== 200) {
29     echo "Response code is not 200 but " . $res->getStatus() . ", stopping\n";
30     exit(3);
31 }
32 $mimetype = explode(';', $res->getHeader('content-type'))[0];
33 if (!in_array($mimetype, $supportedCrawlTypes)) {
34     echo "MIME type not supported for crawling: $mimetype\n";
35     exit(4);
36 }
37
38 //FIXME: mime type switch for cdata
39 $doc = new \DOMDocument();
40 //@ to hide parse warning messages in invalid html
41 @$doc->loadHTMLFile($url);
42
43 //FIXME: extract base url from html
44 $base = new \Net_URL2($url);
45
46 $xpath = new \DOMXPath($doc);
47 $links = $xpath->evaluate('//a');
48 //FIXME: link rel, img, video
49
50 $alreadySeen = array();
51
52 foreach ($links as $link) {
53     $linkTitle = $link->textContent;
54     $href = '';
55     foreach ($link->attributes as $attribute) {
56         if ($attribute->name == 'href') {
57             $href = $attribute->textContent;
58         }
59     }
60     if ($href == '' || $href{0} == '#') {
61         //link on this page
62         continue;
63     }
64
65     $linkUrlObj = $base->resolve($href);
66     $linkUrlObj->setFragment(false);
67     $linkUrl    = (string) $linkUrlObj;
68     if (isset($alreadySeen[$linkUrl])) {
69         continue;
70     }
71
72     switch ($linkUrlObj->getScheme()) {
73     case 'http':
74     case 'https':
75         break;
76     default:
77         continue 2;
78     }
79
80     if ($es->isKnown($linkUrl)) {
81         continue;
82     }
83
84     //FIXME: check target type
85     //FIXME: check nofollow
86     //var_dump($linkTitle, $linkUrl);
87     $es->markQueued($linkUrl);
88     addToIndex($linkUrl, $linkTitle, $url);
89     if (isUrlAllowed($linkUrl)) {
90         addToCrawl($linkUrl);
91     }
92     $alreadySeen[$linkUrl] = true;
93 }
94
95 function addToIndex($linkUrl, $linkTitle, $sourceUrl)
96 {
97     echo "Queuing for indexing: $linkUrl\n";
98     $gmclient = new \GearmanClient();
99     $gmclient->addServer('127.0.0.1');
100     $gmclient->doBackground(
101         'phinde_index',
102         serialize(
103             array(
104                 'url'    => $linkUrl,
105                 'title'  => $linkTitle,
106                 'source' => $sourceUrl
107             )
108         )
109     );
110     if ($gmclient->returnCode() != GEARMAN_SUCCESS) {
111         echo 'Error queueing URL indexing for '
112             . $linkUrl . "\n"
113             . 'Error code: ' . $gmclient->returnCode() . "\n";
114         exit(2);
115     }
116 }
117
118 function addToCrawl($linkUrl)
119 {
120     echo "Queuing for crawling: $linkUrl\n";
121     $gmclient = new \GearmanClient();
122     $gmclient->addServer('127.0.0.1');
123     $gmclient->doBackground(
124         'phinde_crawl',
125         serialize(
126             array(
127                 'url' => $linkUrl
128             )
129         )
130     );
131     if ($gmclient->returnCode() != GEARMAN_SUCCESS) {
132         echo 'Error queueing URL crawling for '
133             . $linkUrl . "\n"
134             . 'Error code: ' . $gmclient->returnCode() . "\n";
135         exit(2);
136     }
137 }
138 ?>