Python Web-Scraping dengan BeautifulSoup
Saya relatif baru mengenal python dan untuk tugas saya harus menulis program yang mengambil halaman web dengan BeautifulSoup, mengekstrak semua Paragraf darinya, dan mengekstrak semua kata yang diakhiri dengan "ing", dan pada akhirnya menyimpannya ke file dengan format "Word" + tab + "wordcount" + "newline".
Ini adalah kode saya sejauh ini. Apakah ada cara yang lebih pythonic untuk menangani ini? Atau umumnya cara untuk meningkatkan kode?
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()
Jawaban
if word in matching_words:
matching_words[word] += 1
else:
matching_words[word] = 1
Jika Anda memeriksa apakah kamus memiliki kunci sebelum menambahkannya, a defaultdictmungkin pilihan yang lebih baik:
from collections import defaultdict
matching_words = defaultdict(int)
matching_words[word] += 1
intmengembalikan 0ketika dipanggil tanpa argumen, dan itu 0digunakan sebagai nilai default untuk kamus ketika kuncinya tidak ada.
fulltext = ''
for p in ps:
fulltext += p.get_text()
Ini tidak terlalu efisien. Performa +=on string menjadi lebih baik di versi Python yang lebih baru, tetapi secara umum masih lebih lambat. Alternatif tipikal menggunakan join:
pieces = [p.get_text() for p in ps]
fulltext = "".join(pieces)
# Or just
fulltext = "".join([p.get_text() for p in ps])
Kemudian serupa di sort_and_format:
output_string = "".join([f"{r}\t{dict[r]}\n"] for r in ordered_keys])
Di sort_and_format, Anda telah memberi nama parameter dict. Ini kurang optimal karena beberapa alasan:
dictadalah nama umum yang tidak mendeskripsikan data dengan tepat.dictadalah nama kelas bawaan, dan membayangi itu membuat kode Anda lebih membingungkan, dan mencegah Anda menggunakan bawaan.
Menunjukkan tipe bisa membantu, jadi saya mungkin memperkenalkan petunjuk tipe di sini
from typing import Dict
def sort_and_format(words: Dict[str, int]) -> str:
. . .
Ini mengatakan bahwa fungsi menerima Dictpemetaan ioner strke ints, dan mengembalikan a string
Juga untuk sort_and_format, saya telah menemukan bahwa ketika Anda mulai menempel andpada nama, itu bisa menunjukkan bahwa fungsinya terlalu banyak. Anda mungkin menemukan bahwa kode akan lebih masuk akal jika pengurutan dan pemformatan dilakukan secara terpisah. Fungsi tersebut dapat menangani pemformatan murni, dan dapat diberikan urutan untuk dikerjakan. Jika urutan itu diurutkan, bagus, jika tidak, juga bagus. Tidak masalah untuk tujuan memformat apa urutan sortirnya.