使用python查找指向目标页面的链接页面
我正在创建一个程序,给定维基百科上的起始页和目标页,通过每个页面上的超链接从起始页导航到目标页。例如,如果我们有起始页面A和目标页面B,以及A到C的链接,这些链接到B,我们可以通过A->C->B从A到B 我试过用漂亮的汤,但我是个新手。到目前为止,我已经从页面中提取了html并对链接进行了排序。到目前为止,我掌握的代码如下:使用python查找指向目标页面的链接页面,python,web-scraping,beautifulsoup,scrapy,Python,Web Scraping,Beautifulsoup,Scrapy,我正在创建一个程序,给定维基百科上的起始页和目标页,通过每个页面上的超链接从起始页导航到目标页。例如,如果我们有起始页面A和目标页面B,以及A到C的链接,这些链接到B,我们可以通过A->C->B从A到B 我试过用漂亮的汤,但我是个新手。到目前为止,我已经从页面中提取了html并对链接进行了排序。到目前为止,我掌握的代码如下: from urllib.request import urlopen from bs4 import BeautifulSoup import re html = url
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"])
我的问题是:如何通过页面上的链接从一个页面移动到下一个页面?一般来说,您想要实现的目标并不是一项简单的任务。还有几个独立的问题需要解决 问题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到该链接的路径。如果您对从一个页面到任何其他页面的任何路径感兴趣,则该方法非常有效 问题3。解决方案C.对于每个页面,当您从中提取所有链接时,您将构建一个地图,其中页面是键,其中包含的链接列表是值。这与方法A有点相反。不是子页面引用父页面,而是父页面列出其子页面。在这种情况下,您还可以使用DFS或WFS算法来查找任意两个页面之间的路径。放弃像Wikipedia这样的“巨大”网站需要“巨大”的资源。我个人不认为这是一项可以由资源有限的个人完成的任务,也不认为这是一个可以在堆栈溢出答案的字数限制内得到明确回答的问题,即使给出了专有技术。尽管如此,我的回答中的以下方法可能适用于具有数百页的较小网站 方法:
- 定义源页面和目标页面
- 从源页面开始爬网,递归地爬网每个链接,直到在结束页面中没有我们以前没有爬网过的链接
- 将每个爬网页面保存到字典中,例如
,其中master\u link\u dict
对作为该页面中的key:value
:爬网页面url
链接
- 不要爬过我们以前爬过的页面。我们可以检查url是否已经存在 在对页面进行爬网之前,请先单击dictionary.keys()
- 当我们找到一个包含
的页面时,我们会打印跟踪并退出。目标仅限于找到从目标url
到源url
目标url
- 答案当然是相当简单的,并没有考虑到许多边缘情况。如果A和B两页之间没有路径怎么办
- 我已经尽了最大的努力,但是可能会有更好的方法
- 我没有随机选择
。我搜索了很多3-6页以外的URL进行测试。代码中的url就是其中之一目标url
httrack
)下载所有链接的页面,然后就可以轻松完成任务
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