C'est le résultat lorsque la vitesse d'exécution du bot de recherche d'images à l'aide de BeautifulSoup a été améliorée. J'espère que cela sera utile pour ceux qui sont en difficulté car la vitesse d'exécution du grattage est lente.
Vous pouvez accélérer en spécifiant un code de caractère approprié dans l'argument de BeautifulSoup: ** from_encoding **.
from urllib import request
import bs4
page = request.urlopen("https://news.yahoo.co.jp/")
html = page.read()
# from_Remplacez le code de caractère du site à gratter dans l'encodage(Dans le cas de Yahoo News cette fois, utf-8)
soup = bs4.BeautifulSoup(html, "html.parser", from_encoding="utf-8")
Fondamentalement, il est écrit après charset = dans la balise meta.
<!--Dans le cas de Yahoo News-->
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
Je l'ai vérifié avec le script suivant. Mesuré avant et après la création d'une instance
verification_bs4.py
from urllib import request as req
from urllib import parse
import bs4
import time
import copy
url = "https://news.yahoo.co.jp/"
page = req.urlopen(url)
html = page.read()
page.close()
start = time.time()
soup = bs4.BeautifulSoup(html, "html.parser")
print('{:.5f}'.format(time.time() - start) + "[s] html.parser, None")
start = time.time()
soup = bs4.BeautifulSoup(html, "lxml")
print('{:.5f}'.format(time.time() - start) + "[s] lxml, None")
start = time.time()
hoge = copy.copy(soup)
print('{:.5f}'.format(time.time() - start) + "[s] copy(lxml, None)")
start = time.time()
soup = bs4.BeautifulSoup(html, "html.parser", from_encoding="utf-8")
print('{:.5f}'.format(time.time() - start) + "[s] html.parser, utf-8")
start = time.time()
soup = bs4.BeautifulSoup(html, "lxml", from_encoding="utf-8")
print('{:.5f}'.format(time.time() - start) + "[s] lxml, utf-8")
start = time.time()
hoge = copy.copy(soup)
print('{:.5f}'.format(time.time() - start) + "[s] copy(lxml, utf-8)")
start = time.time()
soup = bs4.BeautifulSoup(html, "lxml", from_encoding="utf-16")
#La valeur de retour est vide car le code de caractère est différent
print('{:.5f}'.format(time.time() - start) + "[s] lxml, utf-16")
Le résultat de sortie est ici.
% python verification_bs4.py
2.10937[s] html.parser, None
2.00081[s] lxml, None
0.04704[s] copy(lxml, None)
0.03124[s] html.parser, utf-8
0.03115[s] lxml, utf-8
0.04188[s] copy(lxml, utf-8)
0.01651[s] lxml, utf-16
En spécifiant le code de caractère dans ** from_encoding **, nous avons pu accélérer l'instanciation. En regardant le code qui dit que BeautifulSoup est lent, je ne l'ai pas assigné à from_encoding, donc je pense que c'est la cause.
Je me demandais pourquoi il avait de telles spécifications, alors j'ai vérifié le code source. Cependant, je ne touche généralement pas autant à Python, donc j'écris peut-être quelque chose qui ne tient pas compte. Le code source est ici
Probablement à cause de la classe ** EncodingDetector ** définie dans ** bs4 / dammit.py **. Ce qui suit est un extrait de code partiel.
class EncodingDetector:
"""Suggests a number of possible encodings for a bytestring.
Order of precedence:
1. Encodings you specifically tell EncodingDetector to try first
(the override_encodings argument to the constructor).
2. An encoding declared within the bytestring itself, either in an
XML declaration (if the bytestring is to be interpreted as an XML
document), or in a <meta> tag (if the bytestring is to be
interpreted as an HTML document.)
3. An encoding detected through textual analysis by chardet,
cchardet, or a similar external library.
4. UTF-8.
5. Windows-1252.
"""
@property
def encodings(self):
"""Yield a number of encodings that might work for this markup.
:yield: A sequence of strings.
"""
tried = set()
for e in self.override_encodings:
if self._usable(e, tried):
yield e
# Did the document originally start with a byte-order mark
# that indicated its encoding?
if self._usable(self.sniffed_encoding, tried):
yield self.sniffed_encoding
# Look within the document for an XML or HTML encoding
# declaration.
if self.declared_encoding is None:
self.declared_encoding = self.find_declared_encoding(
self.markup, self.is_html)
if self._usable(self.declared_encoding, tried):
yield self.declared_encoding
# Use third-party character set detection to guess at the
# encoding.
if self.chardet_encoding is None:
self.chardet_encoding = chardet_dammit(self.markup)
if self._usable(self.chardet_encoding, tried):
yield self.chardet_encoding
# As a last-ditch effort, try utf-8 and windows-1252.
for e in ('utf-8', 'windows-1252'):
if self._usable(e, tried):
yield e
Si vous traduisez le commentaire écrit au début du cours, il ressemblera à ceci (traduction DeepL)
""""Nous suggérons quelques encodages possibles pour les chaînes d'octets.
L'ordre de priorité est le suivant.
1.L'encodage que vous avez demandé à EncodingDetector d'essayer en premier
Remplacement d'argument du constructeur_Utilisez des encodages).
2.L'encodage déclaré dans la chaîne d'octets elle-même.
Déclaration XML(Lorsque la chaîne d'octets est interprétée comme XML)
document), Ou<meta>Dans le tag(Chaîne d'octets
Interprété comme un document HTML)。
3.L'encodage détecté par l'analyse de texte par Charde.
Utilisez cchardet ou une bibliothèque externe similaire.
4. 4.UTF-8。
5. Windows-1252。
"""
En déduisant des commentaires et du traitement, je pense qu'il est lent car il est en cours de traitement jusqu'à ce que la liste 1 à 5 ci-dessus réussisse dans l'ordre. En regardant 2, le code de caractère devinant à partir de la balise meta mentionnée plus tôt est également fait automatiquement, donc je pense que c'est une considération pour que vous puissiez l'utiliser sans spécifier le code de caractère en regardant la source du site Web. Cependant, lors du grattage, je pense que je vérifie généralement le code source, donc je ne pense pas qu'il devrait être si tard. (Nous n'avons pas vérifié quel processus est le goulot d'étranglement, alors veuillez me donner quelqu'un.)
Dans le script de mesure du temps d'exécution précédent, la méthode copy.copy () est utilisée pour dupliquer l'instance, et la raison pour laquelle c'est si rapide est dans \ _ \ _ copy \ _ \ _ de bs4 / __ init__.py. Ce qui suit est un extrait de code partiel.
__init__.py
class BeautifulSoup(Tag):
def __copy__(self):
"""Copy a BeautifulSoup object by converting the document to a string and parsing it again."""
copy = type(self)(
self.encode('utf-8'), builder=self.builder, from_encoding='utf-8'
)
# Although we encoded the tree to UTF-8, that may not have
# been the encoding of the original markup. Set the copy's
# .original_encoding to reflect the original object's
# .original_encoding.
copy.original_encoding = self.original_encoding
return copy
C'est plus rapide parce que j'ai choisi utf-8 ici. Cependant, au contraire, si le code de caractère du site de grattage est autre que utf-8, il sera plus lent. Dans le script de mesure suivant, le code de caractère est mesuré par price com de shift-jis.
verification_bs4_2.py
from urllib import request as req
from urllib import parse
import bs4
import time
import copy
url = "https://kakaku.com/"
page = req.urlopen(url)
html = page.read()
page.close()
start = time.time()
soup = bs4.BeautifulSoup(html, "html.parser")
print('{:.5f}'.format(time.time() - start) + "[s] html.parser, None")
start = time.time()
soup = bs4.BeautifulSoup(html, "lxml")
print('{:.5f}'.format(time.time() - start) + "[s] lxml, None")
start = time.time()
soup = bs4.BeautifulSoup(html, "lxml", from_encoding="shift_jis")
print('{:.5f}'.format(time.time() - start) + "[s] lxml, shift_jis")
start = time.time()
hoge = copy.copy(soup)
print('{:.5f}'.format(time.time() - start) + "[s] copy(lxml, shift_jis)")
Le résultat de sortie est ici.
% python verification_bs4_2.py
0.11084[s] html.parser, None
0.08563[s] lxml, None
0.08643[s] lxml, shift_jis
0.13631[s] copy(lxml, shift_jis)
Comme mentionné ci-dessus, la copie est plus lente que utf-8. Cependant, dans le cas de shift-jis, même si rien n'est spécifié dans ** from_encoding **, la vitesse d'exécution n'a guère changé. ~~ Je ne sais plus ça </ font> ~~
Merci d'avoir lu jusqu'ici! À la fin, je suis désolé que ça soit compliqué. Je me demande pourquoi plus de 90% de tous les sites Web dans le monde sont utf-8 mais lents. J'ai créé un article parce que je sentais que c'était un problème que les sites qui recherchaient avec BeautifulSoup et atteignaient le sommet n'en aient pas parlé. Si vous le trouvez utile, ce serait encourageant si vous pouviez "LGTM".
référence https://stackoverrun.com/ja/q/12619706
Recommended Posts