как следовать мета-обновлениям в Python - PullRequest
10 голосов
/ 23 февраля 2010

Python urllib2 следует перенаправлениям 3xx, чтобы получить окончательный контент. Есть ли способ заставить urllib2 (или какую-то другую библиотеку, такую ​​как httplib2 ) также следовать мета-обновлениям ? Или мне нужно проанализировать HTML-код вручную для метатегов обновления?

Ответы [ 5 ]

9 голосов
/ 08 сентября 2010

Вот решение с использованием BeautifulSoup и httplib2 (и аутентификации на основе сертификатов):

import BeautifulSoup
import httplib2

def meta_redirect(content):
    soup  = BeautifulSoup.BeautifulSoup(content)

    result=soup.find("meta",attrs={"http-equiv":"Refresh"})
    if result:
        wait,text=result["content"].split(";")
        if text.strip().lower().startswith("url="):
            url=text[4:]
            return url
    return None

def get_content(url, key, cert):

    h=httplib2.Http(".cache")
    h.add_certificate(key,cert,"")

    resp, content = h.request(url,"GET")

    # follow the chain of redirects
    while meta_redirect(content):
        resp, content = h.request(meta_redirect(content),"GET") 

    return content  
3 голосов
/ 04 июня 2013

Аналогичное решение с использованием запросов и библиотек lxml.Также выполняет простую проверку, что проверяемая вещь на самом деле является HTML (требование в моей реализации).Также может захватывать и использовать куки-файлы с помощью сеансов библиотеки запросов (иногда это необходимо, если перенаправление + куки-файлы используются в качестве механизма защиты от скребков).

1 голос
/ 13 февраля 2017

Если вы не хотите использовать bs4, вы можете использовать lxml следующим образом:

from lxml.html import soupparser

def meta_redirect(content):
    root = soupparser.fromstring(content)
    result_url = root.xpath('//meta[@http-equiv="refresh"]/@content')
    if result_url:
        result_url = str(result_url[0])
        urls = result_url.split('URL=') if len(result_url.split('url=')) < 2    else result_url.split('url=')
        url = urls[1] if len(urls) >= 2 else None
    else:
        return None
    return url
1 голос
/ 27 февраля 2010

ОК, кажется, ни одна библиотека не поддерживает его, поэтому я использовал этот код:

import urllib2
import urlparse
import re

def get_hops(url):
    redirect_re = re.compile('<meta[^>]*?url=(.*?)["\']', re.IGNORECASE)
    hops = []
    while url:
        if url in hops:
            url = None
        else:
            hops.insert(0, url)
            response = urllib2.urlopen(url)
            if response.geturl() != url:
                hops.insert(0, response.geturl())
            # check for redirect meta tag
            match = redirect_re.search(response.read())
            if match:
                url = urlparse.urljoin(url, match.groups()[0].strip())
            else:
                url = None
    return hops
0 голосов
/ 23 февраля 2010

Используйте BeautifulSoup или lxml для разбора HTML.

...