Web raschiando con Python [chiuso]


183

Vorrei prendere orari giornalieri di alba / tramonto da un sito web. È possibile raschiare il contenuto Web con Python? quali sono i moduli utilizzati? C'è qualche tutorial disponibile?


3
Python ha diverse opzioni per il web scraping. Ho elencato alcune delle opzioni qui in risposta a una domanda simile.
filippo,

Perché non usare semplicemente il parser HTML incorporato nella libreria standard di Python? Certamente per un compito così semplice e poco frequente (solo una volta al giorno), vedo poche ragioni per cercare altri strumenti. docs.python.org/2.7/library/htmlparser.html
ArtOfWarfare

Spero che questo post possa essere utile a qualcuno riguardo a questo. Un buon tutorial per un principiante. samranga.blogspot.com/2015/08/web-scraping-beginner-python.html Utilizza una bellissima libreria Python per il web scraping con Python.
Samitha Chathuranga,

Risposte:


187

Usa urllib2 in combinazione con la brillante libreria BeautifulSoup :

import urllib2
from BeautifulSoup import BeautifulSoup
# or if you're using BeautifulSoup4:
# from bs4 import BeautifulSoup

soup = BeautifulSoup(urllib2.urlopen('http://example.com').read())

for row in soup('table', {'class': 'spad'})[0].tbody('tr'):
    tds = row('td')
    print tds[0].string, tds[1].string
    # will print date and sunrise

7
Piccolo commento: questo può essere leggermente semplificato usando il pacchetto di richieste sostituendo la riga 6 con: soup = BeautifulSoup (request.get (' example.com'). Testo )
D Coetzee,

4
grazie per il consiglio. il pacchetto di richiesta non esisteva ancora, quando ho scritto lo snippet sopra ;-)

1
@DerrickCoetzee - la tua semplificazione genera un errore MissingSchema (almeno sulla mia installazione). Funziona così:soup = BeautifulSoup(requests.get('http://example.com').text)
kmote del

@kmote: era quello che ho digitato ma ho dimenticato backticksil codice around e lo ha convertito in un link. Grazie!
D Coetzee,

Come sei sicuro che il contenuto sarà in td e tr. Può essere in ul e li anche giusto?
Shashank Hegde,

62

Consiglio vivamente Scrapy.

Citazione da una risposta cancellata:

  • La scansione strisciante è più veloce della meccanizzazione perché utilizza operazioni asincrone (oltre a Twisted).
  • Scrapy ha un supporto migliore e più veloce per l'analisi (x) html su libxml2.
  • Scrapy è un framework maturo con unicode completo, gestisce reindirizzamenti, risposte gzip, codifiche dispari, cache http integrata, ecc.
  • Una volta che sei in Scrapy, puoi scrivere un ragno in meno di 5 minuti per scaricare immagini, creare miniature ed esportare i dati estratti direttamente su CSV o JSON.

13
Non ho notato che questa domanda aveva già 2 anni, sento ancora che Scrapy dovrebbe essere chiamato qui nel caso in cui qualcun altro abbia la stessa domanda.
Sjaak Trekhaak,

4
Scrapy è un framework, quindi è orribile e pensa che sia più importante del tuo progetto. È un framework a causa delle orribili (non necessarie) limitazioni di Twisted.
user1244215

4
@ user1244215: è un framework perché i framework sono belli. Se non vuoi usarlo come framework, non c'è nulla che ti impedisca di bloccare tutto il tuo codice in un unico file.
Blender

1
Ma non supporta Python 3.x.

17

Ho raccolto insieme script dal mio lavoro di scraping web in questa libreria di bit-bucket .

Script di esempio per il tuo caso:

from webscraping import download, xpath
D = download.Download()

html = D.get('http://example.com')
for row in xpath.search(html, '//table[@class="spad"]/tbody/tr'):
    cols = xpath.search(row, '/td')
    print 'Sunrise: %s, Sunset: %s' % (cols[1], cols[2])

Produzione:

Sunrise: 08:39, Sunset: 16:08
Sunrise: 08:39, Sunset: 16:09
Sunrise: 08:39, Sunset: 16:10
Sunrise: 08:40, Sunset: 16:10
Sunrise: 08:40, Sunset: 16:11
Sunrise: 08:40, Sunset: 16:12
Sunrise: 08:40, Sunset: 16:13

10

Consiglio vivamente di dare un'occhiata al pyquery . Usa una sintassi simile a jquery (aka css-like) che rende le cose davvero facili per coloro che provengono da quel background.

Per il tuo caso, sarebbe qualcosa del tipo:

from pyquery import *

html = PyQuery(url='http://www.example.com/')
trs = html('table.spad tbody tr')

for tr in trs:
  tds = tr.getchildren()
  print tds[1].text, tds[2].text

Produzione:

5:16 AM 9:28 PM
5:15 AM 9:30 PM
5:13 AM 9:31 PM
5:12 AM 9:33 PM
5:11 AM 9:34 PM
5:10 AM 9:35 PM
5:09 AM 9:37 PM

7

Puoi usare urllib2 per effettuare le richieste HTTP, quindi avrai contenuti web.

Puoi ottenerlo in questo modo:

import urllib2
response = urllib2.urlopen('http://example.com')
html = response.read()

Bella zuppa è un parser HTML in pitone che dovrebbe essere buono per lo scraping dello schermo.

In particolare, ecco il loro tutorial sull'analisi di un documento HTML.

In bocca al lupo!


Potrebbe essere un'idea impostare un massimo sui byte letti. response.read (100000000) o qualcosa del genere in modo che quegli URL per ISO non riempiano la tua RAM. Buon mining.
Andrew Pate,

4

Uso una combinazione di Scrapemark (trovando urls - py2) e httlib2 (scaricando immagini - py2 + 3). Scrapemark.py ha 500 righe di codice, ma usa espressioni regolari, quindi potrebbe non essere così veloce, non testato.

Esempio per raschiare il tuo sito Web:

import sys
from pprint import pprint
from scrapemark import scrape

pprint(scrape("""
    <table class="spad">
        <tbody>
            {*
                <tr>
                    <td>{{[].day}}</td>
                    <td>{{[].sunrise}}</td>
                    <td>{{[].sunset}}</td>
                    {# ... #}
                </tr>
            *}
        </tbody>
    </table>
""", url=sys.argv[1] ))

Uso:

python2 sunscraper.py http://www.example.com/

Risultato:

[{'day': u'1. Dez 2012', 'sunrise': u'08:18', 'sunset': u'16:10'},
 {'day': u'2. Dez 2012', 'sunrise': u'08:19', 'sunset': u'16:10'},
 {'day': u'3. Dez 2012', 'sunrise': u'08:21', 'sunset': u'16:09'},
 {'day': u'4. Dez 2012', 'sunrise': u'08:22', 'sunset': u'16:09'},
 {'day': u'5. Dez 2012', 'sunrise': u'08:23', 'sunset': u'16:08'},
 {'day': u'6. Dez 2012', 'sunrise': u'08:25', 'sunset': u'16:08'},
 {'day': u'7. Dez 2012', 'sunrise': u'08:26', 'sunset': u'16:07'}]

1

Semplifica la tua vita usando CSS Selectors

So di essere arrivato tardi alla festa, ma ho un bel suggerimento per te.

L'uso BeautifulSoupè già stato suggerito Preferirei preferire l'uso CSS Selectorsper raschiare dati all'interno di HTML

import urllib2
from bs4 import BeautifulSoup

main_url = "http://www.example.com"

main_page_html  = tryAgain(main_url)
main_page_soup = BeautifulSoup(main_page_html)

# Scrape all TDs from TRs inside Table
for tr in main_page_soup.select("table.class_of_table"):
   for td in tr.select("td#id"):
       print(td.text)
       # For acnhors inside TD
       print(td.select("a")[0].text)
       # Value of Href attribute
       print(td.select("a")[0]["href"])

# This is method that scrape URL and if it doesnt get scraped, waits for 20 seconds and then tries again. (I use it because my internet connection sometimes get disconnects)
def tryAgain(passed_url):
    try:
        page  = requests.get(passed_url,headers = random.choice(header), timeout = timeout_time).text
        return page
    except Exception:
        while 1:
            print("Trying again the URL:")
            print(passed_url)
            try:
                page  = requests.get(passed_url,headers = random.choice(header), timeout = timeout_time).text
                print("-------------------------------------")
                print("---- URL was successfully scraped ---")
                print("-------------------------------------")
                return page
            except Exception:
                time.sleep(20)
                continue 

1

Se pensiamo di ottenere il nome degli articoli da una categoria specifica, possiamo farlo specificando il nome della classe di quella categoria usando il selettore css:

import requests ; from bs4 import BeautifulSoup

soup = BeautifulSoup(requests.get('https://www.flipkart.com/').text, "lxml")
for link in soup.select('div._2kSfQ4'):
    print(link.text)

Questi sono i risultati della ricerca parziale:

Puma, USPA, Adidas & moreUp to 70% OffMen's Shoes
Shirts, T-Shirts...Under ₹599For Men
Nike, UCB, Adidas & moreUnder ₹999Men's Sandals, Slippers
Philips & moreStarting 99LED Bulbs & Emergency Lights

0

Ecco un semplice crawler web, ho usato BeautifulSoup e cercheremo tutti i collegamenti (ancore) il cui nome di classe è _3NFO0d. Ho usato Flipkar.com, è un negozio di vendita online.

import requests
from bs4 import BeautifulSoup
def crawl_flipkart():
    url = 'https://www.flipkart.com/'
    source_code = requests.get(url)
    plain_text = source_code.text
    soup = BeautifulSoup(plain_text, "lxml")
    for link in soup.findAll('a', {'class': '_3NFO0d'}):
        href = link.get('href')
        print(href)

crawl_flipkart()

0

Python ha buone opzioni per raschiare il web. Il migliore con un framework è sciatto . Può essere un po 'complicato per i principianti, quindi ecco un piccolo aiuto.
1. Installa python sopra 3.5 (quelli inferiori fino alla 2.7 funzioneranno).
2. Creare un ambiente in conda (ho fatto questo).
3. Installare scrapy in una posizione ed eseguire da lì.
4. Scrapy shellti fornirà un'interfaccia interattiva per testare il tuo codice.
5. Scrapy startproject projectnamecreerà un framework.
6. Scrapy genspider spidernamecreerà un ragno. Puoi creare quanti ragni vuoi. Mentre lo fai, assicurati di essere nella directory del progetto.


Il più semplice è usare le richieste e la bella zuppa . Prima di iniziare, dai un'ora di tempo per consultare la documentazione, risolverà la maggior parte dei tuoi dubbi. BS4 offre una vasta gamma di parser che puoi scegliere. Utilizzare user-agente sleepper facilitare la raschiatura. BS4 restituisce un bs.tag quindi usa variable[0]. Se js è in esecuzione, non sarai in grado di eseguire lo scraping utilizzando le richieste e bs4 direttamente. È possibile ottenere il collegamento API quindi analizzare JSON per ottenere le informazioni necessarie o provare selenium.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.