BeautifulSoup ile Python Web'den Kazıma

Sep 16 2020

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

3 Carcigenicate Sep 16 2020 at 20:57
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:

  • dict verileri doğru şekilde tanımlamayan genel bir addır.
  • dict yerleş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.