使用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_dict
与 key:value
对作为 crawled page url
: links in that page
不要抓取我们之前抓取过的页面。我们可以检查一个 url 是否已经存在
抓取页面之前的dictionary.keys()
。
当我们找到一个包含target url
的页面时,我们会打印线索并退出。目标仅限于找到从source url
到target 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提取页面所有资源加载的链接