предисловие
ScrapyЭто фреймворк сканера, реализованный на чистом языке Python. Простота, удобство использования и высокая масштабируемость делают его основным инструментом в сканере Python. В этой статье используется последняя официальная версия.1.6Исходя из этого, ведется дискуссия от простого использования к углубленному принципу.
Заранее скажу, что туториал есть туториал, в конце концов, нет соответствующего официального документа! Если читатель заинтересуется Scrapy после прочтения этой статьи и намерен узнать больше о Scrapy, пожалуйста, выработайте привычку читать официальную документацию в любое время!
Официальная документация Scrapy
содержание
В этой статье в основном описывается следующее содержание
- Почему выбирают Scrapy?
- Привет Скрапи! (упражняться)
- Как работает Скрейпи?
Что касается первого подраздела «Почему выбирают Scrapy», я предлагаю читателям прочитать его, и я проанализирую свое понимание бизнес-сценариев Scrapy.
Что касается оставшихся двух подразделов, мое первоначальное намерение состояло в том, чтобы поместить «Как работает Scrapy» перед «Hello Scrapy», но, учитывая, что не все хотят сразу понимать теоретические вещи, я сначала поставлю практическую небольшую демонстрацию впереди, надеясь пробудить интерес читателей, а интерес может дать нам более глубокое понимание одной вещи. Поэтому я поместил раздел «Как работает Scrapy» в конец, и я также могу следовать принципу Scrapy в следующей главе!
Почему выбирают Scrapy?
Хотя Scrapy был разработан для выполнения подавляющего большинства задач сканера, все же есть некоторые сценарии, в которых он неприменим.
- Когда Scrapy не предпочтительнее?
-
Scrapy — не лучший выбор, когда вы сканируете небольшое количество страниц и ориентируетесь на небольшой сайт. Например, для сканирования некоторых списков фильмов, некоторой новостной информации и т. д. Requests + PyQuery очень хорошо справляется с такими задачами.И Requests, и PyQuery лучше, чем два модуля, поставляемые со Scrapy!
-
Когда нет общих требований к сканеру, Scrapy не является обязательным. На мой взгляд, реальное преимущество Scrapy заключается в том, что он может настраивать соответствующие «действия паука» для разных типов веб-сайтов.Мощный «ItemLoader» может определять ряд действий обработки для ввода и вывода данных. Если у вас нет необходимости постоянно расширять источник информации, Scrapy фактически не сможет проявить свои максимальные возможности!
-
Scrapy бессилен, когда вам нужно постепенно очищать данные. Scrapy не имеет функции инкрементного сканирования, потому что сложность инкрементов разная.Если на Scrapy просто выполнять незначительные операции, это можно оценить, но если инкрементальные требования высоки, для Scrapy может быть очень проблематично двигаться. !
Примечание. Приведенные выше три случая просто хотят показать, что Scrapy — не лучший выбор, и это не говорит о том, что это не рекомендуется! Я просто надеюсь, что читатели могут понять, что при выборе фреймворка или технологии не следует следовать тренду.Это очень полезно для хорошего развития проекта, тщательно продумать его в начале дизайна.
- Когда полезен Scrapy?
-
Scrapy-redis, неофициальный компонент Scrapy, полезен, когда требуется распределенный дизайн. Сам по себе Scrapy не может реализовать распределенный механизм, но использует rmax для разработкиScrapy-redisЕго можно распространять, и я расскажу об этом позже.
-
Когда есть потребность в масштабируемости, Scrapy — мощный инструмент. Конкретные причины были объяснены выше и не будут объясняться здесь.
Примечание. Все вышеперечисленные ситуации взяты из моего личного обзора использования Scrapy, только для справки!
Hello Scrapy
Демонстрация использует популярные рейтинги фильмов Douban (Victims of Eternal Reptiles) и все его комментарии в качестве экспериментальной цели и описывает основные функции Scrapy одну за другой. Я полагаю, что читатели смогут хорошо использовать Scrapy после практики этой демонстрации. .
Необходимо установить:
- python (в этой статье используется 3.7)
- scrapy
Среда установки
- Установить Скраппи
введите в командной строкеpip install scrapy
Создать Scrapy-проект
Введите в командной строкеscrapy startproject douban_demo
, результат показан на следующем рисунке
Позже вы можете увидеть, что Scrapy также предлагает нам использоватьgenspider
Эта команда создает наш файл краулера.Перед этим давайте посмотрим, что произошло после выполнения команды.
Просмотр каталога файлов. Мы видим следующую информацию
douban_demo
├── douban_demo
│ ├── items.py # 数据模型文件
│ ├── middlewares.py # 中间件文件,配置所有中间件
│ ├── pipelines.py # 管道文件,用于处理数据输出
│ ├── settings.py # douban_demo 的配置文件
│ └── spiders # Spider类文件夹,所有的Spider均在此存放
└── scrapy.cfg # 整个Scrapy的配置文件,由Scrapy自动生成
Получив общее представление о назначении каждого файла, давайте начнем наше путешествие по сканеру.
описать сканер
использоватьscrapy genspider douban douban.com
Чтобы создать новый файл искателя, этот новый файл искателя будет помещен вdouban_demo/spiders
под.
PS:genspider
использованиеscrapy genspider [options] <name> <domain>
В настоящее времяdouban.py
файл появится вspiders
Ниже исходное содержание выглядит следующим образом:
# -*- coding: utf-8 -*-
import scrapy
class DoubanSpider(scrapy.Spider):
name = 'douban' # 爬虫名称
allowed_domains = ['douban.com'] # 允许爬取的域名列表
start_urls = ['http://douban.com/'] # 开始爬取的资源链接列表
def parse(self, response): # 解析数据方法
pass
Все ваши классы Spider в проекте Scrapy должны наследоватьscrapy.Spider
,вname
,start_urls
а такжеparse
Методы-члены должны быть объявлены в каждом классе Spider. Можно использовать дополнительные свойства Spider и методы-члены.нажмите на эту ссылку
Затем просто поместите ссылку на наш объект сканирования вstart_urls
внутри мы можем использоватьhttps://movie.douban.com/chart
для экспериментального объекта.
будетDoubanSpider
серединаstart_urls
Значение заменяется наstart_urls = ['https://movie.douban.com/chart']
Используйте метод оболочки для тестирования страницы
Scrapy также дает намshell
порядок для насshell
Тест извлечения данных страницы выполняется в методе, более эффективном, чем метод request+pyquery.
Формат команды:scrapy shell urls
Введите в командной строкеscrapy shell
Входитьshell
модель.
Примечание. Не спешите добавлять URL-адреса в это время, потому что наш тестовый объект обнаружил UA, и 403 появится, если вы напрямую введете тестовую ссылку. Нет конкретных ограничений на каталог, в который следует вводить эту команду.
Результат выглядит следующим образом:
(venv) ➜ douban_demo scrapy shell --nolog
[s] Available Scrapy objects:
[s] scrapy scrapy module (contains scrapy.Request, scrapy.Selector, etc)
[s] crawler <scrapy.crawler.Crawler object at 0x106c5c550>
[s] item {}
[s] settings <scrapy.settings.Settings object at 0x108e18898>
[s] Useful shortcuts:
[s] fetch(url[, redirect=True]) Fetch URL and update local objects (by default, redirects are followed)
[s] fetch(req) Fetch a scrapy.Request and update local objects
[s] shelp() Shell help (print this help)
[s] view(response) View response in a browser
На данный момент мы видим, что мы вошли в интерфейс, похожий на интерактор командной строки Python, Прежде всего, чтобы предотвратить Douban 403, мы должныsettings
добавить внутрьDEFAULT_REQUEST_HEADERS
атрибут, это словарь заголовка запроса, пока Scrapy обнаружит этот параметр, он добавит его значение в заголовок запроса.
Значения следующие:
DEFAULT_REQUEST_HEADERS = {
'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
'Accept-Language': 'en',
'user-agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_5) AppleWebKit/537.36 \
(KHTML, like Gecko) Chrome/74.0.3729.169 Safari/537.36'
}
Добавьте заголовки запроса по умолчанию, введя в интерактивном интерфейсе
>>> settings.DEFAULT_REQUEST_HEADERS = {
... 'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
... 'Accept-Language': 'en',
... 'user-agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_5) AppleWebKit/537.36 \
... (KHTML, like Gecko) Chrome/74.0.3729.169 Safari/537.36'
... }
повторно войтиsettings.DEFAULT_REQUEST_HEADERS
Проверьте, успешно ли добавлено.
После завершения настройки мы можем использоватьfetch(urls)
команда для сканирования страницы, которую нам нужно протестировать
типfetch('https://movie.douban.com/chart')
чтобы увидеть содержимое
2019-06-03 23:06:13 [scrapy.core.engine] INFO: Spider opened
2019-06-03 23:06:13 [scrapy.core.engine] DEBUG: Crawled (200) <GET https://movie.douban.com/robots.txt> (referer: None)
2019-06-03 23:06:14 [scrapy.core.engine] DEBUG: Crawled (200) <GET https://movie.douban.com/chart> (referer: None)
Из журнала мы видим, что целевая страница была успешно получена.Перед получением страницы мы также можем знать, что сначала к ней обратился scrapy.robots.txt
файл, это хорошая привычка сканера, и все извлечения страниц с помощью скрапинга будут следоватьrobots.txt
внутри правил, если вы не хотите следовать этому правилу, вы можетеsettings
конфигурацияROBOTSTXT_OBEY = False
.
В этот момент вы можете использоватьresponse.text
чтобы проверить, получили ли мы исходный код для всей страницы.
Все операции парсинга ресурсов в scrapy интегрированы вresponse
В этом объекте болееresponse
Введение можетнажмите на эту ссылку
Страница анализа
Страница рейтинга фильмов
Проверка элемента на странице
Вы можете видеть, что контент, который нам нужно просканировать, находится вtable
в. потому что на странице несколькоtable
, поэтому вам нужно только перебрать его.
существуетshell
используется вresponse.css('table')
получить всеtable
элементы, все из которых используются в этой статьеcss selector
сделать выбор элемента,xpath
Вы также можете переключиться самостоятельно.
Информация о каждом фильме находится вtable
под этикеткойtr.item
в.
Ссылку на детали фильма можно использоватьa.nbg::attr(href)
получить
Фотографии фильмов, которые мы можем использоватьa.nbg > img::attr(src)
получить
Обработка названий фильмов немного сложнее.Из приведенного выше рисунка видно, что у фильмов может быть несколько имен, все из которых заключены вdiv.pl2 > a
внизу, где другие имена вdiv.pl2 > a > span
Ниже, поэтому нам нужно сделать некоторое форматирование имени, например, убрать пробелы, новые строки и т. д.
Так что название фильма можно использоватьdiv.pl2 > a::text
иdiv.pl2 > a > span::text
получается отдельно, но таким образомdiv.pl2
подa
Тегов много, нужно использовать только первыйextract_first()
метод удаления первогоSelector
содержимое элемента и преобразуется вstr
.
Синопсис фильма просто нужно использоватьp.pl::text
можно получить в
страница обзора фильма
Сращивание после ссылки на соответствующую информацию о фильмеcomments?status=P
Перейти на страницу обзора фильма.
Можно видеть, что данные обзора фильма состоят из несколькихcomment-item
композиция, содержание обзора фильма завернуто вdiv.comment
Следовательно, в соответствии с вышеуказанным методом анализа также может быть найден соответствующий метод сбора данных. здесь не раскрыто
Реализовать идеи
-
создать два
parse
метод:parse_rank
иparse_comments
,parse_rank
Отвечает за обработку страницы списка лидеров фильмов,parse_comments
Отвечает за обработку соответствующей страницы комментариев. -
переписать
Spider
Категорияstart_requests
метод, заполнитьurl
а такжеcallback
Значение атрибута, потому что вам нужно получить подробную информацию через страницу рейтинга фильмов, прежде чем вы сможете получить адрес комментария, который вы хотите, поэтому вstart_requests
вернулся вRequest callback
Свойства должны быть заполнены какself.parse_rank
-
существует
parse_rank
обработка возвращенаreponse
, следуйте идеям на «Странице анализа», чтобы анализировать данные и использоватьyield
Выкидывает страницу комментариевRequest
,callback
атрибут заполненself.parse_comments
-
существует
parse_comments
Метод обрабатывает возвращенную страницу комментариев, выдает данные и ссылки на следующую страницу.
Примечание:Spider parse
метод: всеparse
Все методы должны возвращать Item (в настоящее время понимается как элемент данных) или Requests (следующий запрос). все здесьparse
это значит конкретноSpider
генерируется в классеparse
метод, но все функции с возможностями синтаксического анализа должны возвращать Item или Requests.
пример кода
# -*- coding: utf-8 -*-
import scrapy
from scrapy.http.request import Request
class DoubanSpider(scrapy.Spider):
name = 'douban'
def start_requests(self):
yield Request(url='https://movie.douban.com/chart', callback=self.parse_rank)
def parse_rank(self, response):
for item in response.css('tr.item'):
detail_url = item.css('a.nbg::attr(href)').extract_first()
img_url = item.css('a.nbg > img::attr(src)').extract_first()
main_name = item.css('div.pl2 > a::text').extract_first()
other_name = item.css('div.pl2 > a > span::text').extract_first()
brief = item.css('p.pl::text').extract_first()
main_name = main_name.replace('\n', '').replace(' ', '')
yield {
'detail_url': detail_url,
'img_url': img_url,
'name': main_name+other_name,
'brief': brief
}
yield Request(url=detail_url+'comments?status=P',
callback=self.parse_comments,
meta={'movie': main_name})
def parse_comments(self, response):
for comments in response.css('.comment-item'):
username = comments.css('span.comment-info > a::text').extract_first()
comment = comments.css('span.short::text').extract_first()
yield {
'movie': response.meta['movie'],
'username': username,
'comment': comment
}
nexturl = response.css('a.next::attr(href)').extract_first()
if nexturl:
yield Request(url=response.url[:response.url.find('?')]+nexturl,
callback=self.parse_comments,
meta=response.meta)
Запустить поисковый робот
все готово, можноdouban_demo
Введите команду в (самом верхнем) каталогеscrapy crawl douban
Вы можете видеть, что есть много данных журнала, а также распечатать много информации о фильме и комментарии.
На данный момент мы завершили предварительное сканирование рейтинга фильмов и комментариев Douban. Конечно, Douban ограничивает количество комментариев, которые могут просматривать пользователи, не вошедшие в систему, и определяет поведение сканера. Мы поговорим об этих механизмах предотвращения сканирования в будущем.
Итак, теперь вопрос в том, как я должен сохранить данные?
Scrapy предоставляет множествоFeed exports
метод, вы можете сохранить выходные данные какjson, json lines, csv, xml
После стартовой команды добавить-o xx.json
Вы можете сохранить файл какjson
Формат.
как:scrapy crawl douban -o result.json
Так как данные содержат китайский контент, scrapy используетjson encoder
По умолчанию все данныеascii
, поэтому нам нужно установить кодировку данных наutf-8
.
только что вsettings.py
ПрисоединяйсяFEED_EXPORT_ENCODING = 'utf-8'
Вот и все.
В это время вы можете увидеть нормальное отображение китайского языка в этих данных.
В это время будет сгенерировано около 2000 фрагментов данных.
резюме
На данный момент мы завершили предварительное сканирование фильмов и обзоров фильмов Douban. Хотя данные могут быть успешно просканированы, это дает людям ощущение, что «я только что написал код для анализа веб-страницы и ввел команду для запуска сканера, и в результате Scrapy может помочь. Я делаю все, от запросов веб-страницы до вывода данных», нам придется продолжить изучение, когда мы наберемscrapy crawl douban -o result.json
Что именно делает Scrapy после этой команды запуска.
Как работает Скрейпи?
Читатели, которые хотят познакомиться со Scrapy, пожалуйста, сохраните следующую картинку, эта картинка особенно важна для изучения Scrapy.
Согласно этому графическому анализу, когда мы печатаемscrapy crawl douban -o result.json
После этого Scrapy сделал следующее
-
Crawler
получилаcrawl
будет активирован после команды, активированнойname
заdouban
изSpider
, при созданииEngine
, в это время нашDoubanSpider
активирован. -
когда
DoubanSpider
После новостройки,Engine
обнаружитSpider
, что является нашей очередью запросовstart_urls
атрибут илиstart_requests
метод. Оба они должны быть итерируемыми объектами, поэтому понятно, что в нашем примере кодаstart_requests
метод зачем использоватьyield
бросать. Сгенерировано в это времяRequest
объект, всеRequest
объекты будут проходить первымиSpider Middlewares
Это промежуточное ПО, на данном этапе нам нужно понимать промежуточное ПО только как мост, нам не нужно вникать в то, что сейчас находится на мосту. -
Spider
произведеноRequest
объект будет проходитьEngine
Отправить вScheduler
В планировщике планировщик будетRequest
Присоединяйтесь к очереди запросов, как только это можно будет запланировать,Request
пройдетDownloader Middlewares
эти мосты достигаютDownloader
,Downloader
Доступ к указанному Интернет-ресурсу будет осуществляться в соответствии с запрошенным контентом, и этот процесс является асинхронным. -
когда
Downloader
завершить одинRequest
После выполнения задачи ресурс будет упакован вResponse
, который будет содержать исходныйRequest
информация, инкапсулированный парсер и т. д., в примере мы можем видеть вparse_rank
брошенный вRequest
несущийmeta
данные, послеmeta
продолжай экономитьparse_comments
изresponse
внутри. -
В это время все
Response
пройдет сноваDownloader Middlewares
эти мосты, а затемEngine
а такжеSpider Middlewares
вернуться к соответствующемуSpider
, и активирует соответствующийcallback
функция и, наконец, выполняет то, что мы написалиparse
код в методе. когдаparse
бросить сноваRequest
Когда объект будет возвращен, шаги (3-5) будут выполнены повторно. -
когда
Spider
При броске данных (Item) он будет проходить сноваSpider Middlewares
прибытьItem Pipeline
, но мы неItem Pipeline
указать какое-либо действие, чтобы он просто бросалItem
, тогда будетlogger
Захватите этот вывод, то есть мы можем видеть, что в консоли есть сгенерированные данные, так как мы использовали-o
инструкция, такexporter
будетitem
Вывод в соответствующем формате, и у нас есть указанныйresult.json
набор данных.
Суммировать
На данный момент мы закончили, как использовать Scrapy для написания простой программы-краулера и получили общее представление о рабочем процессе Scrapy.Далее мы рассмотрим другие компоненты Scrapy и то, как их использовать для взлома механизма защиты от сканирования. .
Если приведенная выше точка зрения неверна, добро пожаловать, Ячжэн!