ParseCityAddressRu::handle()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 13
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 6
nc 1
nop 0
dl 0
loc 13
rs 9.4285
c 0
b 0
f 0
1
<?php
2
3
namespace Ngtfkx\Laradeck\AddressGenerator\Commands;
4
5
use Illuminate\Console\Command;
6
use Illuminate\Support\Collection;
7
use Illuminate\Support\Facades\Storage;
8
use Symfony\Component\DomCrawler\Crawler;
9
10
/**
11
 * Парсер улиц и домов с сайта www.city-address.ru
12
 *
13
 * Class ParseCityAddressRu
14
 * @package Ngtfkx\Laradeck\AddressGenerator\Commands
15
 */
16
class ParseCityAddressRu extends Command
17
{
18
    /**
19
     * The name and signature of the console command.
20
     *
21
     * @var string
22
     */
23
    protected $signature = 'address:city-address-ru {city} {url} {--limit=0}';
24
25
    /**
26
     * The console command description.
27
     *
28
     * @var string
29
     */
30
    protected $description = 'Parse streets and building numbers from www.city-address.ru';
31
32
    /**
33
     * @var Collection
34
     */
35
    protected $streets;
36
37
    /**
38
     * @var int
39
     */
40
    protected $cityId;
41
42
    /**
43
     * @var int
44
     */
45
    protected $limit;
46
47
    /**
48
     * @var string
49
     */
50
    protected $url;
51
52
    /**
53
     * @var string
54
     */
55
    protected $name;
56
57
    public function __construct()
58
    {
59
        $this->streets = new Collection();
60
61
        parent::__construct();
62
    }
63
64
    public function handle()
65
    {
66
        $this->cityId = $this->argument('city');
67
68
        $this->url = $this->argument('url');
69
70
        $this->limit = (int)$this->option('limit');
71
72
        $this->parse();
73
74
        $this->generateFile();
75
76
        $this->info('Data was saved');
77
    }
78
79
    /**
80
     * Парсинг данных
81
     */
82
    protected function parse()
83
    {
84
        $firstPage = $this->download($this->url);
85
86
        $allPages = (int)(new Crawler($firstPage))->filter('.uk-pagination > li')->last()->text();
87
88
        $name = (new Crawler($firstPage))->filterXpath('//meta[@name="geo.placename"]')->attr('content');
89
90
        $this->name = explode(', ', $name)[0];
91
92
        $k = 0;
93
94
        for ($i = 1; $i <= $allPages; $i++) {
95
            $page = $this->download($this->url . '/page-' . $i . '/');
96
97
            $this->line('Downloading streets and building numbers from page #' . $i . ' from ' . $allPages);
98
99
            $streets = (new Crawler($page))->filter('.c4 > a');
100
101
            $streets->each(function ($node) {
102
                $url = 'http://www.city-address.ru' . $node->attr('href');
103
104
                $page = $this->download($url);
105
106
                $numbers = collect((new Crawler($page))->filter('.c6 > div > a')->extract('_text'))
107
                    ->reject(function ($item) {
108
                        return strpos($item, 'дом ') !== 0;
109
                    })->map(function ($item) {
110
                        return str_replace('дом № ', '', $item);
111
                    })->toArray();
112
113
                $this->streets->put($node->text(), $numbers);
114
            });
115
116
            if (++$k == $this->limit) {
117
                $this->warn('Interrupted by the limit');
118
                break;
119
            }
120
        }
121
    }
122
123
    /**
124
     * Скачивание страница
125
     *
126
     * @param string $url
127
     * @return string
128
     */
129
    protected function download(string $url): string
130
    {
131
        $content = file_get_contents($url);
132
133
        return $content;
134
    }
135
136
    /**
137
     * Запись данных в файл
138
     */
139
    protected function generateFile()
140
    {
141
        $output = '<?php' . PHP_EOL . PHP_EOL;
142
        $output .= '/**' . PHP_EOL;
143
        $output .= ' * ' . $this->name . ', Россия' . PHP_EOL;
144
        $output .= ' */' . PHP_EOL . PHP_EOL;
145
        $output .= 'return [' . PHP_EOL;
146
        foreach ($this->streets as $street => $numbers) {
147
            $glueNumbers = implode('", "', $numbers);
148
            if (!empty($glueNumbers)) {
149
                $output .= '    "' . trim($street, ";") . '" => ["' . $glueNumbers . '"],' . PHP_EOL;
150
            }
151
        }
152
        $output .= '];' . PHP_EOL;
153
154
        Storage::put($this->cityId . '.php', $output);
155
    }
156
}
157