BeautifulSoup ile Python Web'den Kazıma
Python'da nispeten yeniyim ve bir ödev için BeautifulSoup ile bir web sayfasını getiren bir program yazmak, ondan tüm Paragrafları çıkarmak ve "ing" ile biten tüm kelimeleri çıkarmak ve sonunda onu bir dosyaya kaydetmek zorunda kaldım. "Kelime" + sekme + "kelime sayısı" + "yeni satır" biçimi.
Şimdiye kadarki kodum bu. Bunu halletmenin daha pitonik bir yolu var mı? Veya genel olarak kodu iyileştirmenin yolları?
from bs4 import BeautifulSoup
import requests
import re
def main():
site = "https://en.wikipedia.org/wiki/Data_science"
r = requests.get(site).content
soup = BeautifulSoup(r)
ps = soup.findAll('p')
fulltext = ''
for p in ps:
fulltext += p.get_text()
words = match_words(fulltext)
formated_words = sort_and_format(words)
with open(r"Q1_Part1.txt","w") as file:
file.write(formated_words)
def match_words(string):
pattern = re.compile(r'\b(\w*ing)\b')
words = re.findall(pattern, string.lower())
matching_words = {}
for word in words:
if word in matching_words:
matching_words[word] += 1
else:
matching_words[word] = 1
return matching_words
def sort_and_format(dict):
ordered_keys = sorted(dict, key=dict.get, reverse=True)
output_string = ''
for r in ordered_keys:
output_string += f"{r}\t{dict[r]}\n"
return output_string
main()
Yanıtlar
if word in matching_words:
matching_words[word] += 1
else:
matching_words[word] = 1
Bir sözlüğe eklemeden önce bir anahtar olup olmadığını kontrol ediyorsanız, defaultdictdaha iyi bir seçenek olabilir:
from collections import defaultdict
matching_words = defaultdict(int)
matching_words[word] += 1
int0bağımsız değişken olmadan çağrıldığında bir döndürür ve bu 0, anahtar olmadığında sözlük için varsayılan bir değer olarak kullanılır.
fulltext = ''
for p in ps:
fulltext += p.get_text()
Bu çok verimli değil. +=Dizeler üzerindeki performansı Python'un sonraki sürümlerinde daha iyi hale geldi, ancak yine de genellikle daha yavaş. Tipik alternatif kullanmaktır join:
pieces = [p.get_text() for p in ps]
fulltext = "".join(pieces)
# Or just
fulltext = "".join([p.get_text() for p in ps])
Sonra benzer şekilde sort_and_format:
output_string = "".join([f"{r}\t{dict[r]}\n"] for r in ordered_keys])
İçinde sort_and_format, parametreyi adlandırdınız dict. Bu, birkaç nedenden dolayı yetersizdir:
dictverileri doğru şekilde tanımlamayan genel bir addır.dictyerleşik bir sınıfın adıdır ve gölgeleme, kodunuzu daha kafa karıştırıcı hale getirir ve yerleşik olanı kullanmanıza engel olur.
Yine de türü belirtmek yardımcı olabilir, bu nedenle burada yazım ipuçları sunabilirim
from typing import Dict
def sort_and_format(words: Dict[str, int]) -> str:
. . .
Bu fonksiyonlar bir kabul ettiğini söylüyor Dictionary haritalama striçin bu toplantıların ints ve döner string
Ayrıca sort_and_format, andisimlere bağlı kalmaya başladığınızda , bu işlevin çok fazla şey yaptığını gösterebileceğini gördüm . Sıralama ve biçimlendirme ayrı ayrı yapılırsa kodun daha anlamlı olacağını görebilirsiniz. Bu işlevler tamamen biçimlendirmeyi halledebilir ve bunun yerine üzerinde çalışmak için bir sıra verilebilir. Bu sıra sıralanırsa, harika değilse de harika. Sıralama düzeninin ne olduğu biçimlendirmenin amaçları açısından önemli değildir.