Извлечение ссылок в классе с веб-страницы

Я пытаюсь извлечь ссылки из блога, используя этот код Python:

    #!/usr/bin/env python

"""
Extract all links from a web page
=================================
Author: Laszlo Szathmary, 2011 ([email protected])
Website: https://pythonadventures.wordpress.com/2011/03/10/extract-all-links-from-a-web-page/
GitHub: https://github.com/jabbalaci/Bash-Utils

Given a webpage, extract all links.

Usage:
------
./get_links.py <URL>
"""

import sys
import urllib
import urlparse

from BeautifulSoup import BeautifulSoup


class MyOpener(urllib.FancyURLopener):
    version = 'Mozilla/5.0 (Windows; U; Windows NT 6.1; en-US; rv:1.9.2.15) Gecko/20110303 Firefox/3.6.15'


def process(url):
    myopener = MyOpener()
    #page = urllib.urlopen(url)
    page = myopener.open(url)

    text = page.read()
    page.close()

    soup = BeautifulSoup(text)

    for tag in soup.findAll('a', href=True):
        tag['href'] = urlparse.urljoin(url, tag['href'])
        print tag['href']
# process(url)


def main():
    if len(sys.argv) == 1:
        print "Jabba's Link Extractor v0.1"
        print "Usage: %s URL [URL]..." % sys.argv[0]
        sys.exit(1)
    # else, if at least one parameter was passed
    for url in sys.argv[1:]:
        process(url)
# main()

#############################################################################

if __name__ == "__main__":
    main()

Ссылки взяты из блога, основной категорией которого является blog.xx/Music/. Он извлечет ссылки из категории blog.xx/this_album_name/, но я хочу получить ссылки из класса с именем quote на подстраницах под категорией

Как я могу разобрать ссылки из категории «Музыка» и заставить BS пройти через каждую ссылку заголовка, чтобы извлечь ссылки на следующей странице, используя класс цитаты?

т. е. blog.xx/Категория

блог.xx/post1.html

блог.xx/post2.html

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

Я новичок в python и BS и пробовал несколько вариантов, но на данный момент мне нужна помощь. Спасибо


person darth    schedule 30.04.2013    source источник


Ответы (1)


Если я вас правильно понял, вы хотите перейти по ссылкам на странице на следующую страницу, а также очистить ссылки с этой страницы? Следующее должно сделать это для вас:

#!/usr/bin/env python

"""
Extract all links from a web page
=================================
Author: Laszlo Szathmary, 2011 ([email protected])
Website: https://pythonadventures.wordpress.com/2011/03/10/extract-all-links-from-a-web-page/
GitHub: https://github.com/jabbalaci/Bash-Utils

Given a webpage, extract all links.

Usage:
------
./get_links.py <URL>
"""

import sys
import urllib
import urlparse
import re

from BeautifulSoup import BeautifulSoup


class MyOpener(urllib.FancyURLopener):
    version = 'Mozilla/5.0 (Windows; U; Windows NT 6.1; en-US; rv:1.9.2.15) Gecko/20110303 Firefox/3.6.15'


def process(url):
    myopener = MyOpener()
    #page = urllib.urlopen(url)
    page = myopener.open(url)

    text = page.read()
    page.close()

    soup = BeautifulSoup(text)

    urls = []

    for tag in soup.findAll('a', href=True):
        tag['href'] = urlparse.urljoin(url, tag['href'])
        urls.append(tag['href'])

    return urls

# process(url)


def main():


    # Store the urls we were given
    urls_queue = sys.argv[1:] 
    urls_found = []
    urls_done = []

    site_roots = []

    # Get the domains to keep us on the same domain (don't follow external links)
    for url in urls_queue:
        mre = re.match('^https?://[^/]*',url,re.IGNORECASE)
        if mre:
            # If we've found a match, add the entire matched string to site_roots
            site_roots.append( mre.group(0) )

    while len(urls_queue) > 0:

        # Get url off the top of the queue
        url = urls_queue.pop()
        urls_done.append(url)

        found = process(url)

        for uf in found:
            # I'd suggest checking to make sure it's on the same domain here
            # any() returns true if any of the elements in the list passed are True
            # In this case, if uf starts with any of the site_root strings.
            # 'not any()' is equivalent to saying 'none'
            if not any( [ uf.startswith( site_root ) for site_root in site_roots ] ):
                continue # Next url, this is off site

            if uf not in urls_found:
                urls_found.append(uf) 

            # If we don't have it in the queue, queue it up
            if uf not in urls_queue and uf not in urls_done:
                urls_queue.append(uf)

        print "Done %d; Queued %d; Found %d" % ( len(urls_done), len(urls_queue), len(urls_found) )

    print urls_found
# main()

#############################################################################

if __name__ == "__main__":
    main()

Я добавил очередь URL-адресов и проверку, чтобы убедиться, что вы не уходите «вне сайта» по ссылкам, указывающим в другом месте. Он выводит все, что он нашел в конце.

Обратите внимание, что этот код будет переходить по ссылкам на вторичных страницах, поэтому, вероятно, проиндексирует весь сайт. Вы можете обойти это, закомментировав бит urls_queue.append в основном цикле while (чтобы больше не добавлять). Затем непосредственно перед циклом while добавьте:

urls_queue = [url for inurl in sys.argv[1:] for url in process(inurl) if any([url.startswith(sr) for sr in site_roots])]
urls_queue = list( set(urls_queue) ) # Get rid of duplicates

Это создает начальную очередь, добавляя ссылки на предоставленные страницы. Таким образом, для вашего примера будут добавлены ссылки на странице категории, но не будут добавлены ссылки на последующие страницы.

person mfitzp    schedule 30.04.2013