Ricerca…


introduzione

Lo scraping Web è un processo programmatico automatizzato attraverso il quale i dati possono essere costantemente "raschiati" fuori dalle pagine Web. Conosciuto anche come screen scraping o web harvesting, il web scraping può fornire dati istantanei da qualsiasi pagina web accessibile al pubblico. Su alcuni siti Web, il web scraping potrebbe essere illegale.

Osservazioni

Utili pacchetti Python per lo scraping web (in ordine alfabetico)

Fare richieste e raccogliere dati

requests

Un semplice ma potente pacchetto per fare richieste HTTP.

requests-cache

Memorizzazione nella cache delle requests ; i dati di memorizzazione nella cache sono molto utili. In fase di sviluppo, significa che puoi evitare di colpire un sito inutilmente. Quando si esegue una vera raccolta, significa che se il tuo raschietto si blocca per qualche motivo (forse non hai gestito alcuni contenuti insoliti sul sito ...? Forse il sito è andato giù ...?) Puoi ripetere la raccolta molto velocemente da dove eri rimasto.

scrapy

Utile per creare web crawler, dove è necessario qualcosa di più potente dell'uso di requests e iterazione attraverso le pagine.

selenium

Collegamenti Python per Selenium WebDriver, per l'automazione del browser. L'utilizzo delle requests per effettuare direttamente richieste HTTP è spesso più semplice per il recupero di pagine Web. Tuttavia, questo rimane uno strumento utile quando non è possibile replicare il comportamento desiderato di un sito utilizzando solo le requests , in particolare quando è richiesto JavaScript per il rendering di elementi in una pagina.

Analisi HTML

BeautifulSoup

Interrogare i documenti HTML e XML, utilizzando un numero di parser diversi (Parser HTML incorporato di Python, html5lib , lxml o lxml.html )

lxml

Elabora HTML e XML. Può essere usato per interrogare e selezionare il contenuto da documenti HTML tramite selettori CSS e XPath.

Esempio di base di utilizzo di richieste e lxml per raschiare alcuni dati

# For Python 2 compatibility.
from __future__ import print_function

import lxml.html
import requests


def main():
    r = requests.get("https://httpbin.org")
    html_source = r.text
    root_element = lxml.html.fromstring(html_source)
    # Note root_element.xpath() gives a *list* of results.
    # XPath specifies a path to the element we want.
    page_title = root_element.xpath('/html/head/title/text()')[0]
    print(page_title)

if __name__ == '__main__':
    main()

Mantenimento della sessione di web scraping con le richieste

È consigliabile mantenere una sessione di web-scraping per mantenere i cookie e altri parametri. Inoltre, può comportare un miglioramento delle prestazioni poiché requests.Session riutilizza la connessione TCP sottostante a un host:

import requests

with requests.Session() as session:
    # all requests through session now have User-Agent header set
    session.headers = {'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/51.0.2704.103 Safari/537.36'}

    # set cookies
    session.get('http://httpbin.org/cookies/set?key=value')

    # get cookies
    response = session.get('http://httpbin.org/cookies')
    print(response.text)

Raschiare usando il framework Scrapy

Per prima cosa devi creare un nuovo progetto Scrapy. Inserisci una directory in cui desideri memorizzare il codice ed esegui:

scrapy startproject projectName

Per raschiare abbiamo bisogno di un ragno. Gli spider definiscono come verrà raschiato un determinato sito. Ecco il codice per uno spider che segue i link alle domande più votate su StackOverflow e cancella alcuni dati da ciascuna pagina ( fonte ):

import scrapy

class StackOverflowSpider(scrapy.Spider):
    name = 'stackoverflow'  # each spider has a unique name
    start_urls = ['http://stackoverflow.com/questions?sort=votes']  # the parsing starts from a specific set of urls

    def parse(self, response):  # for each request this generator yields, its response is sent to parse_question
        for href in response.css('.question-summary h3 a::attr(href)'):  # do some scraping stuff using css selectors to find question urls 
            full_url = response.urljoin(href.extract())
            yield scrapy.Request(full_url, callback=self.parse_question)

    def parse_question(self, response): 
        yield {
            'title': response.css('h1 a::text').extract_first(),
            'votes': response.css('.question .vote-count-post::text').extract_first(),
            'body': response.css('.question .post-text').extract_first(),
            'tags': response.css('.question .post-tag::text').extract(),
            'link': response.url,
        }

Salva le tue classi spider nella directory projectName\spiders . In questo caso - projectName\spiders\stackoverflow_spider.py .

Ora puoi usare il tuo ragno. Ad esempio, prova a eseguire (nella directory del progetto):

scrapy crawl stackoverflow

Modifica agente utente Scrapy

A volte l'agente utente Scrapy predefinito ( "Scrapy/VERSION (+http://scrapy.org)" ) viene bloccato dall'host. Per cambiare l'agente utente predefinito, apri settings.py , decommenta e modifica la riga seguente per quello che vuoi.

#USER_AGENT = 'projectName (+http://www.yourdomain.com)'

Per esempio

USER_AGENT = 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/51.0.2704.103 Safari/537.36'

Raschiare usando BeautifulSoup4

from bs4 import BeautifulSoup
import requests

# Use the requests module to obtain a page
res = requests.get('https://www.codechef.com/problems/easy')

# Create a BeautifulSoup object
page = BeautifulSoup(res.text, 'lxml')   # the text field contains the source of the page

# Now use a CSS selector in order to get the table containing the list of problems
datatable_tags = page.select('table.dataTable')  # The problems are in the <table> tag,
                                                 # with class "dataTable"
# We extract the first tag from the list, since that's what we desire
datatable = datatable_tags[0]
# Now since we want problem names, they are contained in <b> tags, which are
# directly nested under <a> tags
prob_tags = datatable.select('a > b')
prob_names = [tag.getText().strip() for tag in prob_tags]

print prob_names

Raschiatura usando Selenium WebDriver

Alcuni siti Web non amano essere raschiati. In questi casi potrebbe essere necessario simulare un utente reale che lavora con un browser. Selenium lancia e controlla un browser web.

from selenium import webdriver

browser = webdriver.Firefox()  # launch firefox browser

browser.get('http://stackoverflow.com/questions?sort=votes')  # load url

title = browser.find_element_by_css_selector('h1').text  # page title (first h1 element)

questions = browser.find_elements_by_css_selector('.question-summary')  # question list

for question in questions:  # iterate over questions
    question_title = question.find_element_by_css_selector('.summary h3 a').text
    question_excerpt = question.find_element_by_css_selector('.summary .excerpt').text
    question_vote = question.find_element_by_css_selector('.stats .vote .votes .vote-count-post').text
    
    print "%s\n%s\n%s votes\n-----------\n" % (question_title, question_excerpt, question_vote) 

Il selenio può fare molto di più. Può modificare i cookie del browser, compilare moduli, simulare clic del mouse, acquisire schermate di pagine Web ed eseguire JavaScript personalizzato.

Download semplice di contenuti Web con urllib.request

Il modulo di libreria standard urllib.request può essere utilizzato per scaricare contenuti web:

from urllib.request import urlopen

response = urlopen('http://stackoverflow.com/questions?sort=votes')    
data = response.read()

# The received bytes should usually be decoded according the response's character set
encoding = response.info().get_content_charset()
html = data.decode(encoding)

Un modulo simile è disponibile anche in Python 2 .

Raschiando con arricciatura

importazioni:

from subprocess import Popen, PIPE
from lxml import etree
from io import StringIO

Download:

user_agent = 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.95 Safari/537.36'
url = 'http://stackoverflow.com'
get = Popen(['curl', '-s', '-A', user_agent, url], stdout=PIPE)
result = get.stdout.read().decode('utf8')

-s : download silenzioso

-A : flag agente utente

di analisi:

tree = etree.parse(StringIO(result), etree.HTMLParser())
divs = tree.xpath('//div')


Modified text is an extract of the original Stack Overflow Documentation
Autorizzato sotto CC BY-SA 3.0
Non affiliato con Stack Overflow