Neste tutorial, você verá PyQuery
, uma biblioteca Python que permite fazer consultas jQuery em documentos XML. Sintaticamente, é bastante semelhante ao jQuery e, se você estiver familiarizado com o jQuery, será mais fácil segui-lo.
Introdução ao PyQuery
Para começar com PyQuery
instale o pacote Python usando PIP.
Depois de ter instalado PyQuery
importe-o para o programa Python.
1 |
from pyquery import PyQuery as pq |
Depois de importar a classe PyQuery, você pode usá-la para carregar dados de uma string, um arquivo ou até mesmo uma URL.
Vamos começar com um exemplo básico para ver como funciona. Considere o seguinte HTML que está dentro de um arquivo chamado document.html.
1 |
|
2 |
class="no-js" lang="">
|
3 |
|
4 |
charset="utf-8">
|
5 |
|
6 |
name="viewport" content="width=device-width, initial-scale=1">
|
7 |
|
8 |
|
9 |
|
10 |
Hello world! This is a basic webpage. |
11 |
Here is a list of some random words: |
12 |
|
13 |
Impedimenta
|
14 |
Decompensation
|
15 |
Tergiversation
|
16 |
Transcendentalism
|
17 |
Polyphiloprogenitive
|
18 |
|
19 |
|
20 |
|
Podemos passar o arquivo HTML como um argumento para o PyQuery
objeto e, em seguida, poderemos aplicar consultas de estilo jQuery a ele.
1 |
webpage = pq(filename = 'document.html') |
O valor retornado pela chamada para PyQuery
objeto é semelhante ao que você obtém com jQuery()
ou $()
ao usar a biblioteca jQuery. Assim como o html()
método em jQuery, há um html()
método em PyQuery onde você poderá obter ou definir o conteúdo HTML do elemento selecionado.
Atualmente, o objeto da página da Web é representativo de todo o documento, portanto, retorna a marcação da página inteira:
1 |
print(webpage.html()) |
2 |
|
3 |
'''
|
4 |
|
5 |
|
6 |
|
7 |
|
8 |
|
9 |
|
10 |
|
11 |
|
12 |
|
13 |
|
14 |
|
15 |
|
16 |
|
17 |
|
18 |
|
19 |
|
20 |
|
21 |
'''
|
Digamos que você queira obter a marcação do primeiro p
tag em vez de todo o documento. O que você faz? Você simplesmente passa um seletor apropriado para o nosso webpage
objeto. Aqui está um exemplo:
1 |
print(webpage("p").html()) |
2 |
|
3 |
'''
|
4 |
Hello world! This is a basic webpage.
|
5 |
'''
|
Agora dê uma olhada no código a seguir, onde primeiro definiremos o HTML para nosso seletor usando o html()
método e, em seguida, acessá-lo usando o mesmo html()
método.
1 |
from pyquery import PyQuery as pq |
2 |
|
3 |
webpage = pq(filename = 'document.html') |
4 |
|
5 |
print(webpage("p").html()) |
6 |
'''
|
7 |
Hello world! This is a basic webpage.
|
8 |
'''
|
9 |
|
10 |
webpage("p").html("Hello world! I have changed this paragraph.") |
11 |
|
12 |
print(webpage("p").html()) |
13 |
'''
|
14 |
Hello world! I have changed this paragraph.
|
15 |
'''
|
Como você pode ver, foi muito fácil para nós manipular o HTML de tags específicas. Vamos ver o que mais podemos mudar.
Manipulação de atributos usando PyQuery
PyQuery tenta espelhar a API jQuery o mais próximo possível. Isso significa que você obtém acesso a um método de atributo chamado attr()
o que torna possível obter e definir o valor dos atributos para os nós DOM selecionados.
Nossa marcação original tinha uma lista ordenada de palavras. Vamos ver se conseguimos o valor de class
atributo da lista. Também usaremos o attr()
para atribuir um ID à nossa lista não ordenada. Isso exigirá que passemos dois argumentos diferentes para o método. Primeiro será a string Eu iria e o segundo será o ID que queremos definir.
1 |
from pyquery import PyQuery as pq |
2 |
|
3 |
webpage = pq(filename = 'document.html') |
4 |
|
5 |
print(webpage("ul").attr('class')) |
6 |
'''
|
7 |
big-words
|
8 |
'''
|
9 |
|
10 |
webpage("ul").attr("id", "word-list") |
11 |
|
12 |
webpage("p").attr("class", "greeting hello-message") |
13 |
|
14 |
print(webpage.html()) |
15 |
'''
|
16 |
|
17 |
|
18 |
|
19 |
|
20 |
|
21 |
|
22 |
|
23 |
|
24 |
|
25 |
|
26 |
|
27 |
|
28 |
|
29 |
|
30 |
|
31 |
|
32 |
|
33 |
'''
|
Como você pode ver, eu também usei o attr()
método para adicionar um conjunto de classes ao nosso p
elementos. Assim como sua contraparte jQuery, o attr()
O método em PyQuery também define o valor do atributo para todos os elementos correspondentes em vez do primeiro.
Como podemos aplicar as classes apenas para o primeiro p
elemento? Podemos simplesmente usar o eq()
para obter o elemento em um índice específico, conforme mostrado abaixo.
1 |
webpage("p").eq(0).attr("class", "greeting hello-message") |
Se você está procurando principalmente manipular classes de seus elementos, você também pode considerar usar o addClass()
e removeClass()
métodos que irão adicionar ou remover uma classe CSS, respectivamente. Você também pode usar os nomes dos métodos add_class()
e remove_class()
se você estiver mais confortável em trabalhar com a notação de sublinhado.
Aqui está um exemplo:
1 |
webpage("p").eq(0).attr("class", "greeting hello-message") |
2 |
#
|
3 |
|
4 |
webpage("p").eq(0).remove_class("greeting") |
5 |
#
|
6 |
|
7 |
webpage("p").eq(0).add_class("first-message") |
8 |
#
|
Você também pode se livrar de quaisquer atributos atribuídos a um elemento usando o remove_attr()
método. Tenha em mente que não há add_attr()
método como essa funcionalidade é atendida por attr()
em si.
Manipulando CSS Usando PyQuery
Além dos atributos, o elemento teria algumas propriedades CSS. Para adicionar ou modificar as propriedades CSS, você pode usar o css()
método e especifique as propriedades cujo valor você deseja definir.
Para o nosso exemplo, selecionaremos a tag em negrito e definiremos sua cor para marrom escuro enquanto aumentamos o font-size
para 120%
. Também tornaremos a cor da nossa lista não ordenada azul. Aqui está o código necessário para fazer isso:
1 |
from pyquery import PyQuery as pq |
2 |
|
3 |
webpage = pq(filename = 'document.html') |
4 |
|
5 |
webpage("ul").css("color", "#1E88E5") |
6 |
webpage("b").css({"font-size": "120%", "color": "#6D4C41"}) |
7 |
|
8 |
print(webpage) |
9 |
'''
|
10 |
|
11 |
|
12 |
|
13 |
|
14 |
|
15 |
|
16 |
|
17 |
|
18 |
|
19 |
|
20 |
|
21 |
|
22 |
|
23 |
|
24 |
|
25 |
|
26 |
|
27 |
|
28 |
|
29 |
'''
|
30 |
|
31 |
with open('updated_markup.html', 'w') as file: |
32 |
file.write(webpage.outer_html()) |
Como você pode ver, o css()
O método no PyQuery é semelhante ao do jQuery. Depois de atualizar os estilos, salvamos a nova marcação em um arquivo chamado updated_markup.html. Você também pode fazer o mesmo depois de fazer várias alterações na marcação.
Criando, removendo e anexando elementos
Você deve se lembrar que nossos exemplos de documentos HTML contêm uma lista de palavras. Podemos expandir a lista de palavras? Claro que nós podemos. Tudo o que você precisa fazer é usar o append()
ou prepend()
métodos. o append()
O método anexará o valor passado ao nó de chamada. Da mesma forma, o prepend()
O método precederá o valor passado ao nó de chamada. Aqui está um exemplo:
1 |
from pyquery import PyQuery as pq |
2 |
|
3 |
webpage = pq(filename = 'document.html') |
4 |
|
5 |
print(webpage("ul")) |
6 |
'''
|
7 |
|
8 |
|
9 |
|
10 |
|
11 |
|
12 |
|
13 |
|
14 |
'''
|
15 |
|
16 |
webpage("ul").append(" |
17 |
webpage("ul").prepend(" |
18 |
|
19 |
print(webpage("ul")) |
20 |
'''
|
21 |
|
22 |
|
23 |
|
24 |
|
25 |
|
26 |
|
27 |
|
28 |
|
29 |
|
30 |
'''
|
Outra opção que você tem para anexar e preceder elementos é o uso de append_to()
e prepend_to()
métodos. o append_to()
O método anexará seu nó de chamada ao nó passado. Da mesma forma, o prepend_to()
O método precederá seu nó de chamada ao nó passado. No entanto, lembre-se de que você não pode simplesmente chamar esses métodos em uma string. Você terá que envolvê-los em um objeto PyQuery para que a chamada funcione conforme mostrado abaixo:
1 |
from pyquery import PyQuery as pq |
2 |
|
3 |
webpage = pq(filename = 'document.html') |
4 |
|
5 |
print(webpage("ul")) |
6 |
'''
|
7 |
|
8 |
|
9 |
|
10 |
|
11 |
|
12 |
|
13 |
|
14 |
'''
|
15 |
|
16 |
pq(" |
17 |
pq(" |
18 |
|
19 |
print(webpage("ul")) |
20 |
'''
|
21 |
|
22 |
|
23 |
|
24 |
|
25 |
|
26 |
|
27 |
|
28 |
|
29 |
|
30 |
'''
|
Como você pode ver, obtemos exatamente a mesma saída. Você também pode remover nós de seu documento simplesmente chamando o remove()
método sobre eles.
Vamos fazer algo interessante agora. Colocaremos a lista de palavras em ordem alfabética primeiro extraindo-as, depois classificando-as e reinserindo-as. Aqui está o código que usamos para fazer isso:
1 |
from pyquery import PyQuery as pq |
2 |
|
3 |
webpage = pq(filename = 'document.html') |
4 |
|
5 |
print(webpage("ul")) |
6 |
'''
|
7 |
|
8 |
|
9 |
|
10 |
|
11 |
|
12 |
|
13 |
|
14 |
'''
|
15 |
|
16 |
words = webpage("ul").children().text().split(' ') |
17 |
words = sorted(words) |
18 |
|
19 |
webpage("ul li").remove() |
20 |
|
21 |
for word in words: |
22 |
webpage("ul").append(" |
23 |
|
24 |
print(webpage("ul")) |
25 |
'''
|
26 |
|
27 |
|
28 |
|
29 |
|
30 |
|
31 |
|
32 |
|
33 |
'''
|
Dois métodos úteis que usamos no exemplo acima são children()
e text()
. O que eles fazem? o children()
O método retorna todos os elementos que são filhos diretos do nó de chamada. No nosso caso, isso significa todos os elementos da lista. Depois disso, usamos o text()
para acessar o valor de texto do nó.
Os valores de texto extraídos são classificados e agrupados dentro li
tags para anexá-los à nossa lista desordenada agora vazia.
Encontrando elementos usando PyQuery
Há uma boa chance de você trabalhar com documentos HTML para extrair alguns dados deles. Agora, antes de extrair esses dados de qualquer elemento, você precisará localizar ou localizar o elemento primeiro.
Você pode simplesmente usar o find()
método e passe um seletor para ele para encontrar elementos que correspondam a esse seletor específico. Este método pesquisa todos os descendentes do nó de chamada.
Você também pode usar o closest()
para procurar elementos caso você esteja interessado em pesquisar os ancestrais desse seletor específico.
1 |
from pyquery import PyQuery as pq |
2 |
|
3 |
webpage = pq(filename = 'document.html') |
4 |
|
5 |
print(webpage.find("b").text()) |
6 |
'''
|
7 |
world
|
8 |
'''
|
9 |
|
10 |
print(webpage.find("i").closest("p").html()) |
11 |
'''
|
12 |
Here is a list of some random words:
|
13 |
'''
|
Já cobrimos o children()
método na seção anterior. Você também pode acessar todos os irmãos de um elemento usando o siblings()
método. Outros métodos semelhantes que você pode usar são os next_all()
e prev_all()
que lhe dará todos os irmãos que vêm a seguir ou os irmãos que vieram antes, respectivamente. Aqui está um exemplo:
1 |
from pyquery import PyQuery as pq |
2 |
|
3 |
webpage = pq(filename = 'document.html') |
4 |
|
5 |
print(webpage.find("li").eq(2).siblings()) |
6 |
'''
|
7 |
|
8 |
|
9 |
|
10 |
|
11 |
'''
|
12 |
|
13 |
print(webpage.find("li").eq(2).prev_all()) |
14 |
'''
|
15 |
|
16 |
|
17 |
'''
|
18 |
|
19 |
print(webpage.find("li").eq(2).next_all()) |
20 |
'''
|
21 |
|
22 |
|
23 |
'''
|
Extraindo conteúdo da página da Web
Você se lembra quando eu disse no início do tutorial que o PyQuery pode aceitar entrada de várias fontes, como uma string, um arquivo ou até mesmo uma URL?
Nesta seção, vamos deixar o PyQuery obter sua marcação de uma página sobre Python na WikiPedia. A página da Web contém muitas informações sobre o Python. Vamos tentar extrair um pouco para nosso consumo. Vamos ver se conseguimos todos os h2
títulos de nível para manter as coisas simples.
Acredite ou não, mas você só precisa de 5 linhas de código para obter o texto do título.
1 |
from pyquery import PyQuery as pq |
2 |
|
3 |
webpage = pq(url='https://en.wikipedia.org/wiki/Python_(programming_language)') |
4 |
|
5 |
headings = webpage.find("h2 span.mw-headline") |
6 |
|
7 |
for heading in headings: |
8 |
print(pq(heading).text()) |
9 |
'''
|
10 |
History
|
11 |
Design philosophy and features
|
12 |
Syntax and semantics
|
13 |
Programming examples
|
14 |
Libraries
|
15 |
Development environments
|
16 |
Implementations
|
17 |
Development
|
18 |
API documentation generators
|
19 |
Naming
|
20 |
Popularity
|
21 |
Uses
|
22 |
Languages influenced by Python
|
23 |
See also
|
24 |
References
|
25 |
Further reading
|
26 |
External links
|
27 |
'''
|
Você deve ter notado que eu usei o seletor h2 span.mw-manchete ao invés de usar h2. Isso ocorre porque simplesmente usando h2 estava me dando alguns títulos adicionais que não faziam parte do conteúdo principal. Você também terá que fazer uma análise semelhante das páginas da Web antes de determinar o seletor apropriado a ser usado para extrair as informações.
Já escrevi um tutorial sobre o módulo Requests em Python onde usamos o módulo para baixar imagens. Uma limitação do exemplo que incluí foi que estávamos codificando o caminho da imagem. Vamos usar a biblioteca PyQuery para extrair os caminhos de imagem de uma página da Web e alimentá-los para o módulo de solicitações para download. Eu estarei usando a página WikiPedia sobre Estados Unidos para este exemplo:
1 |
import requests |
2 |
from pyquery import PyQuery as pq |
3 |
|
4 |
webpage = pq(url='https://en.wikipedia.org/wiki/United_States') |
5 |
|
6 |
images = webpage.find("img.thumbimage") |
7 |
|
8 |
for image in images: |
9 |
image_url = "https:" + pq(image).attr('src') |
10 |
|
11 |
image_name = image_url.split('/')[-1] |
12 |
|
13 |
req = requests.get(image_url) |
14 |
req.raise_for_status() |
15 |
|
16 |
with open(image_name, 'wb') as fd: |
17 |
fd.write(req.content) |
Não queremos baixar imagens dos ícones da interface do usuário, etc. É por isso que usei um seletor mais específico para extrair nossas imagens. Eu obtenho o nome do arquivo de imagem pegando a última parte do caminho da imagem depois de dividi-lo ao longo do / personagem. Aqui estão algumas das imagens que consegui extrair:
Embrulhando-o
Neste tutorial, você viu como começar a usar PyQuery
, uma biblioteca Python que permite fazer consultas jQuery em documentos XML. Você viu como manipular os atributos e estilos CSS dos elementos HTML.
Você aprendeu como criar e anexar elementos a elementos existentes e inserir novos elementos antes e depois dos elementos. O que você viu neste tutorial é apenas a ponta do iceberg, e há muito mais que esta biblioteca tem a oferecer.
Para obter informações mais detalhadas sobre como usar esta biblioteca, recomendo a leitura da documentação oficial. Deixe-nos saber suas sugestões nos comentários abaixo.