Last chance! 50% off DataCamp Premium
Sale ends in
In een tijd waarin het internet bomvol data staat en data het nieuwe goud lijkt te zijn, is webscraping belangrijker en praktischer geworden voor allerlei toepassingen. Webscraping draait om het extraheren of "scrapen" van informatie van websites. Webscraping wordt ook wel web harvesting of web data extraction genoemd. Tekst van een website kopiëren en plakken op je lokale systeem is óók webscraping, maar dan handmatig. Meestal gaat webscraping over het automatisch extraheren van data met behulp van webcrawlers. Webcrawlers zijn scripts die verbinding maken met het world wide web via het HTTP-protocol en je in staat stellen data geautomatiseerd op te halen.
Of je nu data scientist, engineer of iemand bent die grote datasets analyseert: data van het web kunnen scrapen is een nuttige vaardigheid. Stel, je vindt data op het web en er is geen directe manier om die te downloaden, dan kun je met Python webscraping de data extraheren naar een bruikbare vorm die je daarna op allerlei manieren kunt importeren en gebruiken.
Enkele praktische toepassingen van webscraping zijn:
Naast bovenstaande usecases wordt webscraping veel gebruikt in natural language processing om tekst van websites te halen voor het trainen van een deep learning-model.
Houd er voordat je verdergaat rekening mee dat websites zoals Amazon hun specifieke servicevoorwaarden kunnen bijwerken of nieuwe technische beperkingen kunnen toevoegen die beïnvloeden hoe hun content kan worden benaderd of hergebruikt. Het is jouw verantwoordelijkheid om de Servicevoorwaarden en het robots.txt-bestand van de site te controleren om ervoor te zorgen dat jouw specifieke usecase compliant is. Beleid kan veranderen en toestemmingen kunnen variëren.
Een van de uitdagingen bij het scrapen van informatie van websites is de variatie in websitestructuren. Met andere woorden: websites gebruiken verschillende en unieke templates; generaliseren over websites heen kan dus lastig zijn.
Een andere uitdaging is duurzaamheid. Omdat webdevelopers hun websites blijven updaten, kun je niet te lang op één scraper vertrouwen. Zelfs kleine aanpassingen kunnen het ophalen van data al verstoren.
Om bovenstaande uitdagingen aan te pakken zijn er verschillende oplossingen. Een daarvan is continuous integration & development (CI/CD) toepassen en constante onderhoud, aangezien de wijzigingen op websites dynamisch zijn.
Een realistischer aanpak is het gebruik van Application Programming Interfaces (API's) die door verschillende websites en platforms worden aangeboden. Facebook en Twitter bieden bijvoorbeeld API's die speciaal zijn ontworpen voor developers die met hun data willen experimenteren of informatie willen extraheren, bijvoorbeeld over alle vrienden en gemeenschappelijke vrienden om daar een connectiegrafiek van te maken. Het dataformaat bij gebruik van API's verschilt van gewone webscraping, namelijk JSON of XML, terwijl je bij standaard webscraping vooral met data in HTML-formaat werkt.
Beautiful Soup is een pure Python-bibliotheek voor het extraheren van gestructureerde data van een website. Je kunt er data mee parsen uit HTML- en XML-bestanden. Het fungeert als hulpmodule en werkt met HTML op een vergelijkbare, maar vaak prettigere manier dan hoe je met andere ontwikkelaarstools met een webpagina zou werken.
Het bespaart programmeurs doorgaans uren of dagen werk omdat het samenwerkt met je favoriete parsers zoals lxml en html5lib en zo natuurlijke Python-manieren biedt om door de parsetree te navigeren, te zoeken en die te wijzigen.
Een andere krachtige en nuttige functie van Beautiful Soup is de intelligentie om binnenkomende documenten om te zetten naar Unicode en uitgaande documenten naar UTF-8. Als developer hoef je je daar niet druk om te maken, tenzij het document zelf geen encoding specificeert of Beautiful Soup er geen kan detecteren.
Het wordt ook als sneller beschouwd vergeleken met andere algemene parse- of scrapingtechnieken.
Lees er gerust meer over hier.
Genoeg theorie, toch? Laten we Beautiful Soup installeren en aan de slag gaan met de functies en mogelijkheden in Python.
Als eerste stap installeer je de Beautiful Soup-bibliotheek via je terminal of Jupyter Lab. De beste manier om Beautiful Soup te installeren is via pip, dus zorg dat de module pip al is geïnstalleerd.
!pip3 install beautifulsoup4
Requirement already satisfied: beautifulsoup4 in /usr/local/lib/python3.7/site-packages (4.7.1)
Requirement already satisfied: soupsieve>=1.2 in /usr/local/lib/python3.7/site-packages (from beautifulsoup4) (1.9.5)
Laten we de pakketten importeren die je gebruikt om data van de website te scrapen en te visualiseren met behulp van seaborn, matplotlib en bokeh.
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
%matplotlib inline
import re
import time
from datetime import datetime
import matplotlib.dates as mdates
import matplotlib.ticker as ticker
from urllib.request import urlopen
from bs4 import BeautifulSoup
import requests
De URL die je gaat scrapen is de volgende: https://www.amazon.in/gp/bestsellers/books/. De pagina-parameter kan worden aangepast om data per pagina op te halen. Om alle pagina's te benaderen, moet je dus door alle pagina's loopen om de benodigde dataset te krijgen, maar eerst moet je op de website het aantal pagina's achterhalen.
Om verbinding te maken met de URL en de HTML-content op te halen, heb je het volgende nodig:
get_data die paginanummers als argument krijgt,user-agent die helpt om detectie als scraper te omzeilen,requests.get en voeg de user-agent-header toe als argument,De volgende en belangrijke stap is het identificeren van de parent tag waaronder alle benodigde data staat. De data die je gaat extraheren is:
De onderstaande afbeelding laat zien waar de parent tag zich bevindt; als je eroverheen hovert, worden alle vereiste elementen gemarkeerd.

Net als bij de parent tag moet je de attributen vinden voor boektitel, auteur, beoordeling, aantal beoordelingen en prijs. Ga naar de webpagina die je wilt scrapen, selecteer het attribuut, klik met de rechtermuisknop en kies Inspecteren. Zo vind je de specifieke informatievelden die je uit de ruwe HTML-pagina wilt halen, zoals in de onderstaande figuur:

Let op: sommige auteursnamen zijn niet bij Amazon geregistreerd, dus voor die auteurs moet je een extra find toepassen. In de onderstaande cel vind je geneste if-else-voorwaarden voor auteursnamen om de auteurs-/uitgeversnamen te extraheren.
no_pages = 2
def get_data(pageNo):
headers = {"User-Agent":"Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:66.0) Gecko/20100101 Firefox/66.0", "Accept-Encoding":"gzip, deflate", "Accept":"text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8", "DNT":"1","Connection":"close", "Upgrade-Insecure-Requests":"1"}
r = requests.get('https://www.amazon.in/gp/bestsellers/books/ref=zg_bs_pg_'+str(pageNo)+'?ie=UTF8&pg='+str(pageNo), headers=headers)#, proxies=proxies)
content = r.content
soup = BeautifulSoup(content)
#print(soup)
alls = []
for d in soup.findAll('div', attrs={'class':'a-section a-spacing-none aok-relative'}):
#print(d)
name = d.find('span', attrs={'class':'zg-text-center-align'})
n = name.find_all('img', alt=True)
#print(n[0]['alt'])
author = d.find('a', attrs={'class':'a-size-small a-link-child'})
rating = d.find('span', attrs={'class':'a-icon-alt'})
users_rated = d.find('a', attrs={'class':'a-size-small a-link-normal'})
price = d.find('span', attrs={'class':'p13n-sc-price'})
all1=[]
if name is not None:
#print(n[0]['alt'])
all1.append(n[0]['alt'])
else:
all1.append("unknown-product")
if author is not None:
#print(author.text)
all1.append(author.text)
elif author is None:
author = d.find('span', attrs={'class':'a-size-small a-color-base'})
if author is not None:
all1.append(author.text)
else:
all1.append('0')
if rating is not None:
#print(rating.text)
all1.append(rating.text)
else:
all1.append('-1')
if users_rated is not None:
#print(price.text)
all1.append(users_rated.text)
else:
all1.append('0')
if price is not None:
#print(price.text)
all1.append(price.text)
else:
all1.append('0')
alls.append(all1)
return alls
De onderstaande codecel voert het volgende uit:
get_data aan binnen een for-loop,for-loop itereert over deze functie vanaf 1 tot en met het aantal pagina's+1.results = []
for i in range(1, no_pages+1):
results.append(get_data(i))
flatten = lambda l: [item for sublist in l for item in sublist]
df = pd.DataFrame(flatten(results),columns=['Book Name','Author','Rating','Customers_Rated', 'Price'])
df.to_csv('amazon_products.csv', index=False, encoding='utf-8')
Laad nu het CSV-bestand dat je hierboven hebt gemaakt en opgeslagen. Dit is een optionele stap; je kunt ook direct de dataframe df gebruiken en de onderstaande stap overslaan.
df = pd.read_csv("amazon_products.csv")
df.shape
(100, 5)
De shape van de DataFrame laat zien dat je CSV-bestand 100 rijen en 5 kolommen heeft.
Laten we de eerste 5 rijen van de dataset printen.
df.head(61)
| Book Name | Author | Rating | Customers_Rated | Price | |
|---|---|---|---|---|---|
| 0 | The Power of your Subconscious Mind | Joseph Murphy | 4.5 out of 5 stars | 13,948 | ₹ 99.00 |
| 1 | Think and Grow Rich | Napoleon Hill | 4.5 out of 5 stars | 16,670 | ₹ 99.00 |
| 2 | Word Power Made Easy | Norman Lewis | 4.4 out of 5 stars | 10,708 | ₹ 130.00 |
| 3 | Mathematics for Class 12 (Set of 2 Vol.) Exami... | R.D. Sharma | 4.5 out of 5 stars | 18 | ₹ 930.00 |
| 4 | The Girl in Room 105 | Chetan Bhagat | 4.3 out of 5 stars | 5,162 | ₹ 149.00 |
| ... | ... | ... | ... | ... | ... |
| 56 | COMBO PACK OF Guide To JAIIB Legal Aspects Pri... | MEC MILLAN | 4.5 out of 5 stars | 114 | ₹ 1,400.00 |
| 57 | Wren & Martin High School English Grammar and ... | Rao N | 4.4 out of 5 stars | 1,613 | ₹ 400.00 |
| 58 | Objective General Knowledge | Sanjiv Kumar | 4.2 out of 5 stars | 742 | ₹ 254.00 |
| 59 | The Rudest Book Ever | Shwetabh Gangwar | 4.6 out of 5 stars | 1,177 | ₹ 194.00 |
| 60 | Sita: Warrior of Mithila (Ram Chandra Series -... | Amish Tripathi | 4.4 out of 5 stars | 3,110 | ₹ 248.00 |
61 rijen × 5 kolommen
Laten we wat preprocessing doen op de kolommen Ratings, Customers_Rated en Price.
df['Rating'] = df['Rating'].apply(lambda x: x.split()[0])
df['Rating'] = pd.to_numeric(df['Rating'])
df["Price"] = df["Price"].str.replace('₹', '')
df["Price"] = df["Price"].str.replace(',', '')
df['Price'] = df['Price'].apply(lambda x: x.split('.')[0])
df['Price'] = df['Price'].astype(int)
df["Customers_Rated"] = df["Customers_Rated"].str.replace(',', '')
df['Customers_Rated'] = pd.to_numeric(df['Customers_Rated'], errors='ignore')
df.head()
| Book Name | Author | Rating | Customers_Rated | Price | |
|---|---|---|---|---|---|
| 0 | The Power of your Subconscious Mind | Joseph Murphy | 4.5 | 13948 | 99 |
| 1 | Think and Grow Rich | Napoleon Hill | 4.5 | 16670 | 99 |
| 2 | Word Power Made Easy | Norman Lewis | 4.4 | 10708 | 130 |
| 3 | Mathematics for Class 12 (Set of 2 Vol.) Exami... | R.D. Sharma | 4.5 | 18 | 930 |
| 4 | The Girl in Room 105 | Chetan Bhagat | 4.3 | 5162 | 149 |
Laten we de datatypes van de DataFrame controleren.
df.dtypes
Book Name object
Author object
Rating float64
Customers_Rated int64
Price int64
dtype: object
Vervang de nullen in de DataFrame door NaN.
df.replace(str(0), np.nan, inplace=True)
df.replace(0, np.nan, inplace=True)
count_nan = len(df) - df.count()
count_nan
Book Name 0
Author 6
Rating 0
Customers_Rated 0
Price 1
dtype: int64
Uit bovenstaande output blijkt dat er in totaal zes boeken zijn zonder auteursnaam, terwijl één boek geen prijs heeft. Deze informatie is cruciaal voor een auteur die zijn of haar boeken wil verkopen en zou niet vergeten mogen worden.
Laten we deze NaN's verwijderen.
df = df.dropna()
Laten we uitzoeken welke auteurs het hoogst geprijsde boek hadden. We visualiseren de resultaten voor de top 20 auteurs.
data = df.sort_values(["Price"], axis=0, ascending=False)[:15]
data
| Book Name | Author | Rating | Customers_Rated | Price | |
|---|---|---|---|---|---|
| 56 | COMBO PACK OF Guide To JAIIB Legal Aspects Pri... | MEC MILLAN | 4.5 | 114 | 1400.0 |
| 98 | Diseases of Ear, Nose and Throat | P L Dhingra | 4.7 | 118 | 1285.0 |
| 3 | Mathematics for Class 12 (Set of 2 Vol.) Exami... | R.D. Sharma | 4.5 | 18 | 930.0 |
| 96 | Madhymik Bhautik Vigyan -12 (Part 1-2) (NCERT ... | Kumar-Mittal | 5.0 | 1 | 765.0 |
| 6 | My First Library: Boxset of 10 Board Books for... | Wonder House Books | 4.5 | 3116 | 750.0 |
| 38 | Indian Polity - For Civil Services and Other S... | M. Laxmikanth | 4.6 | 1210 | 700.0 |
| 42 | A Modern Approach to Verbal & Non-Verbal Reaso... | R.S. Aggarwal | 4.4 | 1822 | 675.0 |
| 27 | The Intelligent Investor (English) Paperback –... | Benjamin Graham | 4.4 | 6201 | 650.0 |
| 99 | Law of CONTRACT & Specific Relief | Dr. Avtar Singh | 4.4 | 23 | 643.0 |
| 49 | All In One ENGLISH CORE CBSE Class 12 2019-20 | Arihant Experts | 4.4 | 493 | 599.0 |
| 72 | The Secret | Rhonda Byrne | 4.5 | 11220 | 556.0 |
| 86 | How to Prepare for Quantitative Aptitude for t... | Arun Sharma | 4.4 | 847 | 537.0 |
| 8 | Quantitative Aptitude for Competitive Examinat... | R S Aggarwal | 4.4 | 4553 | 435.0 |
| 16 | Sapiens: A Brief History of Humankind | Yuval Noah Harari | 4.6 | 14985 | 434.0 |
| 84 | Concept of Physics Part-2 (2019-2020 Session) ... | H.C. Verma | 4.6 | 1807 | 433.0 |
from bokeh.models import ColumnDataSource
from bokeh.transform import dodge
import math
from bokeh.io import curdoc
curdoc().clear()
from bokeh.io import push_notebook, show, output_notebook
from bokeh.layouts import row
from bokeh.plotting import figure
from bokeh.transform import factor_cmap
from bokeh.models import Legend
output_notebook()
p = figure(x_range=data.iloc[:,1], plot_width=800, plot_height=550, title="Authors Highest Priced Book", toolbar_location=None, tools="")
p.vbar(x=data.iloc[:,1], top=data.iloc[:,4], width=0.9)
p.xgrid.grid_line_color = None
p.y_range.start = 0
p.xaxis.major_label_orientation = math.pi/2
show(p)

Uit de bovenstaande grafiek blijkt dat de twee hoogst geprijsde boeken van de auteurs Mecmillan en P L Dhingra zijn.
Laten we uitzoeken welke auteurs de hoogst beoordeelde boeken hebben en welke boeken dat zijn. Daarbij filter je auteurs weg met minder dan 1000 klantbeoordelingen.
data = df[df['Customers_Rated'] > 1000]
data = data.sort_values(['Rating'],axis=0, ascending=False)[:15]
data
| Book Name | Author | Rating | Customers_Rated | Price | |
|---|---|---|---|---|---|
| 26 | Inner Engineering: A Yogi’s Guide to Joy | Sadhguru | 4.7 | 4091 | 254.0 |
| 70 | Bhagavad-Gita (Hindi) | A. C. Bhaktivedanta | 4.7 | 1023 | 150.0 |
| 11 | The Alchemist | Paulo Coelho | 4.7 | 22182 | 264.0 |
| 47 | Harry Potter and the Philosopher's Stone | J.K. Rowling | 4.7 | 7737 | 234.0 |
| 84 | Concept of Physics Part-2 (2019-2020 Session) ... | H.C. Verma | 4.6 | 1807 | 433.0 |
| 16 | Sapiens: A Brief History of Humankind | Yuval Noah Harari | 4.6 | 14985 | 434.0 |
| 38 | Indian Polity - For Civil Services and Other S... | M. Laxmikanth | 4.6 | 1210 | 700.0 |
| 29 | Wings of Fire: An Autobiography of Abdul Kalam | Arun Tiwari | 4.6 | 3513 | 301.0 |
| 39 | The Theory of Everything | Stephen Hawking | 4.6 | 2004 | 199.0 |
| 25 | The Immortals of Meluha (Shiva Trilogy) | Amish | 4.6 | 4538 | 248.0 |
| 23 | Life's Amazing Secrets: How to Find Balance an... | Gaur Gopal Das | 4.6 | 3422 | 213.0 |
| 34 | Dear Stranger, I Know How You Feel | Ashish Bagrecha | 4.6 | 1130 | 167.0 |
| 17 | The Monk Who Sold His Ferrari | Robin Sharma | 4.6 | 5877 | 137.0 |
| 13 | How to Win Friends and Influence People | Dale Carnegie | 4.6 | 15377 | 99.0 |
| 59 | The Rudest Book Ever | Shwetabh Gangwar | 4.6 | 1177 | 194.0 |
p = figure(x_range=data.iloc[:,0], plot_width=800, plot_height=600, title="Top Rated Books with more than 1000 Customers Rating", toolbar_location=None, tools="")
p.vbar(x=data.iloc[:,0], top=data.iloc[:,2], width=0.9)
p.xgrid.grid_line_color = None
p.y_range.start = 0
p.xaxis.major_label_orientation = math.pi/2
show(p)

Uit bovenstaande output blijkt dat de drie hoogst beoordeelde boeken met meer dan 1000 klantbeoordelingen zijn: Inner Engineering: A Yogi’s Guide to Joy, Bhagavad-Gita (Hindi) en The Alchemist.
p = figure(x_range=data.iloc[:,1], plot_width=800, plot_height=600, title="Top Rated Books with more than 1000 Customers Rating", toolbar_location=None, tools="")
p.vbar(x=data.iloc[:,1], top=data.iloc[:,2], width=0.9)
p.xgrid.grid_line_color = None
p.y_range.start = 0
p.xaxis.major_label_orientation = math.pi/2
show(p)

De bovenstaande grafiek toont in aflopende volgorde de top 10 auteurs met de hoogst beoordeelde boeken met meer dan 1000 klantbeoordelingen: Sadhguru, A. C. Bhaktivedanta en Paulo Coelho.
Je hebt de hoogst beoordeelde boeken en auteurs al gezien, maar het is overtuigender en betrouwbaarder om de beste auteur en het beste boek te bepalen op basis van het aantal klanten dat heeft beoordeeld.
Laten we dat snel uitzoeken.
data = df.sort_values(["Customers_Rated"], axis=0, ascending=False)[:20]
data
| Book Name | Author | Rating | Customers_Rated | Price | |
|---|---|---|---|---|---|
| 11 | The Alchemist | Paulo Coelho | 4.7 | 22182 | 264.0 |
| 1 | Think and Grow Rich | Napoleon Hill | 4.5 | 16670 | 99.0 |
| 13 | How to Win Friends and Influence People | Dale Carnegie | 4.6 | 15377 | 99.0 |
| 16 | Sapiens: A Brief History of Humankind | Yuval Noah Harari | 4.6 | 14985 | 434.0 |
| 18 | Rich Dad Poor Dad : What The Rich Teach Their ... | Robert T. Kiyosaki | 4.5 | 14591 | 296.0 |
| 10 | The Subtle Art of Not Giving a F*ck | Mark Manson | 4.4 | 14418 | 365.0 |
| 0 | The Power of your Subconscious Mind | Joseph Murphy | 4.5 | 13948 | 99.0 |
| 48 | The Power of Your Subconscious Mind | Joseph Murphy | 4.5 | 13948 | 99.0 |
| 72 | The Secret | Rhonda Byrne | 4.5 | 11220 | 556.0 |
| 41 | 1984 | George Orwell | 4.5 | 10829 | 95.0 |
| 2 | Word Power Made Easy | Norman Lewis | 4.4 | 10708 | 130.0 |
| 46 | Man's Search For Meaning: The classic tribute ... | Viktor E Frankl | 4.4 | 8544 | 245.0 |
| 67 | The 7 Habits of Highly Effective People | R. Stephen Covey | 4.3 | 8229 | 397.0 |
| 47 | Harry Potter and the Philosopher's Stone | J.K. Rowling | 4.7 | 7737 | 234.0 |
| 40 | One Indian Girl | Chetan Bhagat | 3.8 | 7128 | 113.0 |
| 65 | Thinking, Fast and Slow (Penguin Press Non-Fic... | Daniel Kahneman | 4.4 | 7087 | 410.0 |
| 27 | The Intelligent Investor (English) Paperback –... | Benjamin Graham | 4.4 | 6201 | 650.0 |
| 17 | The Monk Who Sold His Ferrari | Robin Sharma | 4.6 | 5877 | 137.0 |
| 53 | Ram - Scion of Ikshvaku (Ram Chandra) | Amish Tripathi | 4.2 | 5766 | 262.0 |
| 93 | The Richest Man in Babylon | George S. Clason | 4.5 | 5694 | 129.0 |
from bokeh.transform import factor_cmap
from bokeh.models import Legend
from bokeh.palettes import Dark2_5 as palette
import itertools
from bokeh.palettes import d3
#colors has a list of colors which can be used in plots
colors = itertools.cycle(palette)
palette = d3['Category20'][20]
index_cmap = factor_cmap('Author', palette=palette,
factors=data["Author"])
p = figure(plot_width=700, plot_height=700, title = "Top Authors: Rating vs. Customers Rated")
p.scatter('Rating','Customers_Rated',source=data,fill_alpha=0.6, fill_color=index_cmap,size=20,legend='Author')
p.xaxis.axis_label = 'RATING'
p.yaxis.axis_label = 'CUSTOMERS RATED'
p.legend.location = 'top_left'
BokehDeprecationWarning: 'legend' keyword is deprecated, use explicit 'legend_label', 'legend_field', or 'legend_group' keywords instead
show(p)

De bovenstaande grafiek is een scatterplot van auteurs met het aantal klantbeoordelingen versus de daadwerkelijke beoordeling. De volgende conclusies kun je trekken:
Gefeliciteerd met het afronden van de tutorial.
Deze tutorial was een basisintroductie in het scrapen van Amazon met Beautiful Soup en hoe je de geëxtraheerde informatie inzichtelijk kunt maken met de Bokeh-plotbibliotheek. Een goede oefening om een stap verder te gaan in webscraping leren met Beautiful Soup is om data van andere websites te scrapen en te kijken welke inzichten je eruit kunt halen. We hebben ook een tutorial over het scrapen van Reddit als je meer begeleiding wilt bij het scrapen van populaire websites.
Ben je net begonnen met Python en wil je meer leren? Volg dan de cursus Introduction to Data Science in Python van DataCamp.
Leer meer over Python
Cursus
Cursus
Cursus

blog
Adel Nehme
15 min