Возникли проблемы с использованием декоратора в скребке Python - PullRequest
0 голосов
/ 30 ноября 2018

Я написал скрипт на python для получения ссылок на некоторые сообщения, отслеживая базовую ссылку с ее целевой страницы.Я сам могу сделать то же самое, если придерживаюсь традиционного подхода.

Однако моя цель здесь состоит в том, чтобы сделать то же самое, используя decorator.Кажется, я близок, но застреваю, когда передаю ссылки из функции get_links() в get_target_link().Я использовал return func() в качестве заполнителя в функции get_target_link(), так как не могу понять, как передавать ссылки.В функции get_links() есть оператор print (работает без комментариев), чтобы убедиться, что я на правильном пути.

Как мне передать ссылки return linklist из get_links()на get_target_link(), чтобы я мог повторно использовать их при необходимости?

Это то, что я пробовал до сих пор:

import requests
from urllib.parse import urljoin
from bs4 import BeautifulSoup

url = "https://www.janglo.net/component/option,com_sobi2/"

def get_links(func):
    linklist = []
    res = requests.get(func())
    soup = BeautifulSoup(res.text,"lxml")
    for item in soup.select(".sobi2ItemTitle a"):
        linklist.append(urljoin(url,item.get("href")))
    #print(linklist)
    return linklist

    def get_target_link():
        return func()  #All I need to do is fix this line
    return get_target_link

@get_links
def get_info():
    res = requests.get(url)
    soup = BeautifulSoup(res.text,"lxml")
    for items in soup.select("#sobi2CatListSymbols .sobi2SubcatsListItems a[title]"):
        if items.text=="Tutors":
            ilink = f"{urljoin(url,items.get('href'))}"
    return ilink

if __name__ == '__main__':
    for links in get_info():
        print(links)

Post Script: I only would like to comply with the logic I've tried to apply above.

Обновление для @sir Andersson (Can you explain how you want to re-use them if necessary):

def get_target_link():
    titles = []
    new_links =  func()
    for new_link in new_links:
        res = requests.get(new_link)
        soup = BeautifulSoup(res.text)
        titles.append(soup.select_one("h1").text)
    return titles
return get_target_link

Я хотел создать украшенную функцию, которая будет действовать следующим образом@Carlos Mermingas:

import requests
from urllib.parse import urljoin
from bs4 import BeautifulSoup

url = "https://www.janglo.net/component/option,com_sobi2/"

def get_info(link):
    res = requests.get(url)
    soup = BeautifulSoup(res.text,"lxml")
    for items in soup.select("#sobi2CatListSymbols .sobi2SubcatsListItems a[title]"):
        if items.text=="Tutors":
            ilink = f"{urljoin(url,items.get('href'))}"
    return ilink

def get_links(tlink):
    linklist = []
    res = requests.get(tlink)
    soup = BeautifulSoup(res.text,"lxml")
    for item in soup.select(".sobi2ItemTitle a"):
        linklist.append(urljoin(url,item.get("href")))
    return linklist

def get_target_link(link):
    titles = []
    res = requests.get(link)
    soup = BeautifulSoup(res.text,"lxml")
    titles.append(soup.select_one("h1").text)
    return titles

if __name__ == '__main__':
    item = get_info(url)
    for nlink in get_links(item):
        for ititle in get_target_link(nlink):
            print(ititle)

Ответы [ 2 ]

0 голосов
/ 01 декабря 2018

Кажется, я очень близок к тому, чего я хотел достичь.Сайт в моем сообщении выше выдает ошибку соединения, поэтому я использовал stackoverflow.com.Мой скрипт собирает все ссылки на различные посты со своей целевой страницы, а затем получает заголовок каждого поста со своей внутренней страницы.

Следующий код полностью функционален :

import requests
from urllib.parse import urljoin
from bs4 import BeautifulSoup

url = "https://stackoverflow.com/questions/tagged/web-scraping"

def get_links(func):

    def get_target_link(*args):
        titles = []
        for link in func(*args):
            res = requests.get(link)
            soup = BeautifulSoup(res.text,"lxml")
            title = soup.select_one("h1[itemprop='name'] a").text
            titles.append(title)
        return titles
    return get_target_link

@get_links
def get_info(*args):
    ilink = []
    res = requests.get(*args)
    soup = BeautifulSoup(res.text,"lxml")
    for items in soup.select(".summary .question-hyperlink"):
        ilink.append(urljoin(url,items.get('href')))
    return ilink

if __name__ == '__main__':
    for item in get_info(url):
        print(item)

Один вопрос, который я не смог найти ни одного решения.Разве нет ничего полезного, что я могу сделать в указанном блоке между функциями ниже?

def get_links(func):
    ###why this area is for? Can I not do anything here as well?
    #### And print that within "get_target_link()" function?
    def get_target_link():
0 голосов
/ 30 ноября 2018

Вроде из длинного поста, честно говоря, я перестал читать при вашей первой ошибке на python.

Позвольте мне исправить это для вас, и вы скажете мне, если это было тем, чего не хватало.Вот как шаблон декоратора работает в python.

Поначалу это немного странно, немного похоже на судоходство, отгружающее корабли, но довольно умное.

Декоратор - это функциякоторая возвращает функцию, которая будет вызвана вместо другой.

Давайте представим, что эта функция не оформлена.

>>> def some_func(number):
...      return f'Number is {number}'
...
>>> print(some_func(10))
Number is 10

Чтобы украсить эту функцию, допустим, мы добавили размытие;обычное дело - добавлять туда и сюда некоторую задержку.

>>> def fuzz():
...     def fuzz_decorator(func):
...         def fuzz_wrapper(*args, **kwargs):
...             print('fuzz') # this is our added functionality
...             return func(*args, **kwargs) # call whatever we're decorating
...         return fuzz_wrapper
...     return fuzz_decorator
...
>>> @fuzz()
... def some_func(number):
...     return f'Number is {number}'
...
>>> print(some_func(10))
fuzz
Number is 10

fuzz() - это функция, которая возвращает функцию, которая принимает функцию fuzz_decorator(func), и возвращает новую функцию, которая добавляет некоторую функциональность к func, в то время как сам звонит func.

Надеюсь, это не смущает.Но вы ошиблись.

...