├── .gitignore ├── __pycache__ ├── avito.cpython-36.pyc ├── bd.cpython-36.pyc ├── config.cpython-36.pyc └── index.cpython-36.pyc ├── avito.py ├── bd.py ├── bot.py ├── config.py ├── index.py └── studios_list.csv /.gitignore: -------------------------------------------------------------------------------- 1 | .idea/ 2 | config.py -------------------------------------------------------------------------------- /__pycache__/avito.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/trof808/python_bot_parser/e95c0802d47fb56fd14cee84375c5c3a8fb37764/__pycache__/avito.cpython-36.pyc -------------------------------------------------------------------------------- /__pycache__/bd.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/trof808/python_bot_parser/e95c0802d47fb56fd14cee84375c5c3a8fb37764/__pycache__/bd.cpython-36.pyc -------------------------------------------------------------------------------- /__pycache__/config.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/trof808/python_bot_parser/e95c0802d47fb56fd14cee84375c5c3a8fb37764/__pycache__/config.cpython-36.pyc -------------------------------------------------------------------------------- /__pycache__/index.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/trof808/python_bot_parser/e95c0802d47fb56fd14cee84375c5c3a8fb37764/__pycache__/index.cpython-36.pyc -------------------------------------------------------------------------------- /avito.py: -------------------------------------------------------------------------------- 1 | import requests 2 | from bs4 import BeautifulSoup 3 | 4 | MAIN_URL = 'https://www.avito.ru' 5 | 6 | def get_html(url): 7 | response = requests.get(url) 8 | return response.text 9 | 10 | def parse(html): 11 | 12 | arrItem = [] 13 | 14 | soup = BeautifulSoup(html, 'html.parser') 15 | all_items = soup.find('div', class_='catalog-list') 16 | items = all_items.find_all('div', class_='item_table') 17 | 18 | for item in items: 19 | name = item.find('div', class_='description').find('h3', class_='item-description-title').a.get_text() 20 | 21 | price = item.find('div', class_='description').find('div', class_='about').contents[0] 22 | 23 | 24 | 25 | link = item.find('div', class_='description').find('h3', class_='item-description-title').a.get('href') 26 | link = 'https://www.avito.ru' + link 27 | arrItem.append({ 28 | 'title': name, 29 | 'price': price, 30 | 'link': link 31 | }) 32 | 33 | return arrItem 34 | 35 | def parseLocation(html): 36 | soup = BeautifulSoup(html, 'html.parser') 37 | 38 | arrCities = [] 39 | objCities = {} 40 | 41 | tables = soup.find_all('div', class_='cities') 42 | for table in tables: 43 | cities = table.find_all('a') 44 | for city in cities: 45 | arrCities.append(city) 46 | 47 | for item in range(0, len(arrCities)): 48 | name = arrCities[item].get_text().strip('\n ') 49 | link = 'https:' + arrCities[item].get('href') 50 | objCities[name] = link 51 | 52 | return objCities 53 | 54 | 55 | def main(): 56 | print(parseLocation(get_html(MAIN_URL))) 57 | 58 | if __name__ == '__main__': 59 | main() 60 | -------------------------------------------------------------------------------- /bd.py: -------------------------------------------------------------------------------- 1 | import postgresql 2 | import avito 3 | import telebot 4 | from telebot import types 5 | import config 6 | 7 | TOKEN = config.TOKEN 8 | 9 | bot = telebot.TeleBot(TOKEN) 10 | 11 | URL = 'https://www.avito.ru' 12 | 13 | objCities = avito.parseLocation(avito.get_html(URL)) 14 | 15 | db = postgresql.open('pq://postgres:585465077m@localhost:5432/postgres') 16 | 17 | def getCitiesFromDb(): 18 | cities = db.query('SELECT name FROM city') 19 | arrCities = [] 20 | 21 | for city in cities: 22 | for item in city: 23 | arrCities.append(item) 24 | 25 | return arrCities 26 | 27 | def getZn(): 28 | links = db.prepare("SELECT user_id, link FROM task_table WHERE active = true") 29 | arrlink = [] 30 | for link in links: 31 | items = avito.parse(avito.get_html(link[1]))[:8] 32 | for item in items: 33 | bot.send_message( 34 | link[0], 35 | '{price} \n {link}'.format(price=item['price'], link=item['link']) 36 | ) 37 | 38 | def main(): 39 | getZn() 40 | 41 | if __name__ == '__main__': 42 | main() -------------------------------------------------------------------------------- /bot.py: -------------------------------------------------------------------------------- 1 | import telebot 2 | from telebot import types 3 | import avito 4 | import config 5 | import bd 6 | import re 7 | 8 | db = bd.db 9 | 10 | URL = '' 11 | custom_url = [] 12 | custom_request = {} 13 | 14 | buttons = { 15 | 'Квартиры': '/kvartiry', 16 | 'Дома': '/doma_dachi_kottedzhi', 17 | 'Комнаты': '/komnaty', 18 | 'Коммерция': '/kommercheskaya_nedvizhimost', 19 | 'Купить': '/prodam', 20 | 'Снять': '/sdam' 21 | } 22 | 23 | krasnodarAreas = { 24 | 'Западный': '?district=359', 25 | 'Карасунский': 'district=360', 26 | 'Прикубанский': '?district=361', 27 | 'Старокорсунский': '?district=547', 28 | 'Центральный': '?district=362' 29 | } 30 | 31 | options = { 32 | 'start': 0, 33 | 'end': 5 34 | } 35 | 36 | result = [] 37 | 38 | 39 | TOKEN = config.TOKEN 40 | 41 | bot = telebot.TeleBot(TOKEN) 42 | 43 | 44 | ##Функция, которая обрабатывает команду /start 45 | @bot.message_handler(commands=['start']) 46 | def stepOne(message, info='Введите ваш город'): 47 | deleteReq = db.prepare("DELETE FROM task_table WHERE user_id = $1 AND active = false") 48 | deleteReq(message.chat.id) 49 | options['start'] = 0 50 | options['end'] = 5 51 | result.clear() 52 | custom_url.clear() 53 | custom_request.clear() 54 | 55 | sent = bot.send_message( 56 | message.chat.id, 57 | info 58 | ) 59 | 60 | bot.register_next_step_handler(sent, stepTwo) 61 | 62 | 63 | def stepTwo(message): 64 | arrCities = bd.getCitiesFromDb() 65 | 66 | city = message.text 67 | 68 | #Проверяет есть ли в массиве arrCities введенный город, если его нет, то перезаписываем переменную city 69 | try: 70 | arrCities.index(city) 71 | except: 72 | city = 'Нет такого города' 73 | 74 | if(city == 'Нет такого города'): 75 | info = city + '\n' + 'Введите город заного' 76 | stepOne(message, info) 77 | else: 78 | ins = db.prepare("INSERT INTO task_table (user_id) VALUES ($1)") 79 | 80 | ins(message.chat.id) 81 | 82 | cityLink = db.prepare('SELECT link FROM city WHERE name = $1') 83 | getCityLink = cityLink(city) 84 | custom_url.append(getCityLink[0][0]) 85 | 86 | custom_request['city'] = city 87 | 88 | keyboard = types.ReplyKeyboardMarkup(resize_keyboard=True) 89 | keyboard.add(*[types.KeyboardButton(name) for name in ['Квартиры', 'Дома', 'Комнаты', 'Коммерция']]) 90 | sent = bot.send_message(message.chat.id, 'Выберите тип недвижимости', reply_markup=keyboard) 91 | 92 | ##После отправки сообщения, бот ждет сообщение в ответ, чтобы вызвать функцию stepTwo() 93 | bot.register_next_step_handler(sent, stepThree) 94 | 95 | 96 | 97 | def stepThree(message): 98 | msg = message.text 99 | 100 | custom_request['realtyType'] = msg 101 | 102 | realtyLink = db.prepare('SELECT link FROM realty WHERE name = $1') 103 | getRealtyLink = realtyLink(msg) 104 | custom_url.append(getRealtyLink[0][0]) 105 | 106 | 107 | keyboard = types.ReplyKeyboardMarkup(resize_keyboard=True) 108 | keyboard.add(*[types.KeyboardButton(name) for name in ['Купить', 'Снять', 'Показать объявления']]) 109 | sent = bot.send_message(message.chat.id, 'Выберите услугу', reply_markup=keyboard) 110 | 111 | bot.register_next_step_handler(sent, actionStep) 112 | 113 | def actionStep(message): 114 | msg = message.text 115 | if(msg == 'Показать объявления'): 116 | showResults(message) 117 | else: 118 | custom_request['service'] = msg 119 | actionLink = db.prepare('SELECT link FROM action WHERE name = $1') 120 | getActionLink = actionLink(msg) 121 | custom_url.append(getActionLink[0][0]) 122 | # print(''.join(custom_url)) 123 | 124 | if(custom_request.get('realtyType') == 'Дома'): 125 | keyboard = types.ReplyKeyboardMarkup(resize_keyboard=True) 126 | keyboard.add(*[types.KeyboardButton(name) for name in ['Показать объявления']]) 127 | sent = bot.send_message(message.chat.id, 'Для этого типа недвижимости пока больше нет параметров для выбора, но мы над этим работаем. А пока вы можете посмотреть объйвления по заданному запросу', reply_markup=keyboard) 128 | 129 | bot.register_next_step_handler(sent, houseChoose) 130 | else: 131 | if(msg == 'Купить'): 132 | keyboard = types.ReplyKeyboardMarkup(resize_keyboard=True) 133 | keyboard.add(*[types.KeyboardButton(name) for name in ['Указать количество комнат', 'Показать объявления']]) 134 | sent = bot.send_message(message.chat.id, 'Выберите услугу', reply_markup=keyboard) 135 | 136 | bot.register_next_step_handler(sent, countRooms) 137 | if(msg == 'Снять'): 138 | keyboard = types.ReplyKeyboardMarkup(resize_keyboard=True) 139 | keyboard.add(*[types.KeyboardButton(name) for name in ['На длительный срок', 'Посуточно', 'Показать объявления']]) 140 | sent = bot.send_message(message.chat.id, 'Выберите срок на который хотите снять или можете посмотреть объявления по собранному запросу', reply_markup=keyboard) 141 | 142 | bot.register_next_step_handler(sent, termRent) 143 | 144 | def houseChoose(message): 145 | msg = message.text 146 | if(msg == 'Показать объявления'): 147 | showResults(message) 148 | 149 | def termRent(message): 150 | msg = message.text 151 | if(msg == 'Показать объявления'): 152 | showResults(message) 153 | else: 154 | if(msg == 'На длительный срок'): 155 | termUrl = '/na_dlitelnyy_srok' 156 | elif(msg == 'Посуточно'): 157 | termUrl = '/posutochno' 158 | 159 | custom_request['term'] = 'Длительность ' + msg 160 | custom_url.append(termUrl) 161 | 162 | keyboard = types.ReplyKeyboardMarkup(resize_keyboard=True) 163 | keyboard.add(*[types.KeyboardButton(name) for name in ['Студии']]) 164 | sent = bot.send_message(message.chat.id, 'Укажите количество комнат цифрой от 1 до 9 или выберите студии из предложенного варианта', reply_markup=keyboard) 165 | 166 | bot.register_next_step_handler(sent, countRoomsNext) 167 | 168 | 169 | def countRooms(message): 170 | msg = message.text 171 | if(msg == 'Показать объявления'): 172 | showResults(message) 173 | else: 174 | keyboard = types.ReplyKeyboardMarkup(resize_keyboard=True) 175 | keyboard.add(*[types.KeyboardButton(name) for name in ['Студии']]) 176 | sent = bot.send_message(message.chat.id, 'Укажите количество комнат цифрой от 1 до 9 или выберите студии из предложенного варианта', reply_markup=keyboard) 177 | 178 | bot.register_next_step_handler(sent, countRoomsNext) 179 | 180 | def countRoomsNext(message): 181 | msg = message.text 182 | if(msg == 'Студии'): 183 | roomUrl = '/studii' 184 | else: 185 | roomUrl = '/'+msg+'-komnatnye' 186 | msg = 'Количество комнат ' + msg 187 | 188 | custom_request['rooms'] = msg 189 | custom_url.append(roomUrl) 190 | 191 | if(custom_request.get('service') == 'Купить'): 192 | keyboard = types.ReplyKeyboardMarkup(resize_keyboard=True) 193 | keyboard.add(*[types.KeyboardButton(name) for name in ['Вторичка', 'Новостройка', 'Показать объявления']]) 194 | sent = bot.send_message(message.chat.id, 'Выберите вид объекта или можете посмотреть объявления по собранному запросу', reply_markup=keyboard) 195 | 196 | bot.register_next_step_handler(sent, vidObjOrShow) 197 | elif(custom_request.get('service') == 'Снять'): 198 | keyboard = types.ReplyKeyboardMarkup(resize_keyboard=True) 199 | keyboard.add(*[types.KeyboardButton(name) for name in ['Западный', 'Карасунский', 'Прикубанский', 'Центральный', 'Старокорсунский', 'Показать объявления']]) 200 | sent = bot.send_message(message.chat.id, 'Выберите нужный район или можете посмотреть объявления', reply_markup=keyboard) 201 | 202 | bot.register_next_step_handler(sent, areaChooseShow) 203 | 204 | def vidObjOrShow(message): 205 | msg = message.text 206 | if(msg == 'Показать объявления'): 207 | showResults(message) 208 | else: 209 | if(msg == 'Вторичка'): 210 | objUrl = '/vtorichka' 211 | elif(msg == 'Новостройка'): 212 | objUrl = '/novostroyka' 213 | 214 | custom_request['typeBuild'] = 'Вид объекта ' + msg 215 | custom_url.append(objUrl) 216 | print(''.join(custom_url)) 217 | if(custom_request['city'] == 'Краснодар'): 218 | keyboard = types.ReplyKeyboardMarkup(resize_keyboard=True) 219 | keyboard.add(*[types.KeyboardButton(name) for name in ['Западный', 'Карасунский', 'Прикубанский', 'Центральный', 'Старокорсунский', 'Показать объявления']]) 220 | sent = bot.send_message(message.chat.id, 'Выберите нужный район или можете посмотреть объявления', reply_markup=keyboard) 221 | 222 | bot.register_next_step_handler(sent, areaChooseShow) 223 | else: 224 | keyboard = types.ReplyKeyboardMarkup(resize_keyboard=True) 225 | keyboard.add(*[types.KeyboardButton(name) for name in ['Показать объявления']]) 226 | sent = bot.send_message(message.chat.id, 'Районов вашего города пока нет в базе, но мы работаем над этим. Введите числом приблизительное количество квадратных метров или можете посмотреть объявления', reply_markup=keyboard) 227 | 228 | bot.register_next_step_handler(sent, amountMetres) 229 | 230 | def areaChooseShow(message): 231 | msg = message.text 232 | if(msg == 'Показать объявления'): 233 | showResults(message) 234 | else: 235 | areaUrl = krasnodarAreas[msg] 236 | custom_request['area'] = 'Район ' + msg 237 | custom_url.append(areaUrl) 238 | print(''.join(custom_url)) 239 | 240 | keyboard = types.ReplyKeyboardMarkup(resize_keyboard=True) 241 | keyboard.add(*[types.KeyboardButton(name) for name in ['Показать объявления']]) 242 | sent = bot.send_message(message.chat.id, 'Введите числом приблизительное количество квадратных метров или можете посмотреть объявления', reply_markup=keyboard) 243 | 244 | bot.register_next_step_handler(sent, amountMetres) 245 | 246 | def amountMetres(message): 247 | msg = message.text 248 | if(msg == 'Показать объявления'): 249 | showResults(message) 250 | else: 251 | custom_request['metres'] = msg 252 | 253 | keyboard = types.ReplyKeyboardMarkup(resize_keyboard=True) 254 | keyboard.add(*[types.KeyboardButton(name) for name in ['Показать объявления', 'Посмотреть запрос', 'Создать новый запрос']]) 255 | sent = bot.send_message(message.chat.id, 'Вы ввели все возможные параметры. Теперь вы можете мосмотреть объявления по вашему запросу, посмотреть запрос, который вы ввели или создать новый запрос. Выберите нужное действие ниже', reply_markup=keyboard) 256 | 257 | bot.register_next_step_handler(sent, allOver) 258 | 259 | def allOver(message): 260 | msg = message.text 261 | if(msg == 'Показать объявления'): 262 | showResults(message) 263 | elif(msg == 'Посмотреть запрос'): 264 | showRequest(message) 265 | elif(msg == 'Создать новый запрос'): 266 | stepOne(message) 267 | 268 | def showRequest(message): 269 | info_msg = 'Вы ввели следующие параметры: \n' 270 | for item in custom_request: 271 | info_msg = info_msg + '- ' + custom_request[item] + '\n' 272 | 273 | info_msg = info_msg + 'Если вы где-то ошиблись или введенные параметры вас не устраивают, вы можете создать новый запрос или, если все устраиает, то можете посмотреть объявления по вашему запросу' 274 | 275 | keyboard = types.ReplyKeyboardMarkup(resize_keyboard=True) 276 | keyboard.add(*[types.KeyboardButton(name) for name in ['Показать объявления', 'Посмотреть запрос', 'Создать новый запрос']]) 277 | sent = bot.send_message(message.chat.id, info_msg, reply_markup=keyboard) 278 | 279 | bot.register_next_step_handler(sent, allOver) 280 | 281 | 282 | ##Покзать результат 283 | def showResults(message): 284 | ##Информаци о запросе 285 | info_msg = 'По Вашему запросу: \n' 286 | for item in custom_request: 287 | info_msg = info_msg + '- ' + custom_request[item] + '\n' 288 | 289 | info_msg = info_msg + 'Было найдено' 290 | 291 | URL = ''.join(custom_url) 292 | 293 | insertUrl = db.prepare("UPDATE task_table SET link = $1 WHERE user_id = $2 AND active = false") 294 | insertUrl(URL, message.chat.id) 295 | 296 | bot.send_message( 297 | message.chat.id, 298 | info_msg 299 | ) 300 | 301 | ##Парсим первую страницу по URL 302 | parse = avito.parse(avito.get_html(URL)) 303 | 304 | metres = custom_request.get('metres', None) 305 | 306 | if(metres != None): 307 | meters = int(custom_request['metres']) 308 | # search_str = '[%s - %s]' % (str(meters-10), str(meters+10)) 309 | search_str = r'[0-9]{1,2} м' 310 | # regx = re.compile(search_str) 311 | 312 | for item in parse: 313 | print(item['title']) 314 | if re.search(search_str, item['title']) is not None: 315 | rightStr = re.findall(search_str, item['title'])[0] 316 | numInTitle = int(rightStr.split(' ')[0]) 317 | if(numInTitle <= meters+10 and numInTitle >= meters-10): 318 | print(True) 319 | result.append(item) 320 | else: 321 | for item in parse: 322 | result.append(item) 323 | 324 | part = result[:options['end']] 325 | options['start'] = options['end'] 326 | options['end'] = options['end'] + 5 327 | 328 | 329 | #Парсим 2 и 3 страницы 330 | # for page in range(2, 4): 331 | # result2 = avito.parse(avito.get_html(custom_url + '?p=' + str(page))) 332 | # for item in result2: 333 | # result.append(item) 334 | 335 | ##Выводим результаты запроса 336 | for item in part: 337 | bot.send_message( 338 | message.chat.id, 339 | '{price} \n {link}'.format(price=item['price'], link=item['link']) 340 | ) 341 | 342 | afterShow(message) 343 | 344 | 345 | def afterShow(message): 346 | keyboard = types.ReplyKeyboardMarkup(resize_keyboard=True) 347 | keyboard.add(*[types.KeyboardButton(name) for name in ['Показать еще', 'Создать новый запрос']]) 348 | sent = bot.send_message(message.chat.id, 'Выберите следующее действие', reply_markup=keyboard) 349 | 350 | bot.register_next_step_handler(sent, chooseAction) 351 | 352 | def chooseAction(message): 353 | if (message.text == 'Показать еще'): 354 | showMore(message) 355 | else: 356 | createNew(message) 357 | 358 | def createNew(message): 359 | 360 | keyboard = types.ReplyKeyboardMarkup(resize_keyboard=True) 361 | keyboard.add(*[types.KeyboardButton(name) for name in ['Да', 'Нет']]) 362 | sent = bot.send_message(message.chat.id, 'Вы нашли, что хотели?', reply_markup=keyboard) 363 | 364 | bot.register_next_step_handler(sent, findRight) 365 | 366 | def findRight(message): 367 | msg = message.text 368 | 369 | if(msg == 'Да'): 370 | deleteReq = db.prepare("DELETE FROM task_table WHERE user_id = $1 AND active = false") 371 | deleteReq(message.chat.id) 372 | stepOne(message) 373 | else: 374 | keyboard = types.ReplyKeyboardMarkup(resize_keyboard=True) 375 | keyboard.add(*[types.KeyboardButton(name) for name in ['Да', 'Нет']]) 376 | sent = bot.send_message(message.chat.id, 'Хотите ли вы получать уведомления по вашему последнему запросу?', reply_markup=keyboard) 377 | 378 | bot.register_next_step_handler(sent, pushActive) 379 | 380 | def pushActive(message): 381 | msg = message.text 382 | if(msg == 'Нет'): 383 | deleteReq = db.prepare("DELETE FROM task_table WHERE user_id = $1 AND active = false") 384 | deleteReq(message.chat.id) 385 | stepOne(message) 386 | else: 387 | deleteReq = db.prepare("DELETE FROM task_table WHERE user_id = $1 AND active = true") 388 | deleteReq(message.chat.id) 389 | setActive = db.prepare("UPDATE task_table SET active = true WHERE user_id = $1 AND active = false") 390 | setActive(message.chat.id) 391 | stepOne(message) 392 | 393 | def showMore(message): 394 | part = result[options['start']:options['end']] 395 | options['start'] = options['end'] 396 | options['end'] = options['end'] + 5 397 | for item in part: 398 | bot.send_message( 399 | message.chat.id, 400 | '{price} \n {link}'.format(price=item['price'], link=item['link']) 401 | ) 402 | 403 | afterShow(message) 404 | 405 | def getZn(): 406 | links = db.prepare("SELECT link FROM task_table WHERE active = true") 407 | arrlink = [] 408 | for link in links: 409 | for item in link: 410 | arrlink.append(item) 411 | return arrlink 412 | 413 | def main(): 414 | links = getZn() 415 | for item in links: 416 | print(item) 417 | 418 | if __name__ == '__main__': 419 | bot.polling(none_stop=True) 420 | -------------------------------------------------------------------------------- /config.py: -------------------------------------------------------------------------------- 1 | TOKEN = '303092094:AAFdpjNi3EO-Utc5A598Mo5kcd4CwlWH9cc' -------------------------------------------------------------------------------- /index.py: -------------------------------------------------------------------------------- 1 | import urllib.request 2 | from bs4 import BeautifulSoup 3 | import csv 4 | 5 | MAIN_URL = 'http://www.ratingruneta.ru/web/krasnodar/' 6 | 7 | def save(studios, path): 8 | with open(path, 'w', encoding='utf-8') as csvfile: 9 | writer = csv.writer(csvfile) 10 | 11 | writer.writerow(('№', 'Название вебстудии', 'Выполнено проектов', 'Рейтинг', 'Год основания', 'Количество сотрудников', 'Веб сайт', 'Стоимость')) 12 | 13 | for item in studios: 14 | writer.writerow((item['name'], item['projects'], item['rate'], item['year'], item['stuff'], item['web_site'], item['price'])) 15 | 16 | def get_html(url): 17 | response = urllib.request.urlopen(url) 18 | return response.read() 19 | 20 | 21 | def parse(html): 22 | soup = BeautifulSoup(html, 'html.parser') 23 | table = soup.find('table', class_='for_tender') 24 | items = table.find_all('tr', class_='row-with-childs')[1:-1] 25 | web_studios = [] 26 | for item in items: 27 | name = item.find_all('td')[1].find('span').a.get_text() 28 | projects = item.find_all('td')[2].a.get_text() 29 | rate = item.find_all('td')[3].a.get_text() 30 | item_link = item.find_all('td')[1].find('span').a.get('href') 31 | web_studios.append({ 32 | 'name': name, 33 | 'projects': projects, 34 | 'rate': rate, 35 | 'link': item_link 36 | }) 37 | return web_studios 38 | 39 | def parseEachStudio(html): 40 | 41 | soup = BeautifulSoup(html, 'html.parser') 42 | dop_options = {} 43 | table = soup.find('table', class_='catalogueTab') 44 | options = table.find_all('td')[1].find_all('p') 45 | 46 | for option in options: 47 | if(option.find('i', class_='grey').get_text() == 'Год основания:'): 48 | dop_options.update({ 49 | 'year': option.find('span').get_text() 50 | }) 51 | elif(option.find('i', class_='grey').get_text() == 'Количество сотрудников:'): 52 | dop_options.update({ 53 | 'stuff': option.find('span').get_text() 54 | }) 55 | elif(option.find('i', class_='grey').get_text() == 'Сайт компании:'): 56 | dop_options.update({ 57 | 'web_site': option.a.get_text() 58 | }) 59 | elif(option.find('i', class_='grey').get_text() == 'Стоимость услуг по разработке сайтов:'): 60 | dop_options.update({ 61 | 'price': option.a.get_text() 62 | }) 63 | 64 | dop_options.setdefault('stuff', '-') 65 | dop_options.setdefault('web_site', '-') 66 | dop_options.setdefault('price', '-') 67 | 68 | return dop_options 69 | 70 | 71 | def main(): 72 | studios = parse(get_html(MAIN_URL)) 73 | count_items = len(studios) 74 | links = [item['link'] for item in studios] 75 | 76 | for item in range(0, count_items): 77 | print('Идет Парсинг %d%%' % (item / count_items * 100)) 78 | dop_options = parseEachStudio(get_html(links[item])) 79 | studios[item].update(dop_options) 80 | 81 | #print(studios) 82 | 83 | save(studios, 'studios_list.csv') 84 | 85 | 86 | if __name__ == '__main__': 87 | main() -------------------------------------------------------------------------------- /studios_list.csv: -------------------------------------------------------------------------------- 1 | Название вебстудии,Выполнено проектов,Рейтинг,Год основания,Количество сотрудников,Веб сайт,Стоимость 2 | «WebFormula»,219,10.04,2008,21-30,webformula.pro,50 000 — 800 000 3 | Iarga,81,3.53,2008,8-15,http://iarga.ru/,150 000 — 580 000 4 | Voodoo,101,3.14,2000,8-15,www.voodoo.ru,70 000 — 500 000 5 | «Very-good»,67,3.01,2008,16-20,http://very-good.ru,60 000 — 800 000 6 | Rutorika,30,2.36,2011,21-30,http://rutorika.ru,250 000 — 1 500 000 7 | Майрон,64,2.20,2009,4-7,mairon-studio.ru,- 8 | РуФокс,16,2.01,2004,16-20,http://web.rufox.ru/,60 000 — 2 500 000 9 | """Топ Медиа""",12,1.99,2001,31-40,http://www.топмедиа.рф/,- 10 | Web112,53,1.63,2009,4-7,http://web112.biz/,100 000 — 5 000 000 11 | BusinessProfi,71,1.61,2005,8-15,http://bizprofi.ru,25 000 — 1 900 000 12 | """Рашн Роботикс""",28,1.25,2009,21-30,http://rusrobots.ru/,100 000 — 1 500 000 13 | Кватрокс,26,1.21,2005,4-7,www.quatrox.ru,10 999 — 49 999 14 | """Интернет-Имидж""",12,1.20,2000,8-15,www.internetimage.ru,30 000 — 700 000 15 | OneRule,15,1.17,2015,4-7,http://onerule.ru/,50 000 — 500 000 16 | """Интернет Коммерсант""",38,1.09,2010,8-15,http://incomyug.ru/,30 000 — 500 000 17 | Zeebra,19,1.07,2013,4-7,www.zeebra.ru,50 000 — 300 000 18 | Малинка,49,1.02,2009,4-7,malinkastudio.com,68 000 — 990 000 19 | New-webstudio,20,1.01,2014,4-7,new-webstudio.ru,20 000 — 200 000 20 | Quartex Group,15,0.97,2003,4-7,http://www.quartex.ru,80 000 — 2 000 000 21 | Southmedia,42,0.94,2008,16-20,http://southmedia.ru,65 000 — 1 000 000 22 | Redham,47,0.93,2009,4-7,www.redhamsites.ru,30 000 — 90 000 23 | XY STUDIO,62,0.89,2012,8-15,xystudio.ru,25 000 — 300 000 24 | KubanTrend,43,0.88,2004,8-15,www.kubantrend.ru,- 25 | Spider Group,14,0.87,2000,21-30,www.spider.ru,190 000 — 2 000 000 26 | Doodah,22,0.86,2011,16-20,http://doodah.ru/,- 27 | WoW DESIGN,16,0.77,2013,1-3,www.wow-design.ru,20 000 — 140 000 28 | creativecult,56,0.62,2013,8-15,http://creativecult.ru,30 000 — 160 000 29 | АЭЛИТА ДИЗАЙН,27,0.56,2006,8-15,aelitadesign.ru,30 000 — 1 000 000 30 | celebro,30,0.53,2011,1-3,http://celebro.ru,25 000 — 500 000 31 | ABP company,20,0.50,2007,8-15,http://abpc.ru,60 000 — 800 000 32 | Viocom,23,0.49,2010,4-7,http://www.viocom.ru/,50 000 — 800 000 33 | Airty,12,0.47,2013,4-7,www.airty.ru,50 000 — 1 000 000 34 | """Мастер Флеш""",37,0.46,2009,4-7,www.masterflash.ru,18 000 — 100 000 35 | Русь-технология,17,0.45,2009,8-15,http://rus-technologia.ru/,30 000 — 160 000 36 | """Лаборатория продаж""",18,0.45,2014,8-15,http://labsales.ru/,30 000 — 500 000 37 | """Бизнес Код""",26,0.45,2008,4-7,www.icbcode.ru,40 000 — 400 000 38 | Mobido,5,0.45,2004,4-7,http://kubancom.ru,- 39 | """Контраст""",11,0.42,2010,4-7,thecontrust.ru,60 000 — 3 000 000 40 | """Регион""",54,0.38,2010,4-7,http://rv36.ru/,15 000 — 250 000 41 | BIKRASNODAR №1,74,0.37,2011,-,bigkrasnodar.ru,20 000 — 500 000 42 | AVN-GROUP,16,0.35,2009,4-7,avn-group.ru,40 000 — 1 000 000 43 | AdVerbs,9,0.32,2013,8-15,adverbs.ru,10 000 — 200 000 44 | Devorcs,26,0.25,2011,4-7,http://devorcs.com/ru,50 000 — 750 000 45 | """Рекламные Сети""",7,0.25,2012,8-15,reklamnyeseti.ru,35 000 — 400 000 46 | Web-Resource,20,0.24,2013,4-7,http://web-resource.pro/,40 000 — 800 000 47 | Round Interactive,12,0.24,2009,8-15,http://www.round-interactive.ru,60 000 — 1 000 000 48 | LaFedja,23,0.23,2007,4-7,http://lafedja.ru,65 000 — 300 000 49 | """Белый Шар""",11,0.23,2005,4-7,http://wssd.ru,15 000 — 120 000 50 | РИЦ САДДАТ,18,0.23,2007,4-7,saddat.ru,15 000 — 350 000 51 | ReadyScript lab.,7,0.22,2011,4-7,readyscript.ru,80 000 — 160 000 52 | PlatZkart,6,0.19,2004,-,http://platzkart.ru/,200 000 — 1 500 000 53 | WYKIWYL,10,0.17,2004,21-30,http://wykiwyl-pro.ru/,15 000 — 300 000 54 | Бородачев Роман,11,0.17,2010,1-3,www.free-lance.ru/users/artpixels,- 55 | Студия snegurow.ru,13,0.15,2001,1-3,http://www.snegurow.ru,27 070 — 70 350 56 | Regrafica,5,0.15,2014,4-7,http://regrafica.ru,60 000 — 300 000 57 | EyeFly,24,0.15,2008,4-7,eyefly.ru,40 000 — 1 000 000 58 | """Максимум""",9,0.15,2010,4-7,http://studio-maximum.ru/,25 000 — 700 000 59 | IVUX,10,0.14,2011,4-7,ivux.ru,9 990 — 160 000 60 | Darkheart,13,0.14,2011,1-3,http://darkheart.ru,30 000 — 300 000 61 | """БитСайт""",10,0.13,2009,8-15,bitsite.ru,30 000 — 1 000 000 62 | BadStudio,11,0.13,2015,1-3,badstudio.ru?utm_source=cmsmagazine.ru,25 000 — 600 000 63 | Re:Say Group,15,0.13,2011,4-7,http://resay.ru,- 64 | Webemot,10,0.11,2013,4-7,http://webemot.com,50 000 — 1 500 000 65 | РГ Зеркало,10,0.10,2003,21-30,www.zerkalo-k.ru,25 000 — 250 000 66 | """Департамент Дизайна""",7,0.09,2009,16-20,www.artassist.ru,30 000 — 500 000 67 | КИТ,11,0.08,2014,4-7,stdkit.ru,15 000 — 200 000 68 | Биатум,10,0.08,2008,8-15,beatum-site.ru,40 000 — 200 000 69 | Digital Set,12,0.08,2011,4-7,digital-set.ru,15 000 — 90 000 70 | IT-DELTA,5,0.08,2009,21-30,it-delta.ru,100 000 — 800 000 71 | М.Програм,9,0.07,2010,1-3,mprogram.ru,15 000 — 1 000 000 72 | СеоСемантика,9,0.05,2010,4-7,http://seosema.ru/,12 000 — 100 000 73 | КИТ-Реклама,16,0.05,2016,4-7,kit-reklama.ru,25 000 — 140 000 74 | AVFsite,9,0.05,2010,1-3,www.avfsite.ru,15 000 — 100 000 75 | ЮГ-ВебДизайн,7,0.05,2014,4-7,yug-webdesign.ru,20 000 — 120 000 76 | Аванзет,5,0.04,2012,4-7,a1z.ru,46 000 — 320 000 77 | Weblines,9,0.04,2010,-,http://weblines.org,45 000 — 400 000 78 | Artworkshop,8,0.02,2015,4-7,artworkshop.pro,15 000 — 300 000 79 | RedGarnet,5,0,2010,4-7,http://www.redgarnet.ru,- 80 | --------------------------------------------------------------------------------