我一直致力于一个在线课程,它引导我们创建一个为Web链接抓取字符串的函数。您可以看到以下功能:
page = 'This is a <a href="http://udacity.com">Link!</a>.This is a <a href="http://egg.com">Link!</a>.This is a <a href="http://bread.com">Link!</a>'
def get_next_target(page):
start_link = page.find("<a href=")
if start_link == -1:
return None, 0
start_quote = page.find('"', start_link)
end_quote = page.find('"', start_quote +1)
url = page[start_quote + 1: end_quote]
return url, end_quote
def print_all_links(page):
while True:
url, endpos = get_next_target(page)
if url:
print url
page = page[endpos:]
else:
break
print_all_links(page)
但是,我仍然不明白它是如何协同工作的?对我来说,它看起来像两个独立的功能。我理解第一个函数 - (print_all_links(page)
- 是如何工作的,但我坚持的是第二部分如何从第一个函数获取信息?
具体而言,while
下的if
和while
声明在做什么?我不明白他们要检查什么,或者他们如何从第一个功能中获取信息。
非常感谢任何帮助。
亲切的问候。 :)
答案 0 :(得分:2)
get_next_target(page)
这会在页面中找到字符串"<a href="
。然后,它会在下一个"
之后的链接中提取链接,然后返回另一个"
并返回该链接,并且链接"
的位置结束于此处。
print_all_links(page)
这会尽可能长地通过get_next_target
从页面中获取链接(while True: ...
)。它获取下一个链接和结束位置。如果链接文本为None
(即找不到链接),则会停止(即else
子句)。否则(if url:
),它会打印链接地址,并在刚刚提取的链接之后用所有内容替换页面文本,以便删除下一个链接。
答案 1 :(得分:1)
您的整个算法归结为代码的这一部分:
page.find("<a href=")
即。 str.find
函数:
string.find(s, sub[, start[, end]])
返回s中找到子字符串sub的最低索引,使得sub完全包含在s [start:end]中。失败时返回-1。开始和结束的默认值以及负值的解释与切片相同。
基本上,您的算法的作用是:
"<a href="
CF:
start_link = page.find("<a href=")
CF:
start_quote = page.find('"', start_link)
end_quote = page.find('"', start_quote +1)
url = page[start_quote + 1: end_quote]
""<a href="
get_next_target
的当前位置
get_next_target
函数未返回有效值,则会中断循环N.B。:捕获字符串中所有链接的另一种更简单的方法是使用正则表达式:
>>> page = 'This is a <a href="http://udacity.com">Link!</a>.This is a <a href="http://egg.com">Link!</a>.This is a <a href="http://bread.com">Link!</a>'
>>> import re
>>> r = re.compile(r'<a href="([^"]+)">')
>>> r.findall(page)
['http://udacity.com', 'http://egg.com', 'http://bread.com']
要了解正则表达式的含义,请查看以下内容:
基本上,您可以看到它查找(感谢findall
)并捕获以<a href="
开头并以">
- <a href="…">
结尾的所有内容,并捕获所有内容之间(字面意思是,任何不是"
的字符) - ([^"]+)
。
显示这是多少改进,这是我为了好玩而做的一个小基准,超过1000000,并从print
删除print_all_links
函数:
>>> timeit.timeit(stmt=lambda: print_all_links(page), number=1000000)
6.7976109981536865
>>> import re
>>> r = re.compile(r'<a href="([^"]+)">')
>>> timeit.timeit(stmt=lambda: r.findall(page), number=1000000)
1.823470115661621
>>> 6.7976109981536865/1.823470115661621
3.7278433793729966
使用正则表达式快几乎快4倍: - )
HTH; - )