написать впереди
Всем большое спасибо за ваши лайки и подписку. На самом деле, это мой первый раз
掘金
На написании статей. Потому что некоторое время назад я также начал понимать и выучить рептилии между случайным и обучающим временем узла не очень долго. Хотя сделали какой-то спина с проектом, но на самом деле, с точки зрения узла и рептилий я был новичком, эта статья в основном хотим поделиться с вами основным узлом и аспектами рептилий, мы хотим помочь, и мы хотим Чтобы обмениваться, учиться вместе, спасибо за вашу поддержку снова!
Да, я открыл свой личный Домашняя страница, в котором есть свои технические статьи, а также личные размышления, размышления и логи. Все будущие статьи будут обновляться здесь как можно скорее, а затем синхронизироваться с другими платформами. Есть друзья, которым это нравится, вы можете пойти по магазинам, еще раз спасибо за вашу поддержку!
1. Что такое рептилия
Веб-краулер(также известные как веб-пауки, веб-роботы, в
FOAF
Community, чаще называемое Web Chaser) — это программа или скрипт, автоматически сканирующий информацию из всемирной паутины по определенным правилам. Другими менее часто используемыми именами являются муравей, автоиндекс, эмулятор или червь.
Введение в поисковый робот WIKIPEDIA
Классификация рептилий
- Универсальный веб-сканер (полный веб-сканер)
ползающие предметы из некоторых
种子URL
Распространяется на всю сеть, в основном для сбора данных для поисковых систем порталов и крупных поставщиков веб-услуг.
- Веб-краулер Spotlight (тематический веб-краулер)
да
指选择性
Поисковые роботы, которые сканируют страницы, относящиеся к заранее определенным темам.
- Инкрементный веб-сканер
Относится к добавочным обновлениям и
只爬行新产生的或者已经发生变化网页
Это может гарантировать, что просканированные страницы в определенной степени являются как можно более новыми.
- Глубокий веб-краулер
Сканеры — это те, к которым можно получить доступ только после того, как пользователи введут ключевые слова для поиска или входа в систему.
深层网页信息
рептилия.
В-третьих, стратегия сканирования сканера
- Универсальный веб-сканер (полный веб-сканер)
стратегия поиска в глубину, стратегия поиска в ширину
- Веб-краулер Spotlight (тематический веб-краулер)
Стратегия сканирования на основе оценки контента (релевантность контента), стратегия сканирования на основе оценки структуры ссылок, стратегия сканирования на основе обучения с подкреплением (важность ссылок), стратегия сканирования на основе графа контекста (расстояние, граница между двумя узлами в теории графов) Веса)
- Инкрементный веб-сканер
Унифицированный метод обновления, индивидуальный метод обновления, метод обновления на основе классификации, метод обновления с адаптивной частотной модуляцией
- Глубокий веб-краулер
Наиболее важной частью процесса сканирования сканера Deep Web является заполнение форм, которое включает два типа: заполнение форм на основе знаний предметной области и заполнение форм на основе анализа структуры веб-страницы.
Поведение современных поисковых роботов обычно является результатом сочетания четырех стратегий:
Стратегия выбора: решить, какие страницы загружать;
Стратегия повторного посещения: решает, когда проверять страницу на наличие обновленных изменений;
Стратегия сбалансированной вежливости: указание, как избежать перегрузки сайта;
Параллельная стратегия: указать, как координировать действия для достижения эффекта распределенного сканирования;
В-четвертых, напишите простой процесс веб-гусеника
- Определите, что сканировать (веб-сайт/страница)
- Анализ содержимого страницы (целевые данные/структура DOM)
- Определение языков разработки, фреймворков, инструментов и т. д.
- кодирование, тестирование, парсинг данных
- оптимизация
Простой поисковик новостей Baidu
Определите, что сканировать (веб-сайт/страница)
Анализ содержимого страницы (целевые данные/структура DOM)
······
Определение языков разработки, фреймворков, инструментов и т. д.
node.js (express)
+SublimeText 3
Код, тест, сбор данных
coding ···
Let's start
Новый каталог проекта
1. Создайте каталог проекта в соответствующем каталоге диска.
baiduNews
(Каталог моего проекта:F:\web\baiduNews
)
Примечание. Потому что компьютер, который я использовал при написании этой статьи, действительно дерьмовый. Немного сложно установить WebStorm или VsCode для запуска проекта. Таким образом, следующие операции командной строки выполняются в окне командной строки DOS, которое поставляется с Window.
Инициализировать package.json
1. Введите корневой каталог проекта в командной строке DOS.
baiduNews
2. Выполнитьnpm init
, инициализацияpackage.json
документ
Установить зависимости
express
(Используйте экспресс для создания простого Http-сервера. Конечно, вы также можете использовать тот, который поставляется с узломhttp
модуль)
superagent
(superagent — очень удобный, легкий и прогрессивный сторонний прокси-модуль запроса клиента в узле, который используется для запроса целевых страниц)
cheerio
(cheerio эквивалентен версии jQuery для узла, студентам, которые использовали jQuery, будет очень легко начать работу. В основном он используется для получения захваченных элементов страницы и информации о данных в них)
// 个人比较喜欢使用yarn来安装依赖包,当然你也可以使用 npm install 来安装依赖,看个人习惯。
yarn add express
yarn add superagent
yarn add cheerio
После установки зависимостей вы можете проверить, были ли успешно установлены только что установленные зависимости в package.json.
После правильной установки картина следующая:
начать кодирование
1. Используйтеexpress
Запустите простой локальный HTTP-сервер
1. Создать в корневом каталоге проектаindex.js
файл (кодирование будет выполнено позже в этом индексном файле)
2. Созданindex.js
, мы сначала создаем экземплярexpress
объект, который используется для запуска локального слушателя3000
Порт службы HTTP.
const express = require('express');
const app = express();
// ...
let server = app.listen(3000, function () {
let host = server.address().address;
let port = server.address().port;
console.log('Your App is running at http://%s:%s', host, port);
});
Да, это так просто, менее 10 строк кода, построить и запустить простую локальную службу Http.
3. Согласно международной практике, мы надеемся посетить местный адресhttp://localhost:3000
, эта услуга может дать нам фолHello World!
существуетindex.js
Добавьте следующий код в:
app.get('/', function (req, res) {
res.send('Hello World!');
});
На данный момент корневой каталог проекта в DOS
baiduNews
выполнять подnode index.js
, пусть проект работает. После этого откройте браузер и посетитеhttp://localhost:3000
, вы увидите слова «Hello World!», отображаемые на странице.
Таким образом, после того, как мы получим информацию на главной странице Baidu News, мы можем посетитьhttp://localhost:3000
см. эту информацию.
Во-вторых, сканирование новостной информации Baidu News
1. Во-первых, давайте проанализируем информацию о странице на главной странице Baidu News.
Домашняя страница новостей Baidu примерно разделена на «горячие новости», «местные новости», «внутренние новости», «международные новости» и т. д. На этот раз давайте сначала попробуем схватиться за левую сторону.
“热点新闻”
и ниже“本地新闻”
Новостные данные из двух мест.
F12
ОткрытьChrome
, просмотрите элементы страницы и посмотрите, где находится информация "Горячие новости" слева.DOM
Структура, мы обнаружили, что вся информация «горячих новостей» (включая заголовки новостей и ссылки на новостные страницы)id
для#pane-news
из<div
>ниже<ul>
Вниз<li>
вниз<a>
в этикетке. использоватьjQuery
Селектор представлен как:#pane-news ul li a
.
2. Чтобы сканировать данные новостей, сначала мы используем суперагент, чтобы запросить целевую страницу и получить всю информацию о домашней странице новостей.
// 引入所需要的第三方包
const superagent= require('superagent');
let hotNews = []; // 热点新闻
let localNews = []; // 本地新闻
/**
* index.js
* [description] - 使用superagent.get()方法来访问百度新闻首页
*/
superagent.get('http://news.baidu.com/').end((err, res) => {
if (err) {
// 如果访问失败或者出错,会这行这里
console.log(`热点新闻抓取失败 - ${err}`)
} else {
// 访问成功,请求http://news.baidu.com/页面所返回的数据会包含在res
// 抓取热点新闻数据
hotNews = getHotNews(res)
}
});
3. Получив информацию о странице, давайте определим функциюgetHotNews()
для сканирования данных «горячих новостей» на странице.
/**
* index.js
* [description] - 抓取热点新闻页面
*/
// 引入所需要的第三方包
const cheerio = require('cheerio');
let getHotNews = (res) => {
let hotNews = [];
// 访问成功,请求http://news.baidu.com/页面所返回的数据会包含在res.text中。
/* 使用cheerio模块的cherrio.load()方法,将HTMLdocument作为参数传入函数
以后就可以使用类似jQuery的$(selectior)的方式来获取页面元素
*/
let $ = cheerio.load(res.text);
// 找到目标数据所在的页面元素,获取数据
$('div#pane-news ul li a').each((idx, ele) => {
// cherrio中$('selector').each()用来遍历所有匹配到的DOM元素
// 参数idx是当前遍历的元素的索引,ele就是当前便利的DOM元素
let news = {
title: $(ele).text(), // 获取新闻标题
href: $(ele).attr('href') // 获取新闻网页链接
};
hotNews.push(news) // 存入最终结果数组
});
return hotNews
};
Еще несколько слов здесь:
async/await
Говорят, что это идеальное решение для асинхронного программирования, оно позволяет нам выполнять асинхронное программирование с синхронным мышлением.Promise
Это решает "ад обратных вызовов" асинхронного программирования. Async/await также делает управление асинхронным процессом удобным и понятным. Заинтересованные студенты могут узнать об этом. Это действительно полезно.superagent
Модуль предоставляет много вещей, таких какget
,post
,delte
и другие методы, вы можете легко выполнять операции запроса Ajax. Выполнить после завершения запроса.end()
Перезвоните..end()
Принимает в качестве параметра функцию, которая в свою очередь имеет два параметраerror和res
. Когда запрос не выполняется,error
Будет включать возвращенное сообщение об ошибке, запрос выполнен успешно,error
значениеnull
, возвращенные данные будут включены вres
в параметре.cheerio
модульный.load()
метод, будетHTML document
Передайте функцию в качестве параметра, а затем вы можете использовать метод, аналогичный $(selectior) jQuery, чтобы получить элемент страницы. Вы также можете использовать что-то вродеjQuery
середина.each()
для перебора элементов. Кроме того, есть много способов, которыми вы можете воспользоваться Google/Baidu самостоятельно.
4. Верните захваченные данные во внешний браузер.
Передний,
const app = express();
создал экземплярexpress
объектapp
.
app.get('', async() => {})
Примите два параметра, первый параметр принимает путь маршрутизации типа String, указывающий путь запроса Ajax. Второй параметр принимает функциональную функцию, которая будет выполнять код этой функции при запросе пути.
/**
* [description] - 跟路由
*/
// 当一个get请求 http://localhost:3000时,就会后面的async函数
app.get('/', async (req, res, next) => {
res.send(hotNews);
});
Корневой каталог проекта в DOS
baiduNews
выполнять подnode index.js
, пусть проект работает. После этого откройте браузер и посетитеhttp://localhost:3000
, вы обнаружите, что захваченные данные возвращаются на главную страницу. Возвращаемая информация, отображаемая браузером после запуска кода, выглядит следующим образом:
Примечание: потому что мойChrome
Установил расширение JSONView., поэтому возвращаемые данные будут автоматически форматироваться в структурированный формат JSON при отображении на странице, что удобно для просмотра.
OK! ! Таким образом, простой Baidu“热点新闻”
Рептилия готова! !
Подводя итог, шаги на самом деле очень просты:
express
начать простойHttp
Служить- Проанализируйте целевую страницу
DOM
структура, найти релевантную информацию для сканированияDOM
элемент- использовать
superagent
запросить целевую страницу- использовать
cheerio
Получить элемент страницы, получить целевые данные- Возврат данных во внешний браузер
Теперь, чтобы продолжить нашу цель, возьмите“本地新闻”
Данные (в процессе кодирования мы столкнемся с некоторыми интересными проблемами)
С предыдущим основанием мы, естественно, подумаем об использовании того же метода, что и выше, для данных «местных новостей».
1. Проанализируйте раздел «Местные новости» на странице.DOM
структура, как показано ниже:
F12
Откройте консоль и просмотрите «Местные новости».DOM
элемент, мы обнаружили, что «местные новости» разделены на два основных раздела: «новости слева» и «новости» справа. Все целевые данные находятся вid
для#local_news
изdiv
середина. Данные "левых новостей" снова вid
для#localnews-focus
изul
под этикеткойli
под этикеткойa
теги, включая заголовки новостей и ссылки на страницы. Данные "местной информации" снова вid
для#localnews-zixun
изdiv
внизul
под этикеткойli
под этикеткойa
теги, включая заголовки новостей и ссылки на страницы.
2. Хорошо! АнализыDOM
структура, которая определяет расположение данных, следующий и обход“热点新闻”
Таким же образом шаг за шагом определитеgetLocalNews()
Функция, сканирующая эти данные.
/**
* [description] - 抓取本地新闻页面
*/
let getLocalNews = (res) => {
let localNews = [];
let $ = cheerio.load(res);
// 本地新闻
$('ul#localnews-focus li a').each((idx, ele) => {
let news = {
title: $(ele).text(),
href: $(ele).attr('href'),
};
localNews.push(news)
});
// 本地资讯
$('div#localnews-zixun ul li a').each((index, item) => {
let news = {
title: $(item).text(),
href: $(item).attr('href')
};
localNews.push(news);
});
return localNews
};
соответственно, вsuperagent.get()
После запроса страницы нам нужно вызватьgetLocalNews()
функция сканирования данных местных новостей.
superagent.get()
Функция изменена на:
superagent.get('http://news.baidu.com/').end((err, res) => {
if (err) {
// 如果访问失败或者出错,会这行这里
console.log(`热点新闻抓取失败 - ${err}`)
} else {
// 访问成功,请求http://news.baidu.com/页面所返回的数据会包含在res
// 抓取热点新闻数据
hotNews = getHotNews(res)
localNews = getLocalNews(res)
}
});
В то же время мы будемapp.get()
Данные также должны быть возвращены во внешний браузер в маршрутизации.app.get()
Код маршрутизации изменен на:
/**
* [description] - 跟路由
*/
// 当一个get请求 http://localhost:3000时,就会后面的async函数
app.get('/', async (req, res, next) => {
res.send({
hotNews: hotNews,
localNews: localNews
});
});
Кодирование завершено, так взволнован! !
DOS
Запустите проект и получите к нему доступ через браузерhttp://localhost:3000
Произошла неприятная вещь! ! Возвращаемые данные — это только горячие новости, а местные новости возвращают пустой массив.[ ]
. Проверьте код и убедитесь, что проблем нет, но почему он продолжает возвращать пустой массив?
После недолгих поисков причины я выяснил, в чем проблема! !
интересный вопрос
Чтобы найти причину, сначала давайте посмотрим на
superagent.get('http://news.baidu.com/').end((err, res) => {})
Запросить домашнюю страницу новостей Baidu в функции обратного вызова.end()
Что именно вы получили во втором параметре res in ?
// 新定义一个全局变量 pageRes
let pageRes = {}; // supergaent页面返回值
// superagent.get()中将res存入pageRes
superagent.get('http://news.baidu.com/').end((err, res) => {
if (err) {
// 如果访问失败或者出错,会这行这里
console.log(`热点新闻抓取失败 - ${err}`)
} else {
// 访问成功,请求http://news.baidu.com/页面所返回的数据会包含在res
// 抓取热点新闻数据
// hotNews = getHotNews(res)
// localNews = getLocalNews(res)
pageRes = res
}
});
// 将pageRes返回给前端浏览器,便于查看
app.get('/', async (req, res, next) => {
res.send({
// {}hotNews: hotNews,
// localNews: localNews,
pageRes: pageRes
});
});
браузер доступа
http://localhost:3000
, на странице отображается следующее содержимое:
Как видите, в возвращаемом значении
text
Поле должно занимать всю страницуHTML
Строковый формат кода. Чтобы облегчить наше наблюдение, мы можем прямо положить этоtext
Значение поля возвращается внешнему браузеру, чтобы мы могли четко видеть страницу, отображаемую браузером.
Измените возвращаемое значение во внешний браузер.
app.get('/', async (req, res, next) => {
res.send(pageRes.text)
}
браузер доступаhttp://localhost:3000
, на странице отображается следующее содержимое:
После проверки элемента было обнаружено, что исходные просканированные нами целевые данные находились в
DOM
Элемент пустой, в нем нет данных!
Здесь все сводится к этому! в нашем использованииsuperagent.get()
При посещении главной страницы Baidu News,res
В полученном содержимом страницы, содержащемся в , нужные нам данные «местных новостей» еще не были сгенерированы,DOM
Элемент node пуст, поэтому возникает предыдущая ситуация! Данные, возвращаемые после захвата, всегда представляют собой пустой массив.[ ]
.
на консоли
Network
Мы обнаружили, что страница однажды запросила такой интерфейс:
http://localhost:3000/widget?id=LocalNews&ajax=json&t=1526295667917
, состояние интерфейса404
.
Это должны быть новости Baidu“本地新闻”
Интерфейс, тут все понятно! «Местные новости» получаются путем динамического запроса вышеуказанного интерфейса после загрузки страницы, поэтому мы используемsuperagent.get()
Когда запрошенная страница снова запрашивает этот интерфейс, интерфейсURL
серединаhostname
часть становится местнойIP
адрес, и этот интерфейс не существует на этой машине, поэтому404
, данные не запрашиваются.
Найдите причину, давайте найдем способ решить эту проблему! !
- Использовать напрямую
superagen
t Посетите правильный и законный Baidu“本地新闻”
Интерфейс после получения данных возвращает их во внешний браузер.- использовать третье лицо
npm
package, смоделируйте браузер для доступа к домашней странице новостей Baidu в этом смоделированном браузере“本地新闻”
После успешной загрузки возьмите данные и верните их во внешний браузер.
Вышеуказанные способы можно использовать, попробуем второй способ, более интересный
Использование инструмента автоматизированного тестирования Nightmare
Electron
позволяет использовать чистыйJavaScript
передачаChrome
Богатый собственный интерфейс для создания настольных приложений. Вы можете думать об этом как о настольном приложении, ориентированномNode.js
вариант , вместоWeb
сервер. Его метод приложения на основе браузера может быть очень удобным для выполнения различных интерактивных взаимодействий.
Nightmare
основывается наElectron
рамки дляWeb
Автоматизированные тесты и сканеры, так как они имеют следующиеPlantomJS
Та же функция автоматизированного тестирования может имитировать поведение пользователя на странице, чтобы инициировать асинхронную загрузку данных или отслеживатьRequest
прямой доступ к библиотекеURL
для очистки данных, и вы можете установить время задержки страницы, поэтому можно легко запустить сценарий вручную или поведение запускает сценарий.
Установить зависимости
// 安装nightmare
yarn add nightmare
Чтобы получать "местные новости", продолжайте писать код...
Датьindex.js
Добавьте следующий код в:
const Nightmare = require('nightmare'); // 自动化测试包,处理动态页面
const nightmare = Nightmare({ show: true }); // show:true 显示内置模拟浏览器
/**
* [description] - 抓取本地新闻页面
* [nremark] - 百度本地新闻在访问页面后加载js定位IP位置后获取对应新闻,
* 所以抓取本地新闻需要使用 nightmare 一类的自动化测试工具,
* 模拟浏览器环境访问页面,使js运行,生成动态页面再抓取
*/
// 抓取本地新闻页面
nightmare
.goto('http://news.baidu.com/')
.wait("div#local_news")
.evaluate(() => document.querySelector("div#local_news").innerHTML)
.then(htmlStr => {
// 获取本地新闻数据
localNews = getLocalNews(htmlStr)
})
.catch(error => {
console.log(`本地新闻抓取失败 - ${error}`);
})
ИсправлятьgetLocalNews()
Функция:
/**
* [description]- 获取本地新闻数据
*/
let getLocalNews = (htmlStr) => {
let localNews = [];
let $ = cheerio.load(htmlStr);
// 本地新闻
$('ul#localnews-focus li a').each((idx, ele) => {
let news = {
title: $(ele).text(),
href: $(ele).attr('href'),
};
localNews.push(news)
});
// 本地资讯
$('div#localnews-zixun ul li a').each((index, item) => {
let news = {
title: $(item).text(),
href: $(item).attr('href')
};
localNews.push(news);
});
return localNews
}
Исправлятьapp.get('/')
Маршрут:
/**
* [description] - 跟路由
*/
// 当一个get请求 http://localhost:3000时,就会后面的async函数
app.get('/', async (req, res, next) => {
res.send({
hotNews: hotNews,
localNews: localNews
})
});
В настоящее время,
DOS
Перезапустите проект из командной строки, доступ через браузерhttps://localhost:3000
, просмотрите информацию, отображаемую на странице, чтобы убедиться, что она просканирована“本地新闻”
данные!
На данный момент создан простой и полноценный краулер, который сканирует новостные страницы Baidu «горячие новости» и «местные новости»! !
Наконец, если подытожить, общая идея выглядит следующим образом:
express
начать простойHttp
Служить- Проанализируйте целевую страницу
DOM
структура, найти релевантную информацию для сканированияDOM元
белый- использовать
superagent
запросить целевую страницу- Динамические страницы (нужно запускать после загрузки страницы)
JS
или страница, запрашивающая интерфейс) может использоватьNightmare
Имитация доступа к браузеру- использовать
cheerio
Получить элемент страницы, получить целевые данные
полный код
Адрес GitHub полного кода сканера:полный код
Позже должны быть некоторые дополнительные шаги для сканирования более привлекательных изображений на некоторых веб-сайтах (вручную забавных), которые будут включать并发控制
а также反-反爬虫
некоторые стратегии. Затем используйте сканер для обхода некоторых веб-сайтов, на которых необходимо войти в систему и ввести код подтверждения.Приглашаем всех обратить внимание и правильно общаться.
я хочу сказать
再次感谢大家的点赞和关注和评论,谢谢大家的支持,谢谢!我自己觉得我算是一个爱文字,爱音乐,同时也喜欢coding的半文艺程序员。
Я думал о написании технических и других литературных статей. Хотя моя база не очень хороша, я всегда чувствую, что в процессе написания статей, будь то технические или литературные, я могу заставить себя думать и заставить себя учиться и общаться.毕竟每天忙忙碌碌之余,还是要活出自己不一样的生活。
Так что, если в будущем появятся хорошие статьи, я буду активно делиться ими с вами! Еще раз спасибо всем за поддержку!