make_links_absolute() 导致损坏的绝对 URL

make_links_absolute() results in broken absolute URLs

我需要将相对 URL 从 HTML 页面转换为绝对页面。我正在使用 pyquery 进行解析。

例如,此页面 http://govp.info/o-gorode/gorozhane 在源代码中有相关的 URL,如

<a href="o-gorode/gorozhane?page=2">2</a>

(这是页面底部的分页link)。我正在尝试使用 make_links_absolute():

import requests
from pyquery import PyQuery as pq

page_url = 'http://govp.info/o-gorode/gorozhane'
resp = requests.get(page_url)
page = pq(resp.text)

page.make_links_absolute(page_url)

但这似乎打破了相对 links:

print(page.find('a[href*="?page=2"]').attr['href'])

# prints            http://govp.info/o-gorode/o-gorode/gorozhane?page=2
# expected value    http://govp.info/o-gorode/gorozhane?page=2

如你所见,最后的URL中间有两个o-gorode,肯定会产生404错误。

pyquery 在内部使用标准 urllib.parse 模块中的 urljoin,有点像这样:

from urllib.parse import urljoin
urljoin('http://example.com/one/', 'two')

# -> 'http://example.com/one/two'

没关系,但是有很多网站,嗯,不寻常 相对 link 具有完整路径。

在这种情况下 urljoin 会给我们一个无效的绝对值 link:

urljoin('http://govp.info/o-gorode/gorozhane', 'o-gorode/gorozhane?page=2')

# -> 'http://govp.info/o-gorode/o-gorode/gorozhane?page=2'

我相信这样的亲戚link不是很靠谱,但是GoogleChrome处理起来没问题;所以我想这在网络上很正常。

有什么解决这个问题的建议吗?我试过 furl 但它做同样的加入。

在这种特殊情况下,相关页面包含

<base href="http://govp.info/"/>

指示浏览器使用它来解析任何相关链接。 <base> 元素是可选的,但如果它存在,您必须使用它来代替页面的实际 URL.

为了跟浏览器一样,提取基本href并在make_links_absolute()中使用它。

import requests
from pyquery import PyQuery as pq

page_url = 'http://govp.info/o-gorode/gorozhane'
resp = requests.get(page_url)
page = pq(resp.text)

base = page.find('base').attr['href']
if base is None:
    base = page_url    # the page's own URL is the fallback

page.make_links_absolute(base)

for a in page.find('a'):
     if 'href' in a.attrib and 'govp.info' in a.attrib['href']:
         print(a.attrib['href'])

打印

http://govp.info/assets/images/map.png
http://govp.info/podpiska.html
http://govp.info/
http://govp.info/#order
...
http://govp.info/o-gorode/gorozhane
http://govp.info/o-gorode/gorozhane?page=2
http://govp.info/o-gorode/gorozhane?page=3
http://govp.info/o-gorode/gorozhane?page=4
http://govp.info/o-gorode/gorozhane?page=5
http://govp.info/o-gorode/gorozhane?page=6
http://govp.info/o-gorode/gorozhane?page=2
http://govp.info/o-gorode/gorozhane?page=17
http://govp.info/bannerclick/264
...
http://doska.govp.info/cat-biznes-uslugi/
http://doska.govp.info/cat-transport/legkovye-avtomobili/
http://doska.govp.info/
http://govp.info/

这似乎是正确的。