【问题标题】:a checker of links in pythonpython中的链接检查器
【发布时间】:2017-09-16 14:44:02
【问题描述】:

我必须在 python 中创建一个函数来搜索 HTML 页面中的链接,然后为每个链接检查链接是否损坏。

首先我创建了一个函数,它搜索每个链接(无论是否损坏),没问题并将它们存储在一个名为“g”的数组中。

其次,我想通过检查数组“g”中的每个项目/元素来创建一个仅包含断开链接的数组“a”。

我不知道为什么,逐个链接的检查链接在该功能中不起作用。但是,如果我复制一个链接并将其粘贴为 shell 上的函数中的参数,它就可以工作。

import urllib.request
import re
import urllib.error

def check(url):
    try:
        f= urllib.request.urlopen(url)
    except urllib.error.HTTPError :
            return False
    return True
def trouveurdurls(url):
    f= urllib.request.urlopen(url)
    b=(f.read().decode('utf-8'))
    d=re.findall('<a href=".*</a>',b)
    liste=[]
    f.close()
    for el in d:
        g=re.findall('"https?://.*\.*"',el)
        liste.append(g)
    a=[]
    for el in liste:
        chaine= ''.join(map(str,el))
        url=chaine.replace('\'','')
        print(url)
        #check(url)


b=trouveurdurls("http://127.0.0.1/")

【问题讨论】:

  • 它是如何工作的?打印时您的网址看起来是否正确...?请注意,re.findall 返回一个列表(并且可能比您认为它应该做的更多),然后您将 list 添加到 liste... 在每个阶段放置一些打印语句并确定最早的点事情开始寻找“错误”...
  • 另外,将 cmets 添加到您的代码中可以让人们更快地了解您的代码是如何工作的。

标签: python http url syntax-error


【解决方案1】:

如果这条线我会很惊讶

d=re.findall('<a href=".*</a>',b)

工作正常。星号正在进行贪婪匹配,这意味着它会找到最长的匹配。如果您的文档中有多个链接,则此正则表达式将吞噬第一个链接和最后一个链接末尾之间的所有内容。

您可能应该使用星号的非贪婪版本,例如*?.

另外,你只对 href 属性感兴趣,所以

d = re.findall('<a href=".*?"', b)

可能是你想要的。这将使以下代码更容易;您无需尝试查找以 http:// 开头的 url,因为您已经在 d 数组中找到了它们。您的代码也会找到不是 a 的 href 属性的一部分,而只是普通文本的一部分或图像引用的一部分等的 url。

请注意,即使是正则表达式 &lt;a href=".*?" 也不会不断产生匹配,因为 HTML 的语法非常懒惰,因此您可能还会遇到 &lt;A HREF='.....'&gt;&lt;a href = ".....&lt;a id="something" href="......"&gt; 等字符串。

您必须改进正则表达式以匹配所有此类情况,或者求助于 Evan 的答案之类的 BeautifulSoup 或为您处理它的成熟 HTML 解析器。

【讨论】:

  • 感谢您的解释,关于正则表达式,我已经完成了 d = re.findall('
  • 确保您的正则表达式不依赖于任何其他有效属性之前的 href 属性 - 'a' 元素可以具有除 'href' 之外的其他属性,它们可能会出现在 之前 i> 'href'。此外,HTML 不仅允许一个空格用于空格,而且 " 和 ' 都可用于分隔属性值。如果您正在处理无法控制其生成的 HTML,则您的正则表达式应考虑所有这些。
【解决方案2】:

这是一个使用“请求”的版本。它从页面中抓取 url,然后检查每个 url 的响应代码(200 表示它有效,等等)。

import requests
from bs4 import BeautifulSoup

page = 'http://the.web.site'

r = requests.get(page)

data = r.text

soup = BeautifulSoup(data, 'lxml')

urls = []

for a in soup.find_all('a'):
    urls.append(a.get('href'))

url_responses = {}

for url in urls:
    temp_r = requests.get(url)
    url_responses[url] = temp_r.status_code

【讨论】:

  • 我认为您想要 a 元素的 href 属性-而不是全部内容...此外,您也可以使用 requests.head 来控制带宽,因为您只想检查如果您不关心内容,服务器会提供响应。
  • 感谢@Jon Clements 发现我的错误,我更改了“href”部分。我没有将其修改为仅请求头部,但是对于带宽会成为问题的页面,您绝对是正确的。
猜你喜欢
  • 2012-06-15
  • 1970-01-01
  • 2015-07-25
  • 1970-01-01
  • 2010-12-03
  • 1970-01-01
  • 2022-11-25
  • 2014-02-26
  • 1970-01-01
相关资源
最近更新 更多