Como recuperar os links de uma página da Web e copiar o endereço de URL dos links usando Python?
141
Como recuperar os links de uma página da Web e copiar o endereço de URL dos links usando Python?
Aqui está um pequeno trecho usando a classe SoupStrainer em BeautifulSoup:
import httplib2
from bs4 import BeautifulSoup, SoupStrainer
http = httplib2.Http()
status, response = http.request('http://www.nytimes.com')
for link in BeautifulSoup(response, parse_only=SoupStrainer('a')):
if link.has_attr('href'):
print(link['href'])
A documentação do BeautifulSoup é realmente muito boa e abrange vários cenários típicos:
https://www.crummy.com/software/BeautifulSoup/bs4/doc/
Edit: Note que eu usei a classe SoupStrainer porque é um pouco mais eficiente (memória e velocidade), se você souber o que está analisando com antecedência.
/usr/local/lib/python2.7/site-packages/bs4/__init__.py:128: UserWarning: The "parseOnlyThese" argument to the BeautifulSoup constructor has been renamed to "parse_only."
has_attr
. Em vez disso, vejo que há algo chamadohas_key
e funciona.Para completar, a versão BeautifulSoup 4, usando também a codificação fornecida pelo servidor:
ou a versão do Python 2:
e uma versão usando a
requests
biblioteca , que, conforme escrita, funcionará no Python 2 e 3:A
soup.find_all('a', href=True)
chamada localiza todos os<a>
elementos que possuem umhref
atributo; elementos sem o atributo são ignorados.O BeautifulSoup 3 parou o desenvolvimento em março de 2012; novos projetos realmente devem usar o BeautifulSoup 4, sempre.
Observe que você deve deixar a decodificação do HTML dos bytes para BeautifulSoup . Você pode informar o BeautifulSoup do conjunto de caracteres encontrado nos cabeçalhos de resposta HTTP para ajudar na decodificação, mas isso pode estar errado e entrar em conflito com as
<meta>
informações do cabeçalho encontradas no próprio HTML, e é por isso que o acima usa o método da classe interna BeautifulSoupEncodingDetector.find_declared_encoding()
para garantir que essas dicas de codificação incorporadas conquistam um servidor mal configurado.Com
requests
, oresponse.encoding
atributo padrão é Latin-1 se a resposta tiver umtext/*
tipo de mimet, mesmo que nenhum conjunto de caracteres tenha sido retornado. Isso é consistente com os RFCs HTTP, mas é doloroso quando usado com análise de HTML, portanto, você deve ignorar esse atributo quando nenhumcharset
estiver definido no cabeçalho Tipo de Conteúdo.fonte
SoupStrainer
você quer dizer? Não foi a lugar nenhum, ainda faz parte do projeto .Outros recomendaram o BeautifulSoup, mas é muito melhor usar o lxml . Apesar do nome, é também para analisar e copiar HTML. É muito, muito mais rápido que o BeautifulSoup, e até lida com HTML "quebrado" melhor que o BeautifulSoup (sua reivindicação à fama). Também possui uma API de compatibilidade para BeautifulSoup, se você não quiser aprender a API lxml.
Ian Blicking concorda .
Não há mais motivo para usar o BeautifulSoup, a menos que você esteja no Google App Engine ou algo em que algo que não seja puramente Python não seja permitido.
O lxml.html também suporta seletores CSS3, portanto esse tipo de coisa é trivial.
Um exemplo com lxml e xpath ficaria assim:
fonte
lxml
como o analisador padrão, se instalado.fonte
O código a seguir é recuperar todos os links disponíveis em uma página da Web usando
urllib2
eBeautifulSoup4
:fonte
Sob o capô, o BeautifulSoup agora usa lxml. Pedidos, lxml e compreensão de lista fazem uma combinação incrível.
Na lista comp, o "se '//' e 'url.com' não estiver em x" é um método simples para limpar a lista de URLs dos URLs de navegação 'internos' dos sites, etc.
fonte
apenas para obter os links, sem B.soup e regex:
para operações mais complexas, é claro que o BSoup ainda é o preferido.
fonte
<a
ehref
? Digarel="nofollow"
ouonclick="..."
mesmo apenas uma nova linha? stackoverflow.com/questions/1732348/…Esse script faz o que você procura, mas também resolve os links relativos aos links absolutos.
fonte
Para encontrar todos os links, neste exemplo, usaremos o módulo urllib2 junto com o re.module * Uma das funções mais poderosas no módulo re é "re.findall ()". Enquanto re.search () é usado para encontrar a primeira correspondência para um padrão, re.findall () localiza todas as correspondências e as retorna como uma lista de cadeias, com cada cadeia representando uma correspondência *
fonte
Por que não usar expressões regulares:
fonte
(r"<a.*?\s*href=\"(.*?)\".*?>(.*?)</a>", page)
significa? obrigado!Os links podem estar em uma variedade de atributos para que você possa passar uma lista desses atributos para selecionar
por exemplo, com o atributo src e href (aqui estou usando o operador begin com ^ para especificar que um desses valores de atributos começa com http. Você pode adaptá-lo conforme necessário
Atributo = seletores de valor
fonte
Aqui está um exemplo usando @ars resposta aceita e os
BeautifulSoup4
,requests
ewget
módulos para lidar com os downloads.fonte
Encontrei a resposta do @ Blairg23 funcionando, após a seguinte correção (cobrindo o cenário em que não funcionou corretamente):
Para Python 3:
urllib.parse.urljoin
deve ser usado para obter o URL completo.fonte
O analisador do BeatifulSoup pode ser lento. Pode ser mais viável usar o lxml, que é capaz de analisar diretamente de uma URL (com algumas limitações mencionadas abaixo).
O código acima retornará os links como estão e, na maioria dos casos, seriam links relativos ou absolutos da raiz do site. Como meu caso de uso era apenas para extrair um certo tipo de links, abaixo está uma versão que converte os links em URLs completos e que opcionalmente aceita um padrão global como
*.mp3
. Porém, ele não suporta pontos únicos e duplos nos caminhos relativos, mas até agora eu não precisava disso. Se você precisar analisar fragmentos de URL que contenham../
ou./
então urlparse.urljoin, pode ser útil.OBSERVAÇÃO : A análise direta de URL lxml não processa o carregamento
https
e não redireciona, portanto, por esse motivo, a versão abaixo está usandourllib2
+lxml
.O uso é o seguinte:
fonte
lxml
só pode lidar com entrada válida, como ele pode substituirBeautifulSoup
?lxml.html
é um pouco mais branda do que olxml.etree
. Se sua entrada não for bem formada, você poderá definir explicitamente o analisador BeautifulSoup: lxml.de/elementsoup.html . E se você optar pelo BeatifulSoup, o BS3 é uma escolha melhor.fonte
Pode haver muitos links duplicados junto com links externos e internos. Para diferenciar os dois e obter links exclusivos usando conjuntos:
fonte