Уведомления

Группа в Telegram: @pythonsu

#1 Ноя. 17, 2016 11:29:05

S_K_Y_E
Зарегистрирован: 2016-11-17
Сообщения: 5
Репутация: +  0  -
Профиль   Отправить e-mail  

Парсинг сайта LinkedIn

Добрый день, уважаемые знатоки Python!

Возникла такая проблема, очень прошу помощи в поиске ее решения.
Есть скрипт, который парсит данный с сайта LinkedIn по конкретным фильтрам и запросам. Сам скрипт работает без вопросов, данные берутся корректно, кроме одного пункта (весь скрипт в аттачах).
Дело в том, что поле Specialties в коде содержит данные в таком виде: “specialties”: (квадратная скобка) “PCB”,“Pil”,“Led & Adaptör”,“Aluminium PCB” (квадратная скобка) . Все другие переменные имеют описание только в одних кавычках, посему содержание берется без проблем, а тут - только первое слово и хоть ты тресни…

Подскажите пожалуйста, как “научить” скрипт смотреть на открывающую и закрывающую скобку и брать данные, которые внутри них, а не только то, что в кавычках?

Часть кода прставлена ниже:

 def extract_data(www,link):
	soup = BeautifulSoup(www)
	
	name = soup.find('h1',{'class':'name'}).text.strip()
	# off_name = 
	try:
		size = soup.find('li',{'class':'company-size'}).find('p').text.strip()
	except:
		size = ''
	try:
		country = soup.find('li',{'class':'vcard hq'}).find('span',{'class':'country-name'}).text.strip()
	except:
		country = ''
	try:
		address = soup.find('li',{'class':'vcard hq'}).find('span',{'class':'street-address'}).text.strip()
	except:
		address = ''
	try:
		c1 = soup.find('li',{'class':'vcard hq'}).find('span',{'class':'locality'}).text.strip().replace(',','')
	except:
		c1 = ''
	try:
		c2 = soup.find('li',{'class':'vcard hq'}).find('abbr',{'class':'region'}).text.strip()
	except:
		try:
			c2 = soup.find('li',{'class':'vcard hq'}).find('span',{'class':'region'}).text.strip()
		except:
			c2 = ''
               try:
                        specialities  = soup.find('li',{'class':'specialties'}).find('p').text.strip()
                  except:
                          specialties = ''
	try:
		industry = soup.find('li',{'class':'industry'}).find('p').text.strip()
	except:
		industry = ''
	try:
		web = soup.find('li',{'class':'website'}).find('a').text.strip()
	except:
		web = ''
	try:
		zip_code = soup.find('li',{'class':'vcard hq'}).find('span',{'class':'postal-code'}).text.strip()
	except:
		zip_code = ''
	try:
		desc = soup.find('div',{'class':'basic-info-description'}).text.strip()
	except:
		desc = ''
	# print([link, name, size, country, address, c1, c2, specialties, industry, web, zip_code, desc])
	return [link, name, size, country, address, c1, c2, specialties, industry, web, zip_code, desc]

Заранее огромное спасибо!

Отредактировано S_K_Y_E (Ноя. 17, 2016 11:30:09)

Прикреплённый файлы:
attachment linkedin scrap.zip (6,2 KБ)

Офлайн

#2 Ноя. 17, 2016 12:01:37

FishHook
От:
Зарегистрирован: 2011-01-08
Сообщения: 8312
Репутация: +  568  -
Профиль   Отправить e-mail  

Парсинг сайта LinkedIn

Самого то не задрало эту елку писать?
Если у вы видите миллион одинаковых строк кода и у вас не чешется спина - срочно меняйте профессию


  
def find(tag, attrs, tag1, attrs1):
   try:
       return soup.find(tag, attrs).find(tag1, attrs1).text.strip()
   except:
       return ""
и теперь вместо ёлки пишем
  
c2 = find('li',{'class':'vcard hq'}, 'span',{'class':'region'})
zip_code = find('li',{'class':'vcard hq'}, 'span',{'class':'postal-code'})
# и так далее



Отредактировано FishHook (Ноя. 17, 2016 12:02:07)

Офлайн

#3 Ноя. 17, 2016 12:38:41

S_K_Y_E
Зарегистрирован: 2016-11-17
Сообщения: 5
Репутация: +  0  -
Профиль   Отправить e-mail  

Парсинг сайта LinkedIn

Задрало, и еще как
Скрипт по сути достался “в наследство” и выглядел еще хуже, поверьте.. А шеф категорически не хочет слышать о смене скрипта (разве что втихую это сделаю). Посему поставлена задача типа “работайте на этом говне”.

Но а если по сути - то Ваш способ действительно выдернет все данные до следующего тэга в коде страницы?
Я просто думал, чтобы ему поставить какое-то условие конкрентно на этот тэг типа если начало идет с “открывающая скобка” то начинай копировать все вплоть до нахождения “закрывающая скобка”.

Отредактировано S_K_Y_E (Ноя. 17, 2016 12:40:35)

Офлайн

#4 Ноя. 20, 2016 11:56:30

S_K_Y_E
Зарегистрирован: 2016-11-17
Сообщения: 5
Репутация: +  0  -
Профиль   Отправить e-mail  

Парсинг сайта LinkedIn

Добрый день! Прошу помощи, потому что у самого уже видимо замылен глаз и не вижу ошибку..
Есть кусок кода

 with open("scraped.pkl","wb") as p:
		pickle.dump(out, p)
	out2 = []
	for k in out:
		out2.append(k.split('?')[0])
	out3 = list(set(out2))
	with open('companies.txt','w',encoding='utf-8') as f:
		f.write('\n'.join(out3))
except Exception as ex:
	print(ex)
	print(traceback.format_exc())
	with open("err result.pkl","wb") as p:
		pickle.dump(out, p)
		print('error dump OK')
		input()
		
finally:
	driver.quit()

До этого вверху код парсил страницы, в файл все сохранил, только теперь проблемы с извлечением этого всего в текстовый файл companies.txt. Не могу понять, почему скрипт это файл даже не создает + практически моментально закрывает окно (т.е. метод input() не срабатывает).

Гуру, ткните, пожалуйста, носом, может чего-то очевидного не вижу?
Заранее спасибо!

Офлайн

#5 Ноя. 21, 2016 04:30:52

py.user.next
От:
Зарегистрирован: 2010-04-29
Сообщения: 9977
Репутация: +  857  -
Профиль   Отправить e-mail  

Парсинг сайта LinkedIn

S_K_Y_E
даже не создает + практически моментально закрывает окно
Во второй строке перед pickle лишний отступ. Он определяет блок для with, и всё, что ниже, не принадлежит этому блоку, потому что отступ другой. А когда он доходит до следующей строки, с out2, он видит отступ в строке и не понимает, чей это отступ (отступ блока какой конструкции) и выдаёт синтаксическую ошибку. А синтаксические ошибки исключениями не считаются.

S_K_Y_E
практически моментально закрывает окно
Тебе надо научиться запускать программы в консоли (для этого открывать консоль отдельно). Тогда бы ты увидел, что там пишется.



Отредактировано py.user.next (Ноя. 21, 2016 04:32:32)

Офлайн

#6 Ноя. 21, 2016 12:15:06

S_K_Y_E
Зарегистрирован: 2016-11-17
Сообщения: 5
Репутация: +  0  -
Профиль   Отправить e-mail  

Парсинг сайта LinkedIn

Спасибо большое за ответ!
Попробую изменить синтаксическую конструкцию и попробую еще раз

Про консоль вообще вылетело из головы, но потом додумался, и вот что выдает:


Т.е. это и есть синтаксическая ошибка?

Офлайн

#7 Ноя. 21, 2016 15:00:44

py.user.next
От:
Зарегистрирован: 2010-04-29
Сообщения: 9977
Репутация: +  857  -
Профиль   Отправить e-mail  

Парсинг сайта LinkedIn

S_K_Y_E
Т.е. это и есть синтаксическая ошибка?
Это уже другая ошибка. k - это не строка, а список.



Офлайн

#8 Ноя. 21, 2016 23:12:03

S_K_Y_E
Зарегистрирован: 2016-11-17
Сообщения: 5
Репутация: +  0  -
Профиль   Отправить e-mail  

Парсинг сайта LinkedIn

py.user.next спасибо за ответ!
Тогда это немного странно, т.к. я формирую файл как единую строку, чтобы в дальнейшем ее как раз и разбить на отдельные строки по сепаратору..
Код такой:

 from selenium import webdriver
from selenium.webdriver.common.desired_capabilities import DesiredCapabilities
from selenium.webdriver.common.by import By
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.support.ui import Select
from selenium.common.exceptions import NoSuchElementException
from selenium.common.exceptions import NoAlertPresentException
import unittest, time, re
import traceback
import os
import pickle
import csv
from bs4 import BeautifulSoup
import pprint
import random
from account import settings
links = [i.strip() for i in open('links.txt')]
random.shuffle(links)
try:
	if 1:
		driver = webdriver.Chrome()
		driver.set_window_size(1200, 800)
		driver.implicitly_wait(4)
	else:
		profile=webdriver.FirefoxProfile()
		profile.set_preference("intl.accept_languages", "en")
		firefox_capabilities = DesiredCapabilities.FIREFOX
		firefox_capabilities['marionette'] = True
		driver = webdriver.Firefox(firefox_profile=profile,capabilities=firefox_capabilities)
		driver.set_window_size(1300, 1000)
		driver.implicitly_wait(30)
	driver.get("http://www.linkedin.com")
	time.sleep(3)
	emailBox = driver.find_element_by_xpath("//input[@id='login-email']")
	emailBox.send_keys(settings['login'])
	time.sleep(2)
	passwordBox = driver.find_element_by_xpath("//input[@id='login-password']")
	passwordBox.send_keys(settings['pass'])
	time.sleep(2)
	passwordBox.submit()
	time.sleep(5)
	
	out = []
	cntr = 1
	for link in links:
		print('Link %s/%s' % (cntr, len(links)))
		cntr += 1
		buf = []
		driver.get(link)
		time.sleep(3)
		pcnt = 1
		while True:
			pag = driver.find_elements_by_xpath("//div[@id='results-pagination']/ul[@class='pagination']/li[@class='next']")
			print("Page: %s" % pcnt)
			pcnt += 1
			if len(pag) > 0:
				print('next page button')
				urls = driver.find_elements_by_xpath("//div[@id='results-container']/ol[@id='results']/li/div[@class='bd']/h3/a")
				if urls:
					hrefs = [i.get_attribute('href') for i in urls]
					buf += hrefs
				driver.find_element_by_xpath("//div[@id='results-pagination']/ul[@class='pagination']/li[@class='next']").click()
			else:
				print('no next page button')
				urls = driver.find_elements_by_xpath("//div[@id='results-container']/ol[@id='results']/li/div[@class='bd']/h3/a")
				if urls:
					hrefs = [i.get_attribute('href') for i in urls]
					buf += hrefs
				break
			time.sleep(3)
		out.append([link, buf])
			time.sleep(3)
	with open("scraped.pkl","wb") as p:
		pickle.dump(out, p)
	out2 = []
	for k in out:
		out2.append(k.split('?')[0])
	out3 = list(set(out2))
	with open('companies.txt','w',encoding='utf-8') as f:
		f.write('\n'.join(out3))
except Exception as ex:
	print(ex)
	print(traceback.format_exc())
	with open("err result.pkl","wb") as p:
		pickle.dump(out, p)
		print('error dump OK')
		input()
		
finally:
	driver.quit()


Что меня сильно начало смущать - так это то, что данные после работы скрипта в файле показываются ну в очень странный способ:


Для разития руководствовался классическим подходом, создав пустой список и методом append (ну или extend вместе со split) разделить его по строкам по сепаратору “?”.

Может быть, где-то ошибочный подход?

Офлайн

#9 Ноя. 22, 2016 02:56:02

py.user.next
От:
Зарегистрирован: 2010-04-29
Сообщения: 9977
Репутация: +  857  -
Профиль   Отправить e-mail  

Парсинг сайта LinkedIn

S_K_Y_E
  
out.append([link, buf])
Ну, вот у тебя список добавляется в out. У тебя получается, что out - это список списков, где каждый список в out представляет из себя строку link и список строк buf. При переборе надо просто смотреть на элементы out как на списки, а не как на строки. А чтобы получить строки, нужно дальше раскладывать.

S_K_Y_E
Что меня сильно начало смущать - так это то, что данные после работы скрипта в файле показываются ну в очень странный способ:
Ну, это же формат pickle, там пишется служебная информация о каждом сохранённом объекте, чтобы потом его можно было точно восстановить. Список - это объект, строка - это объект, число - это объект. Объект обладает типом. При сохранении записывается всё об объектах и их вложенности.



Отредактировано py.user.next (Ноя. 22, 2016 02:59:40)

Офлайн

Board footer

Модераторировать

Powered by DjangoBB

Lo-Fi Version