Войти

Показать полную графическую версию : python вопрос по работе скрипта


Страниц : [1] 2

dark-------13
25-03-2019, 11:45
Добрый день есть такой парсер сайта, который должен скачивать изображения с страниц галереи.
Изначально был написан его разработчиком на python 2.75.
Сейчас пытаюсь адаптировать скрипт под python 3.7.2
Не могу понять почему не может найти имя пользователя в адресе.
Сам не программист, адаптирую скрипт для себя.... Помогите пожалуйста
Немного поправил код , теперь выдается другая ошибка:



from __future__ import print_function
from urllib.request import urlopen, urlretrieve
import mechanize
import pickle
import random
import sys
import re
import os


PAGES = []
ARTIST = ""
IMG_BUFF = []
TITLES = []
LOGGED_IN = False


class Page:
def __init__(self, link=None, search=False):
global TITLES
if (search):
phrase = ""
while (phrase != '~q'):
phrase = input("Search ~q to quit: ")
try:
source = "http://" + ARTIST + ".deviantart.com/gallery/?catpath=%2F&q=" + \
'+'.join(phrase.split())
print("Searching for:", source)
gallery = open_page(source)
if (re.findall("no deviations yet\!", gallery)):
print("No Results")
continue
print("Results Found")
break
except:
print("Bad phrase")
continue
else:
self.__index = int(int(link[link.find('?offset=') + 8:]) / 24) + 1
gallery = open_page(link)
self.__images = []
blocks = get_blocks(gallery)
for block in blocks:
title = re.findall('title="(.*?) by ' + ARTIST, block)[0]
self.__title = title
TITLES.append(self.__title)
self.__images.append(Image(self, self.__title, block))

def get_images(self):
return self.__images

def get_index(self):
return self.__index


class Image:
def __init__(self, page, title, block):
self.__artist = ARTIST
self.__page = page
self.__title = title
self.__date = re.findall(ARTIST + ', (.*?) in', block)[0]
self.__mature = False
self.__gif = False
found = re.findall('data-super-(?:full-)?img="(.*?)"', block) + \
[re.findall('src="(.*?)"', block)[0]]
if (len(found) == 3):
self.__quality = 3
self.__link = found[1]
elif (len(found) == 2):
self.__quality = 2
self.__link = found[0]
elif (len(found) == 1):
self.__quality = 1
if ('gif' in found[0]):
self.__gif = True
if (re.findall('ismature', block)):
self.__mature = True
self.__link = found[0]
self.__ext = self.__link[len(self.__link) - 4:]

def dl_image(self):
if (self.__gif) or (self.__mature):
status = ' ! '
else:
status = '\t'
status += str(self.__quality) + " [.] "
status += self.__title
print(status, end='\r')
mod = 1
while (self.__title + str(mod) + self.__ext in os.listdir('.')):
mod += 1
urlretrieve(self.__link, self.__title.replace('/', '') + str(mod) + self.__ext)
print(status.replace('.', '+'))

def get_title(self):
return self.__title

def is_mat(self):
return self.__mature


class NoHistory(object):
def add(self, *a, **k):
pass

def clear(self):
pass


def daSetBrowser():
useragents = (
'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/535.1 (KHTML, like Gecko) Chrome/14.0.835.202 Safari/535.1',
'Mozilla/5.0 (Windows NT 6.1; WOW64; rv:7.0.1) Gecko/20100101',
'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_6_8) AppleWebKit/534.50 (KHTML, like Gecko) Version/5.1 Safari/534.50',
'Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.1; Trident/4.0)',
'Opera/9.99 (Windows NT 5.1; U; pl) Presto/9.9.9',
'Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_5_6; en-US) AppleWebKit/530.5 (KHTML, like Gecko) Chrome/ Safari/530.5',
'Mozilla/5.0 (Windows; U; Windows NT 6.1; en-US) AppleWebKit/533.2 (KHTML, like Gecko) Chrome/6.0',
'Mozilla/5.0 (Windows; U; Windows NT 6.1; pl; rv:1.9.1) Gecko/20090624 Firefox/3.5 (.NET CLR 3.5.30729)'
)
global BROWSER
BROWSER = mechanize.Browser(history=NoHistory())
BROWSER.set_handle_redirect(True)
BROWSER.set_handle_robots(False)
BROWSER.addheaders = [('Referer', 'http://www.deviantart.com/')]
BROWSER.addheaders = [('User-Agent', random.choice(useragents))]


def daLogin(username, password):
data = ""
try:
BROWSER.open('https://www.deviantart.com/users/login', "ref=http%3A%2F%2Fwww.deviantart.com%2F&remember_me=1")
BROWSER.select_form(nr=1)
BROWSER.form['username'] = username
BROWSER.form['password'] = password
BROWSER.submit()
data = BROWSER.response().read()
except urllib.error.HTTPError as e:
print("HTTP Error:", e.code)
sys.exit()
except urllib.error.URLError as e:
print("URL Error:", e.reason)
sys.exit()
if re.search("The password you entered was incorrect", data):
print("Wrong password or username. Attempting to download anyway.")
elif re.search("\"loggedIn\":true", data):
print("Logged in!")
global LOGGED_IN
LOGGED_IN = True
else:
print("Login unsuccessful. Attempting to download anyway.")


def startup():
print("\ngetdeviantart 1.0")
while True:
artist = input("Enter artist: ").lower()
try:
source = "http://" + artist + ".deviantart.com/gallery/?offset=0"
gallery = open_page(source)
artist = re.findall('<title>(.*?)&#', gallery)[0]
print("Found", artist)
if (re.findall("no deviations yet\!", gallery)):
print(artist, "has no art.")
continue
try:
os.mkdir(artist)
except:
pass
os.chdir(artist)
gallery = open_page(source)
break
except:
print("User not found, try again.")
continue
global ARTIST
ARTIST = artist
return gallery, source


def count_pages(text, source):
found = re.findall('(\d+)</a></li><li class="next"', text)[0]
pages = []
for i in range(0, int(found) * 24, 24):
pages.append(source[:-1] + str(i))
return pages


def menu():
print("\n1) Download all pages\
\n2) Select pages\
\n3) Select images page by page\
\n4) Search for image\
\n5) Choose different artist\
\n6) Quit")
choice = 0
while (choice < 1) or (choice > 6):
try:
choice = int(input("Choice> "))
except ValueError:
continue
return choice


def execute(choice, all_pages, source):
global PAGES
global ARTIST
global IMG_BUFF
global TITLES

if (choice == 1):
download(range(1, len(all_pages) + 1), source)

elif (choice == 2):
sel_pages = input_vals(pg=True, last=len(all_pages))
download(sel_pages, source)

elif (choice == 3):
sel_pages = input_vals(pg=True, last=len(all_pages))
download(sel_pages, source, sel_imgs=True)

elif (choice == 4):
search()

elif (choice == 5):
PAGES = []
ARTIST = ""
IMG_BUFF = []
TITLES = []


def download(pages, source, sel_imgs=False):
global PAGES
page_nums = pages
source = source[:-1]
page_links = []
for var in page_nums:
page_links.append(source + str((int(var) - 1) * 24))

for link in page_links:
PAGES.append(Page(link))
page = PAGES[-1]
print("\nPage #", page.get_index())
buff_down(page, sel_imgs)


def buff_down(page, sel_imgs):
global IMG_BUFF
index = 1
for image in page.get_images():
if (sel_imgs):
if (image.is_mat()):
s = ' ! '
else:
s = '\t'
print(s + str(index) + ')', image.get_title())
IMG_BUFF.append(image)
index += 1
else:
image.dl_image()
if (sel_imgs):
for img in input_vals(img=True, last=len(IMG_BUFF)):
IMG_BUFF[int(img) - 1].dl_image()
IMG_BUFF = []


def search():
page = Page(search=True)
buff_down(page, True)


def input_vals(pg=False, img=False, last=0):
output = []
while True:
try:
if (pg):
in_vals = input("Pages to get/search (1-3,5,6-8 etc): ")
in_vals = in_vals.replace(' ', '').split(',')
elif (img):
in_vals = input("Images to download (1-3,5,6-8 etc): ")
in_vals = in_vals.replace(' ', '').split(',')
for val in in_vals:
if (val.isdigit()):
output.append(int(val))
elif ('-' in val):
if not ((val.replace('-', '').isdigit())):
raise ValueError
else:
left = int(val[:val.find('-')])
right = int(val[val.find('-') + 1:]) + 1
if (left > right):
raise ValueError
else:
output += [int(var) for var in range(left, right)]
elif (int(val) <= 0):
raise ValueError
else:
raise ValueError

output = [int(a) for a in output]
if (max(output) > last):
raise ValueError
if (output.sort()) != None:
output = output.sort()
output = [str(a) for a in output]
return output

except ValueError:
print("Bad format, Try again.")
output = []
continue


def get_blocks(text):
return [re.findall('</smoothie>.*</div>', text)[0]] \
+ re.findall('</span></small><!-- TTT\$ --></span></div> <div.*', text)


def open_page(url):
if (LOGGED_IN):
return BROWSER.open(url).read()
else:
return urlopen(url).read().decode("utf-8")


def get_account():
fil = '.DeVaCtinfo.p'
choice = ''
while (choice != 'y') and (choice != 'n'):
choice = input("Log in? (y/n): ").lower()
if (choice == 'n'):
return [None, None, 0]
choice = ''
while (choice != 'y') and (choice != 'n'):
choice = input("New Account? (y/n): ").lower()
if (choice == 'y'):
print("Use throwaway account..")
uname = input("Enter account username: ")
passwd = input("Enter account password: ")
pickle.dump('\n'.join([uname, passwd]), open(fil, 'wb'))
return [uname, passwd, 0]
else:
try:
uname, passwd = pickle.load(open(fil, 'rb')).split()
return [uname, passwd, 0]
except:
print("Bad account info or no user on file.")
return [None, None, 1]


def main():
global PAGES
global IMG_BUFF
global TITLES
choice = 5
acl = [None, None, 1]
while (acl[2] != 0):
acl = get_account()
if (acl[0] and acl[1]):
daSetBrowser()
daLogin(acl[0], acl[1])
while (choice != 6):
if (choice == 5):
gallery, source = startup()
all_pages = count_pages(gallery, source)
print(ARTIST, "has", len(all_pages), "pages of art.")
choice = menu()
if (choice == 6):
break
else:
execute(choice, all_pages, source)
PAGES = []
IMG_BUFF = []
TITLES = []
print("Quitting..")


main()

shisik
25-03-2019, 18:03
Немного поправил код , теперь выдается другая ошибка: »

А другая ошибка - это какая?

Iska
25-03-2019, 18:15
dark-------13, почему бы не обратиться к автору? Анализ корректности парсинга страниц — дело не быстрое. Здесь дело может быть не в одной ошибке.

Bumbik
25-03-2019, 18:37
для парсинга в питоне есть requests и beautifulsoup, по нормальному все надо переписывать

Iska
25-03-2019, 19:27
и beautifulsoup, »
Самое то!

dark-------13
26-03-2019, 00:46
Проблема после функции, программа как понимаю останавливается с ошибкой из-за того, что нужных данных не обнаружено:


def get_blocks(text):
return [re.findall('</smoothie>.*</div>', text)[0]] \
+ re.findall('</span></span><!-- TTT\$ --></span></div> <div.*', text)


Непонятно как она выбирает данные о ссылках на фотографии для последующего разбора в другой функции. Части из тегов на сайте уже нет и изображения хранятся между другими тегами.

Iska
26-03-2019, 06:59
Части из тегов на сайте уже нет и изображения хранятся между другими тегами. »
dark-------13, про то и речь. Это не найти и поправить ошибку в коде. Это надо садиться и долго и нудно разбираться сначала в коде, а затем — что и как сейчас на сайте устроено. Это не дело пяти минут.

dark-------13
26-03-2019, 08:35
про то и речь. »


Вы могли бы хотя бы на своем примере показать, что какие текстовые данные вернет данная функция ?

Если например создать переменную с такими же тегами - например хоть в тексте программы, а в теги и руками запихнуть пару ссылок на картинки, или текст вместо них.

Вообще как правильно вывести результат ее работы на экран ?

Вот так выглядела оригинальная функция get_block(text ) автора:





def get_blocks(text):
return [ re.findall('</smoothie>.*</div>', text)[0] ] \
+re.findall('</span></small><!-- TTT\$ --></span></div> <div.*', text)

Iska
26-03-2019, 17:38
dark-------13, не могу. Ни на своём, ни на Вашем. Что нужно по-хорошему сделать — написал выше коллега Bumbik:
для парсинга в питоне есть requests и beautifulsoup, по нормальному все надо переписывать »
В любом случае это долгое и нудное занятие. Я таким занимался.

dark-------13
27-03-2019, 17:03
Хм, можете объяснить как из одной функции передать кортеж в другую ? Из второй функции я хочу вывести текст на печать.
Что нужно дописать в код фунций ?

первая функция:
def t():

text= 'молоко'
вторая функция:
def g(text):

return [re.findall ('солнце', text]) [0]]

shisik
27-03-2019, 17:50
как из одной функции передать кортеж в другую »

Как и любой другой объект.

dark-------13
27-03-2019, 18:33
Как и любой другой объект. »
Я писал я не программист. Покажите пожалуйста какой должен быть синтаксис.
Если вы приходите к врачу и спрашиваете как мне вылечиться , - у меня болит живот. Вам врач говорит - да так же, как и лечить воспаление легких. Вам понятно будет как вам лечиться ?

Bumbik
27-03-2019, 19:13
def text():
return 'молоко'



def g():
return [re.findall('молоко', text())][0]

print(g())

dark-------13
27-03-2019, 20:02
Спасибо большое Bumbik. Вы мне очень помогли. Дальше буду разбираться.

Bumbik
27-03-2019, 20:31
тестировать регулярные выражения удобно тут https://regex101.com/

dark-------13
28-03-2019, 10:38
Цитата Bumbik:
тестировать регулярные выражения удобно тут https://regex101.com/ »
А еще можете вставить кусок HTML страницы в notepad ++ , и выбрать поиск. Установите галочку регулярные выражения, и о чудо то, что вы хотели найти в документе выделяется, если конечно существует.

dark-------13
29-03-2019, 13:04
Всем привет, продолжаю разбираться парсингом картинок с сайта в разных скриптах, и вот в одном из них возникает ошибка.
Помогите пожалуйста , как исправить проблему не знаю .

Скрипт парсит сайт , выбирает ссылки на фотки, загружает на диск, но в какой-то рандомный момент валится с ошибкой, отладчик ссылается на ошибку в функции def name_format(url,title): в строке p2 = name.split('-')[1].split('.')[1]:



from selenium import webdriver
from selenium.webdriver.common.keys import Keys
from selenium.common.exceptions import WebDriverException
from bs4 import BeautifulSoup
from queue import Queue
from threading import Thread, Lock
import collections
import datetime
import time
import os
import pathlib
import requests
import subprocess

images = []
img_num = 0
workers = 20
threads = []
tasks = Queue()
lock = Lock()



def get_driver():





opt = webdriver.ChromeOptions()

driver = webdriver.Chrome()
return driver






return driver




def get_username(d):
global username
html = d.page_source
soup = BeautifulSoup(html, 'html.parser')
username = soup.find(class_='gruserbadge').find('a').get_text()


def get_thumb_links(q):
d = get_driver()
d.get('https://megancoffey.deviantart.com/gallery/')
unique_img = scroll_page_down(d)
time.sleep(0.5)
for img in unique_img:
q.put(img)
global expected_img_num
expected_img_num = str(len(unique_img))
get_username(d)
print(' Unique images found = ' + expected_img_num)
print(' Artist = ' + username + "\n")
time.sleep(0.5)
d.close()


def scroll_page_down(d):
SCROLL_PAUSE_TIME = 1.5
last_height = d.execute_script("return document.body.scrollHeight")
while True:
d.execute_script("window.scrollTo(0, document.body.scrollHeight);")
time.sleep(SCROLL_PAUSE_TIME)
new_height = d.execute_script("return document.body.scrollHeight")
im = d.find_element_by_class_name('folderview-art')
links = im.find_elements_by_class_name('torpedo-thumb-link')
for link in links:
l = link.get_attribute('href')
images.append(l)
unique_img = list(set(images))
time.sleep(0.5)
if new_height == last_height:
break
last_height = new_height
return unique_img


def get_full_image(l):
s = requests.Session()





h = {'User-Agent': 'Firefox'}
soup = BeautifulSoup(s.get(l, headers=h).text, 'html.parser')
title = ''
link = ''
try:
link = soup.find('a', class_='dev-page-download')['href']
except TypeError:
try:
link = soup.find('img', class_='dev-content-full')['src']
title = soup.find('a',
class_='title').text.replace(' ', '_').lower()
except TypeError:
try:
link = age_restricted(l)
except (WebDriverException, AttributeError):
link = age_restricted(l)
pass
req = s.get(link, headers=h)
time.sleep(0.1)
download_now(req,title)
url = req.url
ITuple = collections.namedtuple('ITuple', ['u', 't'])
it = ITuple(u=url, t=title)
return it


def age_restricted(l):
d = get_driver()
d.get(l)
time.sleep(0.8)
d.find_element_by_class_name('datefields')
d.find_elements_by_class_name('datefield')
d.find_element_by_id('month').send_keys('01')
d.find_element_by_id('day').send_keys('01')
d.find_element_by_id('year').send_keys('1991')
d.find_element_by_class_name('tos-label').click()
d.find_element_by_class_name('submitbutton').click()
time.sleep(1)
img_lnk = d.find_element_by_class_name('dev-page-download')
d.get(img_lnk.get_attribute('href'))
time.sleep(0.5)
link = d.current_url
d.close()
return link


def name_format(url,title):
if url.find('/'):
name = url.rsplit('/', 1)[1]
p1 = name.split('-')[0]

p2 = name.split('-')[1].split('.')[1]
name = p1 + '.' + p2
if title != '':
name = title + '.png'
return name


def download_now(req,title):
url = req.url
name = name_format(url,title)
pathlib.Path('{}.deviantart.com'.format(username)).mkdir(parents=True,
exist_ok=True)
with open(os.path.join('{}.deviantart.com/'.format(username),
'{}'.format(name)), 'wb') as file:
file.write(req.content)


def save_img(url):
try:
with open('{}-gallery.txt'.format(username), 'a+') as file:
file.write(url + '\n')
except:
print('An write error occurred.')
pass


def worker_thread(q, lock):
while True:
link = q.get()
if link is None:
break
p = get_full_image(link)
url = p.u
title = p.t
name = name_format(url, title)
with lock:
global img_num
img_num += 1
save_img(url)
print('Image ' + str(img_num) + ' - ' + name)
q.task_done()

def main():
get_thumb_links(tasks)
start = time.time()
for i in range(workers):
t = Thread(target = worker_thread, args = (tasks, lock))
t.start()
threads.append(t)
tasks.join()
for _ in range(workers):
tasks.put(None)
for t in threads:
t.join()


folder_size = subprocess.check_output(['du','-shx','{}.deviantart.com/'.format(username)]).split()[0].decode('utf-8')
print('\n Total Images: ' + str(img_num) + ' (' + str(folder_size) + ')')
print(' Excepted: ' + expected_img_num)
end = time.time()
print(' Elapsed Time: {:.4f}\n'.format(end-start))


if __name__ == '__main__':
try:
main()
except KeyboardInterrupt:
print()









def name_format(url,title):
if url.find('/'):
name = url.rsplit('/', 1)[1]
p1 = name.split('-')[0]

p2 = name.split('-')[1].split('.')[1]
name = p1 + '.' + p2
if title != '':
name = title + '.png'
return name



List index out the range и указывает на p2 = name.split('-')[1].split('.')[1]

Iska
29-03-2019, 16:36
dark-------13, сначала «ручками» проверьте, что в name содержится хотя бы один символ «-», затем проверьте, что в name.split('-')[1] содержится хотя бы один символ «.». Явно нет либо одного, либо другого. Почему нет — смотрите сами.

Bumbik
29-03-2019, 19:19
попробуй обернуть этот операцию в блок try, except дабы выловить ошибку


def name_format(url,title):
if url.find('/'):
name = url.rsplit('/', 1)[1]
p1 = name.split('-')[0]
try:
p2 = name.split('-')[1].split('.')[1]
except IndexError as err:
print(name, err)
raise Exception
name = p1 + '.' + p2
if title != '':
name = title + '.png'
return name


ошибка List index out the range указывает что там нет индекса 1 который у тебя в квадратных скобках [1]

Iska
29-03-2019, 19:34
попробуй обернуть этот операцию в блок try, except дабы выловить ошибку »
А что это ему даст? Там надо смотреть, почему там нет того или другого.




© OSzone.net 2001-2012