Web Scrapping - рекурсивные вызовы ссылок из href, обход данных хранилища - PullRequest
0 голосов
/ 17 апреля 2019

Итак, я создаю веб-скребок, который посещает веб-сайт, находит все div с помощью li elements. Затем обходит Ли и сохраняет их внутри text file.

Теперь на веб-сайте также есть встроенные ссылки.

Итак, мне нужно пройти по ссылкам, найти в них элементы li и вернуться на родительскую страницу. pageStructure

Мой код доступен ниже

import urllib
import urllib.request
from bs4 import BeautifulSoup


def writeToFile(ul):
    for li in ul:
        with open('path/to/file.txt', 'a+') as f:
            text = li.text
            f.write(text + ',')
            f.close()


def searchElements(url):
    print(url)
    response = urllib.request.urlopen(url)
    html = response.read()

    soup = BeautifulSoup(html, 'html.parser')

    divs = soup.findAll('div', id=lambda x: x and x.startswith('mntl-sc-block_1-0-'))
    for div in divs:
        ul = div.find("ul")
        if ul is not None:
            ulVariable = ul.findAll('a')
            for b in ulVariable:
                if ulVariable is not None:
                    if b is not None:
                        linkItemsList = list()
                        links = (b.get("href"))
                        linkItemsList.append(links)
                        for link in linkItemsList:
                            searchElements(link)
                            print('link internal data print')
                            writeToFile(ul)
                else:
                    print('link in not none else')
                    writeToFile(ul)
        print('all non link')
        writeToFile(ul)


def main():
    searchElements('https://www.thebalancecareers.com/list-of-information-technology-it-skills-2062410')


if __name__ == '__main__':
    main()

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

Итак, я был бы очень признателен за любую помощь, которую я получаю

1 Ответ

1 голос
/ 23 апреля 2019

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

Чтобы этого избежать, нужно отслеживать посещенные ссылки; Вы можете сделать это с помощью списка, как я сделал в коде ниже.

Приведенный ниже код достигает конца поиска, но для этого есть несколько предостережений, о которых нужно позаботиться:

  1. некоторые страницы ссылаются на внешние ссылки, которые не работают; поэтому я поставил предложение try, except (иначе: ошибки ...)

  2. некоторый текст (по крайней мере, один, насколько я мог проверить) содержит специальный символ - '\ u200b' - который раздражает запись в файл, поэтому я изменил open на codecs.open с кодировкой, чтобы уметь управлять им.

  3. По крайней мере одна ссылка перенаправляет на https://web.archive.org/... (см. Код ниже), поэтому я использовал регулярное выражение, чтобы вернуть его на www.thebalancecareers.com/. Если это не то, что вы собираетесь делать с этими ссылками, вам нужно адаптировать код.

  4. Наконец, я прокомментировал последний writeToFile(ul), поскольку он записывал None в файл, вызывая ошибки.

Надеюсь, это поможет.

import urllib
import urllib.request
from bs4 import BeautifulSoup
import codecs
import re

def writeToFile(ul):
    for li in ul:
        # codecs.open with encoding can manage some spacial characters in
        # you text such as '\u200b' 
        with codecs.open('file.txt', encoding='utf-8', mode='a+') as f:
            text = li.text
            f.write(text + ',')
            f.close()

def searchElements(url, visitedurls):
    visitedurls.append(url)
    print(url)
    # Uncomment the following line to see all link visited by searchElements
    # print(visitedurls)

    # Some external links referenced by www.thebalancecareers.com
    # don't exist anymore or are forbidden
    try:
        response = urllib.request.urlopen(url)
    except (urllib.error.HTTPError, urllib.error.URLError):
        return

    html = response.read()

    soup = BeautifulSoup(html, 'html.parser')

    divs = soup.findAll('div', id=lambda x: x and x.startswith('mntl-sc-block_1-0-'))
    for div in divs:
        ul = div.find("ul")
        if ul is not None:
            ulVariable = ul.findAll('a')
            for b in ulVariable:
                if ulVariable is not None:
                    if b is not None:
                        linkItemsList = list()
                        links = (b.get("href"))
                        linkItemsList.append(links)
                        for link in linkItemsList:
                            # Get rid of this kind of link:
                            # https://web.archive.org/web/20180425012458/https:/www.thebalancecareers.com/....
                            link = re.sub(r'https://web.archive.org/(.*)/https:', 'https:/', link)
                            if link in visitedurls:
                                print('%s already traversed' % link)
                                return
                            else:
                                searchElements(link, visitedurls)
                                print('link internal data print')
                                writeToFile(ul)
                else:
                    print('link in not none else')
                    writeToFile(ul)
        print('all non link')

        # Commented: this would try to write None
        # resulting in an error
        #writeToFile(ul)

def main():
    visitedurls = []
    searchElements('https://www.thebalancecareers.com/list-of-information-technology-it-skills-2062410', visitedurls)


if __name__ == '__main__':
    main()
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...