使用python查找链接页面到目标页面

Posted

技术标签:

【中文标题】使用python查找链接页面到目标页面【英文标题】:Finding linked pages to target pages with python 【发布时间】:2019-08-02 02:20:28 【问题描述】:

我正在创建一个程序,给定***上的起始页面和目标页面,通过每个页面上的超链接从起始页面导航到目标页面。例如,如果我们有起始页面 A 和目标页面 B,并且 A 链接到 C,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"])

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

【问题讨论】:

很抱歉避免回答确切的问题,但也许您可以通过使用现有的网络爬虫应用程序(如httrack)更轻松地完成您的任务,下载所有链接页面,然后只需解析代码遍历下载的文件? 只需对每个链接重复此过程,直到您到达目的地。这可以通过无限循环或递归来完成。 【参考方案1】:

一般来说,您要实现的目标并非易事。还有几个单独的问题需要解决。

问题 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 页面时,您“附加了一个标有“A”的解析器。这意味着可以从页面 A 访问这些页面。您访问的每个新页面还必须保留有关可以从何处访问的信息。然后使用 DFS 或 BFS 算法在该组链接页面中查找路径。

问题 3. 解决方案 B。 您维护一个列表,而不是仅保留对前一页的引用。如果您从 A 访问 B,您的 B 链接将有“A”作为它的路径。但是,如果您从 B 访问 C,您会将 B 添加到现有路径中,并且 C 将包含“A->B”等等。这意味着最终对于每个链接,您将拥有从 A 到该链接的路径。如果您对从 A 到任何其他页面的任何路径感兴趣,则效果很好。

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

【讨论】:

我一直在阅读有关 scrapy 和观看教程的内容,试图让它尽可能简单,只需在 2-3 页之间移动即可。感谢您的彻底回复,我将逐一调查这些问题。 要找到合适的解决方案,我建议您回答以下问题: - 您是否正在寻找页面 A 和页面 B 之间的任何类型(不一定最短)的路径? - 您是否正在寻找 A 和 B 之间的最短路径? - 您是否希望能够找到任意两个页面之间的最短路径?【参考方案2】:

抓取像***这样的“巨大”网站有“巨大”资源需求。我个人不相信这是一个可以由资源有限的个人完成的任务,或者这是一个可以在堆栈溢出答案的字数限制内明确回答的问题,即使知道如何做。话虽如此,我回答中的以下方法可能适用于拥有几百页的小型网站。

方法:

定义源页面和目标页面。

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

将每个抓取的页面保存到字典中,例如 master_link_dictkey:value 对作为 crawled page url links 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就是其中之一。

【讨论】:

以上是关于使用python查找链接页面到目标页面的主要内容,如果未能解决你的问题,请参考以下文章

点击按钮(或超链接)如何跳转到另外一个页面并执行目标页面的js函数

如何用python的selenium提取页面所有资源加载的链接

页面链接

浏览pdf文件以查找特定页面并使用python从图像中提取表格数据

CSS 使用CSS查找断开的链接和404页面

Python爬虫框架Scrapy实例