sql >> Databáze >  >> NoSQL >> MongoDB

Scrapy webu pomocí Scrapy a MongoDB

V tomto článku vytvoříme škrabku pro skutečné koncert na volné noze, kde klient chce, aby program Python seškrábal data ze Stack Overflow, aby získal nové otázky (název otázky a URL). Scrapped data by pak měla být uložena v MongoDB. Stojí za zmínku, že Stack Overflow má API, které lze použít k přístupu k přesnému stejná data. Klient však chtěl škrabku, takže dostal škrabku.

Box zdarma: Klikněte sem a stáhněte si kostru projektu Python + MongoDB s úplným zdrojovým kódem, který vám ukáže, jak přistupovat k MongoDB z Pythonu.

Aktualizace:

  • 01/03/2014 - Refaktorováno pavouka. Díky, @kissgyorgy.
  • 18. 2. 2015 – přidána část 2.
  • 09/06/2015 – Aktualizováno na nejnovější verzi Scrapy a PyMongo – na zdraví!

Jako vždy si nezapomeňte přečíst podmínky používání/služby webu a respektovat robots.txt soubor před zahájením jakékoli škrabací práce. Ujistěte se, že dodržujete etické postupy stírání tím, že nezahlcujete web mnoha požadavky během krátké doby. Zacházejte s každým webem, který oškrábete, jako by byl váš vlastní .


Instalace

Potřebujeme knihovnu Scrapy (v1.0.3) spolu s PyMongo (v3.0.3) pro ukládání dat v MongoDB. Musíte nainstalovat také MongoDB (není zahrnuto).


Scrapy

Pokud používáte OSX nebo verzi Linuxu, nainstalujte Scrapy s pip (s aktivovaným virtualenv):

$ pip install Scrapy==1.0.3
$ pip freeze > requirements.txt

Pokud používáte počítač se systémem Windows, budete muset ručně nainstalovat řadu závislostí. Podrobné pokyny naleznete v oficiální dokumentaci a v tomto videu na YouTube, které jsem vytvořil.

Jakmile je Scrapy nastaven, ověřte svou instalaci spuštěním tohoto příkazu v prostředí Pythonu:

>>>
>>> import scrapy
>>> 

Pokud se vám nezobrazí chyba, můžete začít!



PyMongo

Dále nainstalujte PyMongo pomocí pip:

$ pip install pymongo
$ pip freeze > requirements.txt

Nyní můžeme začít stavět prohledávač.




Projekt Scrapy

Začněme nový projekt Scrapy:

$ scrapy startproject stack
2015-09-05 20:56:40 [scrapy] INFO: Scrapy 1.0.3 started (bot: scrapybot)
2015-09-05 20:56:40 [scrapy] INFO: Optional features available: ssl, http11
2015-09-05 20:56:40 [scrapy] INFO: Overridden settings: {}
New Scrapy project 'stack' created in:
    /stack-spider/stack

You can start your first spider with:
    cd stack
    scrapy genspider example example.com

Tím se vytvoří řada souborů a složek, které obsahují základní vzor, ​​abyste mohli rychle začít:

├── scrapy.cfg
└── stack
    ├── __init__.py
    ├── items.py
    ├── pipelines.py
    ├── settings.py
    └── spiders
        └── __init__.py

Zadejte data

Soubor items.py soubor se používá k definování „kontejnerů“ úložiště pro data, která plánujeme seškrábat.

StackItem() třída dědí z Item (docs), který má v podstatě řadu předdefinovaných objektů, které pro nás Scrapy již postavil:

import scrapy


class StackItem(scrapy.Item):
    # define the fields for your item here like:
    # name = scrapy.Field()
    pass

Pojďme přidat nějaké položky, které skutečně chceme sbírat. Pro každou otázku klient potřebuje název a URL. Aktualizujte tedy items.py takhle:

from scrapy.item import Item, Field


class StackItem(Item):
    title = Field()
    url = Field()


Vytvořte Pavouka

Vytvořte soubor s názvem stack_spider.py v adresáři „pavouci“. Tady se děje kouzlo – např. kde Scrapymu řekneme, jak najít přesné údaje, které hledáme. Jak si dokážete představit, toto je specifické na každou jednotlivou webovou stránku, kterou chcete seškrábat.

Začněte definováním třídy, která dědí ze Scrapyho Spider a poté podle potřeby přidejte atributy:

from scrapy import Spider


class StackSpider(Spider):
    name = "stack"
    allowed_domains = ["stackoverflow.com"]
    start_urls = [
        "http://stackoverflow.com/questions?pagesize=50&sort=newest",
    ]

Prvních několik proměnných je samovysvětlujících (docs):

  • name definuje jméno pavouka.
  • allowed_domains obsahuje základní adresy URL povolených domén, které může pavouk procházet.
  • start_urls je seznam adres URL, ze kterých má pavouk začít procházet. Všechny následující adresy URL budou začínat daty, která si pavouk stáhne z adres URL v start_urls .


Selektory XPath

Dále Scrapy používá selektory XPath k extrahování dat z webu. Jinými slovy, můžeme vybrat určité části HTML dat na základě dané XPath. Jak je uvedeno v dokumentaci Scrapy, „XPath je jazyk pro výběr uzlů v dokumentech XML, který lze také použít s HTML.“

Konkrétní Xpath můžete snadno najít pomocí vývojářských nástrojů Chrome. Jednoduše zkontrolujte konkrétní prvek HTML, zkopírujte cestu XPath a poté dolaďte (podle potřeby):

Nástroje pro vývojáře také umožňují testovat selektory XPath v konzole JavaScript pomocí $x – tj. $x("//img") :

Opět v podstatě říkáme Scrapymu, kde má začít hledat informace na základě definované XPath. Přejdeme na stránku Stack Overflow v prohlížeči Chrome a najdeme selektory XPath.

Klikněte pravým tlačítkem na první otázku a vyberte „Inspect Element“:

Nyní uchopte cestu XPath pro <div class="summary"> , //*[@id="question-summary-27624141"]/div[2] a poté jej otestujte v konzole JavaScript:

Jak můžete říci, vybere pouze to jeden otázka. Musíme tedy změnit cestu XPath tak, aby zachytila ​​vše otázky. Nějaké nápady? Je to jednoduché://div[@class="summary"]/h3 . Co to znamená? Tato cesta XPath v podstatě uvádí:Uchopte vše <h3> prvky, které jsou potomky <div> který má třídu summary . Otestujte tuto cestu XPath v konzole JavaScript.

Všimněte si, že nepoužíváme skutečný výstup XPath z Chrome Developer Tools. Ve většině případů je výstup jen užitečnou stranou, která vás obecně nasměruje správným směrem k nalezení funkční XPath.

Nyní aktualizujme soubor stack_spider.py skript:

from scrapy import Spider
from scrapy.selector import Selector


class StackSpider(Spider):
    name = "stack"
    allowed_domains = ["stackoverflow.com"]
    start_urls = [
        "http://stackoverflow.com/questions?pagesize=50&sort=newest",
    ]

    def parse(self, response):
        questions = Selector(response).xpath('//div[@class="summary"]/h3')


Extrahujte data

Stále potřebujeme analyzovat a seškrábat požadovaná data, která spadají do <div class="summary"><h3> . Znovu aktualizujte stack_spider.py takhle:

from scrapy import Spider
from scrapy.selector import Selector

from stack.items import StackItem


class StackSpider(Spider):
    name = "stack"
    allowed_domains = ["stackoverflow.com"]
    start_urls = [
        "http://stackoverflow.com/questions?pagesize=50&sort=newest",
    ]

    def parse(self, response):
        questions = Selector(response).xpath('//div[@class="summary"]/h3')

        for question in questions:
            item = StackItem()
            item['title'] = question.xpath(
                'a[@class="question-hyperlink"]/text()').extract()[0]
            item['url'] = question.xpath(
                'a[@class="question-hyperlink"]/@href').extract()[0]
            yield item
````

We are iterating through the `questions` and assigning the `title` and `url` values from the scraped data. Be sure to test out the XPath selectors in the JavaScript Console within Chrome Developer Tools - e.g., `$x('//div[@class="summary"]/h3/a[@class="question-hyperlink"]/text()')` and `$x('//div[@class="summary"]/h3/a[@class="question-hyperlink"]/@href')`.

## Test

Ready for the first test? Simply run the following command within the "stack" directory:

```console
$ scrapy crawl stack

Spolu s trasováním zásobníku Scrapy by se mělo zobrazit 50 názvů otázek a adres URL. Výstup můžete vykreslit do souboru JSON pomocí tohoto malého příkazu:

$ scrapy crawl stack -o items.json -t json

Nyní jsme implementovali náš Spider na základě našich dat, která hledáme. Nyní musíme uložit seškrabovaná data do MongoDB.




Uložte data do MongoDB

Pokaždé, když se položka vrátí, chceme data ověřit a poté je přidat do kolekce Mongo.

Prvním krokem je vytvoření databáze, kterou plánujeme použít k uložení všech našich prolezených dat. Otevřete settings.py a zadejte kanál a přidejte nastavení databáze:

ITEM_PIPELINES = ['stack.pipelines.MongoDBPipeline', ]

MONGODB_SERVER = "localhost"
MONGODB_PORT = 27017
MONGODB_DB = "stackoverflow"
MONGODB_COLLECTION = "questions"

Správa potrubí

Nastavili jsme našeho pavouka, aby procházel a analyzoval HTML, a nastavili jsme nastavení naší databáze. Nyní je musíme propojit pomocí potrubí v pipelines.py .

Připojit k databázi

Nejprve definujme metodu skutečného připojení k databázi:

import pymongo

from scrapy.conf import settings


class MongoDBPipeline(object):

    def __init__(self):
        connection = pymongo.MongoClient(
            settings['MONGODB_SERVER'],
            settings['MONGODB_PORT']
        )
        db = connection[settings['MONGODB_DB']]
        self.collection = db[settings['MONGODB_COLLECTION']]

Zde vytvoříme třídu MongoDBPipeline() a máme funkci konstruktoru pro inicializaci třídy definováním nastavení Mongo a následným připojením k databázi.

Zpracování dat

Dále musíme definovat metodu zpracování analyzovaných dat:

import pymongo

from scrapy.conf import settings
from scrapy.exceptions import DropItem
from scrapy import log


class MongoDBPipeline(object):

    def __init__(self):
        connection = pymongo.MongoClient(
            settings['MONGODB_SERVER'],
            settings['MONGODB_PORT']
        )
        db = connection[settings['MONGODB_DB']]
        self.collection = db[settings['MONGODB_COLLECTION']]

    def process_item(self, item, spider):
        valid = True
        for data in item:
            if not data:
                valid = False
                raise DropItem("Missing {0}!".format(data))
        if valid:
            self.collection.insert(dict(item))
            log.msg("Question added to MongoDB database!",
                    level=log.DEBUG, spider=spider)
        return item

Navážeme spojení s databází, rozbalíme data a poté je uložíme do databáze. Nyní můžeme testovat znovu!




Test

Znovu spusťte následující příkaz v adresáři „stack“:

$ scrapy crawl stack

POZNÁMKA :Ujistěte se, že máte démona Mongo - mongod - běžící v jiném okně terminálu.

Hurá! Naše procházená data jsme úspěšně uložili do databáze:



Závěr

Toto je docela jednoduchý příklad použití Scrapy k procházení a škrábání webové stránky. Skutečný projekt na volné noze vyžadoval, aby skript sledoval odkazy na stránkování a seškrábal každou stránku pomocí CrawlSpider (docs), který se velmi snadno implementuje. Zkuste to implementovat sami a zanechte níže komentář s odkazem na úložiště Github pro rychlou kontrolu kódu.

Potřebovat pomoc? Začněte s tímto skriptem, který je téměř hotový. Pak si prohlédněte část 2, kde najdete úplné řešení!

Box zdarma: Klikněte sem a stáhněte si kostru projektu Python + MongoDB s úplným zdrojovým kódem, který vám ukáže, jak přistupovat k MongoDB z Pythonu.

Celý zdrojový kód si můžete stáhnout z úložiště Github. Komentář níže s dotazy. Děkujeme za přečtení!



  1. Jedinečný index Mongoose na vnořeném dokumentu

  2. Proč lua skript blokuje redis-server?

  3. nakonfigurujte redis auth na sidekiq

  4. Jak připojit mongodb klienty k místnímu Meteor MongoDB