Использование Item Pipeline с использованием платформы Scrapy

MySQL рептилия MongoDB Scrapy

Item Pipeline — это конвейер элементов, и в этом разделе мы подробно узнаем о его использовании.

Во-первых, давайте посмотрим на архитектуру Item Pipeline в Scrapy, как показано на следующем рисунке.

Крайняя левая часть рисунка — это Конвейер Предметов, который вызывается после того, как Паук сгенерирует Предмет. После того, как Spider проанализирует ответ, элемент будет передан в конвейер элементов, и определенные компоненты конвейера элементов будут вызываться последовательно для выполнения ряда процедур обработки, таких как очистка и хранение данных.

Основные функции Item Pipeline следующие:

  • Очистите HTML-данные.

  • Подтвердите просканированные данные и проверьте просканированные поля.

  • Проверяйте наличие дубликатов и удаляйте дубликаты.

  • Сохраните результаты сканирования в базе данных.

Один, основной метод

Мы можем настроить конвейер элементов, нужно только реализовать указанный метод, метод, который должен быть достигнут:process_item(item, spider).

Кроме того, есть еще несколько практических методов, а именно:

  • open_spider(spider).

  • close_spider(spider).

  • from_crawler(cls, crawler).

Ниже мы подробно опишем использование этих методов.

1. process_item(item, spider)

process_item()Это метод, который должен быть реализован.Определенный Item Pipeline будет вызывать этот метод по умолчанию для обработки Item. Например, мы можем выполнять такие операции, как обработка данных или запись данных в базу данных. он должен вернутьсяItemзначение типа или выдаетDropItemаномальный.

process_item()Параметры метода следующие.

  • item, является объектом Item, то есть обрабатываемым Item.

  • spider, является объектом Spider, то есть Spider, сгенерировавшим Item.

process_item()Типы возвращаемых данных методов резюмируются следующим образом.

  • Если он возвращает объект Item, этот элемент будет конвейером элементов с низким приоритетом.process_item()Обработка методов до тех пор, пока не будут вызваны все методы.

  • Если он выдает исключение DropItem, элемент будет отброшен и не будет обработан.

2. open_spider(self, spider)

open_spider()Метод вызывается автоматически при запуске паука. Здесь мы можем выполнить некоторые операции инициализации, такие как открытие соединения с базой данных. Среди них параметрspiderОткрывается объект Spider.

3. close_spider(spider)

close_spider()Метод вызывается автоматически при закрытии паука. Здесь мы можем сделать некоторые последние штрихи, такие как закрытие соединений с базой данных и т. д. Среди них параметрspiderЭто объект Spider, который закрыт.

4. from_crawler(cls, crawler)

from_crawler()Метод представляет собой метод класса, с@classmethodIdentity — это способ внедрения зависимостей. Его параметрыcrawler,пройти черезcrawlerобъект, мы можем получить все основные компоненты Scrapy, такие как каждая информация о глобальной конфигурации, а затем создать экземпляр Pipeline. параметрclsЯвляется классом и, наконец, возвращает экземпляр класса.

Давайте воспользуемся примером, чтобы углубить наше понимание использования Item Pipeline.

2. Задачи этого раздела

Давайте возьмем сканирование 360 фотографий в качестве примера для реализации трех конвейеров хранилища MongoDB, хранилища MySQL и хранилища изображений.

3. Подготовка

Убедитесь, что установлены базы данных MongoDB и MySQL, а также установлены платформы Python PyMongo, PyMySQL и Scrapy.

В-четвертых, анализ захвата

Целевой веб-сайт, который мы сканируем на этот раз: https://image.so.com. Откройте эту страницу и перейдите на страницу фотографии, где много красивых фотографий. Мы открываем инструменты разработчика браузера, переключаем фильтр на параметр XHR, а затем опускаем страницу. Мы видим, что многие запросы Ajax будут отображаться ниже, как показано на следующем рисунке.

Мы смотрим на детали запроса и наблюдаем за возвращаемой структурой данных, как показано на следующем рисунке.

Формат возврата — JSON. вlistПоле представляет собой подробную информацию о каждом изображении, включая идентификатор, имя, ссылку, миниатюру и другую информацию о 30 изображениях. Кроме того, обратите внимание на информацию о параметрах запроса Ajax, есть параметрsnОн все время меняется, и этот параметр, очевидно, является смещением. когдаsnКогда sn равно 30, возвращаются первые 30 изображений, а когда sn равно 60, возвращаются изображения с 31-го по 60-е. Кроме того,chПараметр - категория фотографии,listtypeметод сортировки,tempПараметры можно игнорировать.

Поэтому нам нужно только изменитьsnзначение в порядке.

Ниже мы используем SCRAPY для реализации захвата изображения, сохранить информацию о изображении на MongoDB, MySQL и хранить изображение локально.

5. Новые проекты

Сначала создайте новый проект с помощью следующей команды:

scrapy startproject images360

Далее создаем нового Паука, команда следующая:

scrapy genspider images images.so.com

Итак, мы успешно создали Паука.

6. Сформируйте запрос

Затем определите количество страниц для обхода. Например, чтобы просканировать 50 страниц и 30 страниц на страницу, то есть 1500 изображений, мы можем сначала определить переменную в settings.py.MAX_PAGEДобавьте следующее определение:

MAX_PAGE = 50

определениеstart_requests()метод, используемый для генерации 50 запросов, следующим образом:

def start_requests(self):
    data = {'ch': 'photography', 'listtype': 'new'}
    base_url = 'https://image.so.com/zj?'
    for page in range(1, self.settings.get('MAX_PAGE') + 1):
        data['sn'] = page * 30
        params = urlencode(data)
        url = base_url + params
        yield Request(url, self.parse)

Здесь мы сначала определяем начальные два параметра,snПараметры генерируются путем обхода цикла. затем используйтеurlencode()метод преобразования словаря в URLGETПараметры, построить полный URL, построить и генерировать запрос.

Также необходимо ввести модули SCRAPY.REQUEST и URLLIB.PARSE следующим образом:

from scrapy import Spider, Request
from urllib.parse import urlencode

Затем измените settings.py вROBOTSTXT_OBEYпеременная, установите ее вFalse, в противном случае он не может быть просканирован следующим образом:

ROBOTSTXT_OBEY = False

Запустив краулер, вы увидите, что ссылки успешно запрошены, а команда выполнения выглядит следующим образом:

scrapy crawl images

Результат выполнения примера показан на следующем рисунке.

Код состояния всех запросов — 200, что свидетельствует об успешном сканировании информации об изображении.

Семь, для извлечения информации

Сначала определите Item, называемыйImageItem,Следующее:

from scrapy import Item, Field
class ImageItem(Item):
    collection = table = 'images'
    id = Field()
    url = Field()
    title = Field()
    thumb = Field()

Здесь мы определяем четыре поля, включая идентификатор изображения, ссылку, заголовок и миниатюру. Также есть два свойстваcollectionиtable, определяются как строки изображений, представляющие имя коллекции, хранящееся в MongoDB, и имя таблицы, хранящееся в MySQL, соответственно.

Далее мы извлекаем соответствующую информацию в Пауке, и мыparse()Метод перезаписи заключается в следующем:

def parse(self, response):
    result = json.loads(response.text)
    for image in result.get('list'):
        item = ImageItem()
        item['id'] = image.get('imageid')
        item['url'] = image.get('qhimg_url')
        item['title'] = image.get('group_title')
        item['thumb'] = image.get('qhimg_thumb_url')
        yield item

Сначала проанализируйте JSON, просмотрите его поле списка, извлеките информацию об изображении одно за другим, а затемImageItemНазначение для создания объекта Item.

На этом извлечение информации завершено.

8. Информация о хранении

Далее нам нужно сохранить информацию об изображении в MongoDB, MySQL и сохранить изображение локально.

MongoDB

Сначала убедитесь, что MongoDB установлен и работает правильно.

Мы используем MongoPipeline для сохранения информации в MongoDB и добавляем реализацию следующих классов в pipens.py:

import pymongo

class MongoPipeline(object):
    def __init__(self, mongo_uri, mongo_db):
        self.mongo_uri = mongo_uri
        self.mongo_db = mongo_db

    @classmethod
    def from_crawler(cls, crawler):
        return cls(
            mongo_uri=crawler.settings.get('MONGO_URI'),
            mongo_db=crawler.settings.get('MONGO_DB')
        )

    def open_spider(self, spider):
        self.client = pymongo.MongoClient(self.mongo_uri)
        self.db = self.client[self.mongo_db]

    def process_item(self, item, spider):
        self.db[item.collection].insert(dict(item))
        return item

    def close_spider(self, spider):
        self.client.close()

Здесь используются две переменные,MONGO_URIиMONGO_DB, то есть адрес ссылки и имя базы данных, хранящиеся в MongoDB. Мы добавляем эти две переменные в settings.py следующим образом:

MONGO_URI = 'localhost'
MONGO_DB = 'images360'

Такой конвейер, сохраненный в MongoDB, создается. Основным методом здесь являетсяprocess_item()метод, который напрямую вызывает метод объекта Collection.insert()Метод может завершить вставку данных и, наконец, вернуть объект Item.

MySQL

Сначала убедитесь, что MySQL правильно установлен и работает.

Создайте новую базу данных, имя по-прежнему images360, и оператор SQL выглядит следующим образом:

CREATE DATABASE images360 DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci

Создайте новую таблицу данных с четырьмя полями: id, url, title и thumb.Выражение SQL выглядит следующим образом:

CREATE TABLE images (id VARCHAR(255) NULL PRIMARY KEY, url VARCHAR(255) NULL , title VARCHAR(255) NULL , thumb VARCHAR(255) NULL)

После выполнения оператора SQL мы успешно создали таблицу данных. Затем вы можете сохранить данные в таблице.

Далее мы реализуемMySQLPipeline, код выглядит так:

import pymysql

class MysqlPipeline():
    def __init__(self, host, database, user, password, port):
        self.host = host
        self.database = database
        self.user = user
        self.password = password
        self.port = port

    @classmethod
    def from_crawler(cls, crawler):
        return cls(
            host=crawler.settings.get('MYSQL_HOST'),
            database=crawler.settings.get('MYSQL_DATABASE'),
            user=crawler.settings.get('MYSQL_USER'),
            password=crawler.settings.get('MYSQL_PASSWORD'),
            port=crawler.settings.get('MYSQL_PORT'),
        )

    def open_spider(self, spider):
        self.db = pymysql.connect(self.host, self.user, self.password, self.database, charset='utf8', port=self.port)
        self.cursor = self.db.cursor()

    def close_spider(self, spider):
        self.db.close()

    def process_item(self, item, spider):
        data = dict(item)
        keys = ', '.join(data.keys())
        values = ', '.join(['%s'] * len(data))
        sql = 'insert into %s (%s) values (%s)' % (item.table, keys, values)
        self.cursor.execute(sql, tuple(data.values()))
        self.db.commit()
        return item

Как упоминалось ранее, используемый здесь метод вставки данных представляет собой метод динамического построения операторов SQL.

Здесь нам понадобится еще несколько конфигураций MySQL.Добавим несколько переменных в settings.py следующим образом:

MYSQL_HOST = 'localhost'
MYSQL_DATABASE = 'images360'
MYSQL_PORT = 3306
MYSQL_USER = 'root'
MYSQL_PASSWORD = '123456'

Здесь определяются адрес MySQL, имя базы данных, порт, имя пользователя и пароль.

Таким образом, конвейер MySQL завершен.

Image Pipeline

Scrapy предоставляет конвейер, предназначенный для обработки загрузок, включая загрузку файлов и загрузку изображений. Принцип загрузки файлов и изображений такой же, как и при сканировании страниц, поэтому процесс загрузки поддерживает асинхронность и многопоточность, а загрузка очень эффективна. Рассмотрим конкретный процесс реализации.

Официальный адрес документа: https://doc.scrapy.org/en/latest/topics/media-pipeline.html.

Сначала определите путь к файлу хранилища, вам нужно определитьIMAGES_STOREдобавьте следующий код в settings.py:

IMAGES_STORE = './images'

Здесь мы определяем путь как подпапку с изображениями по текущему пути, то есть загруженные изображения будут сохранены в папку с изображениями этого проекта.

ВстроенныйImagesPipelineЭлемент будет прочитан по умолчаниюimage_urlsполе и считает это поле списком, он проходит через элементimage_urlsполе, а затем выньте каждый URL для загрузки изображения.

Но поле ссылки на изображение сгенерированного элемента неimage_urlsПоле представлено не в виде списка, а в виде одного URL-адреса. Итак, чтобы реализовать загрузку, нам нужно переопределить загруженную частичную логику, то есть настроитьImagePipelineНаследование встроенногоImagesPipeline, переопределяя несколько методов.

мы определяемImagePipeline,Следующее:

from scrapy import Request
from scrapy.exceptions import DropItem
from scrapy.pipelines.images import ImagesPipeline

class ImagePipeline(ImagesPipeline):
    def file_path(self, request, response=None, info=None):
        url = request.url
        file_name = url.split('/')[-1]
        return file_name

    def item_completed(self, results, item, info):
        image_paths = [x['path'] for ok, x in results if ok]
        if not image_paths:
            raise DropItem('Image Downloaded Failed')
        return item

    def get_media_requests(self, item, info):
        yield Request(item['url'])

Здесь мы достигаемImagePipeline, наследуя встроенный в ScrapyImagesPipeline, переопределите следующие методы.

  • get_media_requests(). его первый параметрitemЭто объект Item, созданный при сканировании. мы это сделаемurlПоле вынимается, а затем непосредственно генерируется объект Запрос. Этот запрос добавляется в очередь планирования, ожидая запланированного выполнения загрузки.

  • file_path(). его первый параметрrequestЭто объект запроса, соответствующий текущей загрузке. Этот метод используется для возврата сохраненного имени файла, а последняя часть ссылки на изображение может быть непосредственно использована в качестве имени файла. он используетsplit()Функция разбивает ссылку и извлекает последнюю часть, возвращая результат. Таким образом, имя, сохраненное после загрузки изображения, является именем файла, возвращаемым функцией.

  • item_completed(), который является методом обработки после завершения загрузки одного элемента. Поскольку не каждое изображение будет успешно загружено, нам необходимо проанализировать результаты загрузки и удалить изображения, которые не удалось загрузить. Если изображение не загружается, то нам не нужно сохранять этот элемент в базе данных. Первый параметр методаresultsЭто результат загрузки, соответствующий Item, который представлен в виде списка, и каждый элемент списка представляет собой кортеж, который содержит информацию об успехе или неудаче загрузки. Здесь мы перебираем результаты загрузки, чтобы найти все списки успешных загрузок. Если список пуст, изображение, соответствующее элементу, не может быть загружено, возникает исключение DropItem, и элемент игнорируется. В противном случае возвращается Item, указывающий, что Item допустим.

На данный момент определения трех конвейеров элементов завершены. Наконец, вам нужно только включить его, изменить settings.py, установитьITEM_PIPELINES,Следующее:

ITEM_PIPELINES = {
    'images360.pipelines.ImagePipeline': 300,
    'images360.pipelines.MongoPipeline': 301,
    'images360.pipelines.MysqlPipeline': 302,
}

Обратите внимание на порядок вызовов здесь. Нам нужно сначала позвонитьImagePipelineЭлементы фильтруются после загрузки. Элементы, которые не удалось загрузить, будут напрямую игнорироваться и не будут сохранены в MongoDB и MySQL. Затем вызовите два других сохраненных конвейера, чтобы обеспечить успешную загрузку изображений, хранящихся в базе данных.

Затем запустите программу для выполнения сканирования следующим образом:

scrapy crawl images

Искатель загружается во время сканирования, и скорость загрузки очень высока. Соответствующий выходной журнал показан на следующем рисунке.

Проверьте папку «Локальные изображения» и найдите, что изображения были успешно загружены, как показано на следующем рисунке.

Проверьте MySQL, информация о загруженном изображении также была успешно сохранена, как показано на следующем рисунке.

При просмотре MongoDB информация о загруженном изображении также была успешно сохранена, как показано на следующем рисунке.

Таким образом, мы можем успешно загрузить изображение и сохранить информацию о нем в базе данных.

Девять, этот код раздела

Кодовый адрес этого раздела: https://github.com/Python3WebSpider/Images360.

Х. Заключение

Item Pipeline является очень важным компонентом Scrapy, почти все данные, хранящиеся в этом компоненте, достигаются. Читатели внимательно воспринимают это содержание.


Этот ресурс был впервые опубликован в личном блоге Цуй Цинцай Цзин Ми:Практическое руководство по разработке веб-краулера на Python3 | Цзин Ми

Если вы хотите узнать больше информации о поисковых роботах, обратите внимание на мой личный публичный аккаунт WeChat: Coder of Attack.

WeChat.QQ.com/Day/5 Это радость VE Z…(автоматическое распознавание QR-кода)