Mysql
 sql >> Datenbank >  >> RDS >> Mysql

Wunderschönes Suppen-Webscrape in MySQL

Hier gibt es also ein paar Dinge zu beachten.

Die Dokumente zu PyMySQL sind ziemlich gut darin, Sie zum Laufen zu bringen.

Bevor Sie diese Dinge jedoch in eine Datenbank einfügen können, müssen Sie sie so erfassen, dass der Interpret und der Songname miteinander verknüpft sind. Im Moment erhalten Sie eine separate Liste mit Künstlern und Songs, ohne dass Sie sie zuordnen können. Dazu sollten Sie die title-artist-Klasse durchlaufen.

Ich würde das so machen -

from urllib import urlopen
from bs4 import BeautifulSoup
import pymysql.cursors

# Webpage connection
html = urlopen("http://www.officialcharts.com/charts/singles-chart/19800203/7501/")

# Grab title-artist classes and iterate
bsObj = BeautifulSoup(html)
recordList = bsObj.findAll("div", {"class" : "title-artist",})

# Now iterate over recordList to grab title and artist
for record in recordList:
     title = record.find("div", {"class": "title",}).get_text().strip()
     artist = record.find("div", {"class": "artist"}).get_text().strip()
     print artist + ': ' + title

Dadurch werden der Titel und der Interpret für jede Iteration der recordList-Schleife gedruckt.

Um diese Werte in eine MySQL-DB einzufügen, habe ich eine Tabelle namens artist_song erstellt mit folgendem:

CREATE TABLE `artist_song` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `artist` varchar(255) COLLATE utf8_bin NOT NULL,
  `song` varchar(255) COLLATE utf8_bin NOT NULL,
  PRIMARY KEY (`id`)
  ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin
  AUTO_INCREMENT=1;

Dies ist nicht der sauberste Weg, dies zu tun, aber die Idee ist solide. Wir wollen eine Verbindung zur MySQL-DB öffnen (ich habe meine DB top_40 genannt) und ein Interpret/Titel-Paar für jede Iteration der recordList-Schleife einfügen:

from urllib import urlopen
from bs4 import BeautifulSoup
import pymysql.cursors


# Webpage connection
html = urlopen("http://www.officialcharts.com/charts/singles-chart/19800203/7501/")

# Grab title-artist classes and store in recordList
bsObj = BeautifulSoup(html)
recordList = bsObj.findAll("div", {"class" : "title-artist",})

# Create a pymysql cursor and iterate over each title-artist record.
# This will create an INSERT statement for each artist/pair, then commit
# the transaction after reaching the end of the list. pymysql does not
# have autocommit enabled by default. After committing it will close
# the database connection.
# Create database connection

connection = pymysql.connect(host='localhost',
                             user='root',
                             password='password',
                             db='top_40',
                             charset='utf8mb4',
                             cursorclass=pymysql.cursors.DictCursor)

try:
    with connection.cursor() as cursor:
        for record in recordList:
            title = record.find("div", {"class": "title",}).get_text().strip()
            artist = record.find("div", {"class": "artist"}).get_text().strip()
            sql = "INSERT INTO `artist_song` (`artist`, `song`) VALUES (%s, %s)"
            cursor.execute(sql, (artist, title))
    connection.commit()
finally:
    connection.close()

Bearbeiten:Laut meinem Kommentar ist es meiner Meinung nach klarer, stattdessen über die Tabellenzeilen zu iterieren:

from urllib import urlopen
from bs4 import BeautifulSoup
import pymysql.cursors


# Webpage connection
html = urlopen("http://www.officialcharts.com/charts/singles-chart/19800203/7501/")

bsObj = BeautifulSoup(html)

rows = bsObj.findAll('tr')
for row in rows:
    if row.find('span', {'class' : 'position'}):
        position = row.find('span', {'class' : 'position'}).get_text().strip()
        artist = row.find('div', {'class' : 'artist'}).get_text().strip()
        track = row.find('div', {'class' : 'title'}).get_text().strip()