Zoeken…


Invoering

Webschrapen is een geautomatiseerd, programmatisch proces waardoor gegevens constant van webpagina's kunnen worden 'geschraapt'. Web scraping, ook bekend als screen scraping of web harvesting, kan direct gegevens opleveren van elke openbaar toegankelijke webpagina. Op sommige websites kan webschrapen illegaal zijn.

Opmerkingen

Handige Python-pakketten voor webscraping (alfabetische volgorde)

Verzoeken doen en gegevens verzamelen

requests

Een eenvoudig, maar krachtig pakket voor het doen van HTTP-verzoeken.

requests-cache

Caching voor requests ; cachegegevens zijn erg handig. In ontwikkeling betekent dit dat u kunt voorkomen dat u onnodig een site bezoekt. Terwijl je een echte collectie beheert, betekent dit dat als je krabber om de een of andere reden crasht (misschien heb je geen ongewone inhoud op de site behandeld ...? Misschien is de site offline gegaan??), Je de collectie heel snel kunt herhalen van waar je was gebleven.

scrapy

Handig voor het bouwen van webcrawlers, waarbij u iets nodig hebt dat krachtiger is dan het gebruik van requests en het doorlopen van pagina's.

selenium

Python-bindingen voor Selenium WebDriver, voor browserautomatisering. Het gebruik van requests om HTTP-aanvragen rechtstreeks te doen, is vaak eenvoudiger voor het ophalen van webpagina's. Dit blijft echter een handig hulpmiddel wanneer het niet mogelijk is om het gewenste gedrag van een site te repliceren met alleen requests , vooral wanneer JavaScript vereist is om elementen op een pagina weer te geven.

HTML parsing

BeautifulSoup

Vraag HTML- en XML-documenten op, met behulp van een aantal verschillende parsers (Python's ingebouwde HTML Parser, html5lib , lxml of lxml.html )

lxml

Verwerkt HTML en XML. Kan worden gebruikt voor het opvragen en selecteren van inhoud uit HTML-documenten via CSS-selectors en XPath.

Eenvoudig voorbeeld van het gebruik van verzoeken en lxml om sommige gegevens te schrapen

# 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()

Web-scraping-sessie met verzoeken onderhouden

Het is een goed idee om een webschrapsessie te houden om de cookies en andere parameters te behouden. Bovendien kan het leiden tot een prestatieverbetering omdat requests.Session de onderliggende TCP-verbinding met een host opnieuw gebruikt:

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)

Schrapen met behulp van het Scrapy-framework

Eerst moet je een nieuw Scrapy-project opzetten. Voer een map in waar u uw code wilt opslaan en voer uit:

scrapy startproject projectName

Om te schrapen hebben we een spin nodig. Spinnen bepalen hoe een bepaalde site wordt geschraapt. Hier is de code voor een spin die de links volgt naar de meest gestemde vragen over StackOverflow en wat gegevens van elke pagina ( bron ) verwijdert:

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,
        }

Sla uw spider-klassen op in de map projectName\spiders . In dit geval - projectName\spiders\stackoverflow_spider.py .

Nu kunt u uw spin gebruiken. Probeer bijvoorbeeld uit te voeren (in de map van het project):

scrapy crawl stackoverflow

Wijzig Scrapy user agent

Soms wordt de standaard Scrapy-gebruikersagent ( "Scrapy/VERSION (+http://scrapy.org)" ) geblokkeerd door de host. Als u de standaard user-agent wilt wijzigen, opent u settings.py , uncomment en bewerkt u de volgende regel naar wens.

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

Bijvoorbeeld

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'

Schrapen met 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

Schrapen met Selenium WebDriver

Sommige websites houden er niet van om geschraapt te worden. In deze gevallen moet u mogelijk een echte gebruiker simuleren die met een browser werkt. Selenium lanceert en bestuurt een webbrowser.

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) 

Selenium kan veel meer. Het kan de cookies van de browser wijzigen, formulieren invullen, muisklikken simuleren, screenshots van webpagina's maken en aangepaste JavaScript uitvoeren.

Eenvoudig downloaden van webcontent met urllib.request

De standaard bibliotheekmodule urllib.request kan worden gebruikt om webinhoud te downloaden:

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)

Een vergelijkbare module is ook beschikbaar in Python 2 .

Schrapen met krullen

invoer:

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

downloaden:

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 : stille download

-A : user agent vlag

parseren:

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


Modified text is an extract of the original Stack Overflow Documentation
Licentie onder CC BY-SA 3.0
Niet aangesloten bij Stack Overflow