使用python查找指向目标页的链接页

2024-06-28 19:29:16 发布

您现在位置:Python中文网/ 问答频道 /正文

我正在创建一个程序,给定Wikipedia上的起始页和目标页,通过每个页面上的超链接从起始页导航到目标页。例如,如果我们有起始页A和目标页B,以及A到C的链接,这些链接到B,我们可以通过A->;C->;B从A到B

我试过用漂亮的汤,但我是新的网页刮。到目前为止,我已经从页面中提取了html并对链接进行了排序。到目前为止,我掌握的代码是:

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

html = urlopen("https://en.wikipedia.org/wiki/Web_Bot")
bs = BeautifulSoup(html, "lxml")
links = bs.find("div", {"id": "bodyContent"}).findAll("a", 
href=re.compile("^(/wiki/)((?!:).)*$"))

for link in links:
    if "href" in link.attrs:
        print(link.attrs["href"])

我的问题是:如何通过页面上的链接从一个页面移动到下一个页面?你知道吗


Tags: fromimportgtre目标bs链接html
2条回答

取消维基百科这样一个“巨大”的网站,对资源的需求是巨大的。我个人不认为这是一个可以由一个资源有限的人来完成的任务,也不认为这是一个可以在堆栈溢出答案的字数限制内得到明确回答的问题,即使是已知技术。也就是说,我的答案中的以下方法可能适用于几百页的小型网站。你知道吗

接近:

  • 定义源页面和目标页面。

  • 从源页面开始爬网,递归地爬网每个链接,直到在结束页面中没有我们以前没有爬网过的链接。

  • 将每个已爬网的页面保存到字典中,例如master_link_dictkey:value对作为crawled page urllinks in that page

  • 不要爬过我们以前爬过的页面。我们可以检查url是否已经在 抓取页面之前的dictionary.keys()

  • 当我们找到一个有target url存在的页面时,我们打印路径并退出。目标仅限于找到从source urltarget url

代码:

import requests
from bs4 import BeautifulSoup
import re
import pprint
source_page='/wiki/Web_Bot'
target_page='/wiki/Computer_Sciences_Corporation'
master_link_dict={}
#initialize trail with target
trail_reverse=[target_page]
def get_links(url):
    html=requests.get('https://en.wikipedia.org'+url)
    soup = BeautifulSoup(html.text, "html.parser")
    links = soup.find("div", {"id": "bodyContent"}).findAll("a", href=re.compile("^(/wiki/)((?!:).)*$"))
    hrefs=[x['href'] for x in links]
    return hrefs

def recursive_crawl(url):
    #don't crawl again if the page has already been crawled
    if url in master_link_dict.keys():
        return
    #get all urls in the current page
    url_list=get_links(url)
    #store as page:[list of urls] in the master dict
    master_link_dict[url]=url_list

    #if target page is found print trail
    if target_page in url_list:
        find_trail(url)

    #crawl all urls of curret page
    for item in url_list:
        recursive_crawl(item)

def find_trail(url):
    #append current url to trail reverse
    trail_reverse.append(url)
    #if current url is the source url print trail and exit
    if url is source_page:
        print('->'.join(trail_reverse[::-1]))
        exit()
    #if current url is in a page, get trail of that page
    for page,url_list in master_link_dict.items():
        if url in url_list:
            find_trail(page)

recursive_crawl(source_page)

输出:

/wiki/Web_Bot->/wiki/Internet_bot->/wiki/Automated_bot->/wiki/Computer_science->/wiki/Computer_Sciences_Corporation

注意事项和免责声明:

  • 答案当然是相当简单的,并没有考虑到许多边缘的情况。如果A页和B页之间没有路径怎么办?

  • 我已经尽了我最大的努力,但可能有更好的办法。

  • 我没有随机选择target url。我搜索了许多网址是3-6页以外的测试。代码中的url就是其中之一。

总的来说,你想要达到的目标并不是一件小事。还有几个单独的问题需要解决。你知道吗

问题1:跟踪您已经访问过的所有链接和您尚未访问的链接

问题2:知道何时停止。如果你正在爬行的网站很小,那么你可以希望在一段时间后,你可以简单地找到所有可能的链接,你的爬行将结束。你知道吗

问题3:根据链接到哪个页面的知识查找路径。 现在讨论可能的解决方案:

问题1。解决方案A: 使用队列和集合。在每个步骤中,将当前页面链接放入一组已访问的链接中,从页面中获取链接,检查其中是否有任何链接已在一组已访问的链接中,向队列中添加新链接。然后从队列中选取要访问的下一个链接。非常简单的方法,尤其是如果你的爬虫需要时间的话。这将按顺序完成所有操作。一页接一页。你知道吗

问题1。解决方案B: 花1-2小时阅读关于Scrapy的文章,并尝试使用Scrapy实现爬行。它将为您提供多线程处理以及查找链接的工具(以类似于您在BeautifulSoup中的方式)。优点:已经实现了很多特性,例如导出到CSV、JSON以进行进一步处理、日志记录、刮取统计等等。你知道吗

问题2。解决方案A。视情况而定。如果您正在寻找任何特定的路径,则可以在到达目标页时立即停止,然后可以重建从A到B的路径

问题2。解决方案B.如果您正在寻找最短路径或找到任何给定A和B的A和B之间的路径的能力,则可以通过跳数限制您的爬网。假设你从a页开始,它有到B1,B2和B3的链接。你拜访他们并给他们序号1。这些B页面有到C1,C2,C3,C4,C5的链接-你访问这些页面并给它们序号2。你继续,直到你达到序号X,这意味着这些网页是X跳离你的起始页。这将确保您限制爬行时间。你知道吗

问题3。解决方案A.当您从A页转到B1、B2、B3页时,您会“附加一个parsel”,上面写着“A”。这意味着这些页面可以从A页访问。您访问的每一个新页面还必须保留有关可以从何处访问的信息。然后使用DFS或BFS算法在链接页集中查找路径。你知道吗

问题3。解决方案B.您可以维护一个列表,而不是只保留对上一页的引用。如果您从A访问B,您的B链接将有“A”作为它的路径。但是如果您从B访问C,您将把B添加到现有路径,C将包含“A->;B”等等。这意味着,在每个链接的最后,您将有一个从a到该链接的路径。如果您对从一个页面到另一个页面的任何路径感兴趣,那么它的效果会很好。你知道吗

问题3。解决方案C.对于每个页面,当您从中提取所有链接时,您将构建一个地图,其中您的页面是键,它包含的链接列表是值。这与方法A有些相反。父页面列出子页面,而不是子页面引用父页面。在这种情况下,您还可以使用DFS或WFS算法来查找任意两个页面之间的路径。你知道吗

相关问题 更多 >