Написание парсера с помощью ChatGPT. Насколько это хорошо?
17 апреля 2023 г.В ноябре, после того как OpenAI выпустила ChatGPT на основе GPT-3.5, новости о нем распространились со скоростью лесного пожара. В связи с этим я написал об искусственном интеллекте и парсинге веб-страниц, а затем спросил собеседников, что они думают. внимание было уделено состоянию искусственного интеллекта для индустрии парсинга веб-страниц.
Пять месяцев спустя у нас есть GPT-4 и множество приложений, созданных на основе моделей GPT, так что пришло время поближе познакомиться с искусственным интеллектом для парсинга веб-страниц.
Может ли ИИ писать парсеры для нас?
В настоящий момент мы не можем ожидать, что ChatGPT напишет для нас полностью работающий парсер на выбранном веб-сайте. Он вернет синтаксически правильный парсер, но с универсальными селекторами, бесполезными в нашем случае. Если мы попросим очистить какой-нибудь известный веб-сайт, возможно, он сможет вернуть правильное сопоставление, если ответ уже был дан где-то в прошлом, например, в Stackoverflow.
Учитывая это, давайте попробуем создать парсер с нуля с помощью ChatGPT для нишевого веб-сайта, такого как https://www.gianvitorossi.com/it_it/
Я перейду прямо к последней подсказке, которую я написал, чтобы получить правильный паук Scrapy, где я попросил сопоставить четыре поля и объяснил ChatGPT план доступа к веб-сайту.
<цитата>Создайте веб-парсер Python, используя платформу Scrapy и селекторы XPath.
Параметр start_urls должен содержать URL-адрес [https://www.gianvitorossi.com/it_it](https://www.gianvitorossi.com/it_it), который необходимо очистить.
После очистки первой страницы парсер должен ввести функцию get_categories.
В этой функции парсер извлекает все относительные ссылки на разные типы продуктов, используя следующий селектор XPath: product_pages = response.xpath('//a[@role="menuitem"]/@href').extract() р>
Для каждой страницы продукта следует ввести функцию get_product_list.
Извлеките список продуктов на странице с помощью селектора XPath (’//a[contains(@class, «b-product_tile-image_link»)]/@href).
Если нужно показать больше продуктов, перейдите на следующую страницу продукта, используя XPath ('//a[data-event-click.prevent="loadMore"]/@href).extract()[0], который содержит абсолютный путь к следующей странице и включить этот селектор в предложение try/except. Если совпадения для селектора нет, в предложении exclude следует использовать инструкцию pass.
Для каждого извлеченного продукта введите функцию get_product_details.
Напишите логику очистки следующих полей:
- код продукта
- полная_цена
- цена
– product_url
Страница сведений о продукте содержит JSON, содержащий большую часть необходимых нам данных. Его можно найти, ища первое вхождение скрипта type="application/ld+json" и извлекая оттуда текст.
Он следует стандартному типу Product [Schema.org](http://schema.org/), и вы можете сопоставить поле product_code с полем mpn Json.
Цену поля можно сопоставить, введя словарь предложений в JSON и выбрав поле цены.
Вместо этого поле product_url можно сопоставить с помощью значения response.url.
Так как на этом сайте нет скидок, поле full_price может отображаться как поле цены.
А вот код, указанный в ответе:
import scrapy
import json
class GianvitoRossiSpider(scrapy.Spider):
name = 'gianvitorossi'
start_urls = ['https://www.gianvitorossi.com/it_it']
def parse(self, response):
# Extract product categories
product_pages = response.xpath('//a[@role="menuitem"]/@href').extract()
for product_page in product_pages:
yield scrapy.Request(response.urljoin(product_page), callback=self.get_product_list)
def get_product_list(self, response):
# Extract product links
product_links = response.xpath('//a[contains(@class, "b-product_tile-image_link")]/@href')
for link in product_links:
yield scrapy.Request(response.urljoin(link.extract()), callback=self.get_product_details)
# Check for more product pages
try:
next_page = response.xpath('//a[data-event-click.prevent="loadMore"]/@href').extract()[0]
yield scrapy.Request(response.urljoin(next_page), callback=self.get_product_list)
except:
pass
def get_product_details(self, response):
# Extract JSON data
json_data = response.xpath('//script[@type="application/ld+json"]/text()').extract_first()
data = json.loads(json_data)
# Extract product details
product_code = data['mpn']
full_price = data['offers']['price']
price = full_price
product_url = response.url
# Return item
yield {
'product_code': product_code,
'full_price': full_price,
'price': price,
'product_url': product_url
}
Парсер работает правильно и извлекает все элементы. Но разве на написание подсказки, необходимой для создания паука, уходит меньше времени, чем на написание паука самостоятельно? Трудно сказать. В обоих случаях мне нужно записать селекторы XPath, поэтому ИИ не экономит мне время. Предположим, у нас есть правильно спроектированная подсказка и шаблон паука Scrapy для повторного использования, мы можем предположить, что время, затрачиваемое на изменение подсказки или скребка, одинаково. Единственным улучшением процесса является то, что ChatGPT написал парсер без каких-либо ошибок.
Исправление ошибок с ИИ
Давайте проверим полезность ChatGPT, когда столкнемся с ошибкой в наших парсерах. Я изменю предыдущего паука, удалив цитату из Xpath и изменив имя неинициированной переменной.
def get_product_details(self, response):
# Extract JSON data
json_data = response.xpath('//script[@type="application/ld+json"]/text()).extract_first()
data = json.loads(json_data)
# Extract product details
product_code = data['mpn']
full_price = data['offers']['price']
price = full_price
product_url = response.url
# Return item
yield {
'product_code': product_code3,
'full_price': full_price,
'price': price,
'product_url': product_url
}
Сможет ли ChatGPT это исправить?
Да и не только вернул исправленный код, но и объяснил, что исправил.
<цитата>Ошибка в исходном коде была синтаксической ошибкой в селекторе XPath, используемом для извлечения данных JSON. Закрывающая кавычка была помещена неправильно, что привело к недопустимому селектору. Исправленный код помещает закрывающую кавычку в правильное место, позволяя селектору правильно извлекать данные JSON. Кроме того, в названии поля product_code
в операторе yield
была опечатка, которая была исправлена в исправленном коде.
Это полезный способ использования ChatGPT, поскольку иногда мы тратим много времени на поиск решения этих глупых ошибок.
Перенос на другой язык
Вместо того, чтобы создавать парсер с помощью Python, я использовал ту же подсказку для создания парсера Node.js. Я ничего не знаю об этом языке, и посмотрим, сможет ли ChatGPT помочь мне в создании моего первого парсера на Node.js
Вот результат:
const axios = require('axios');
const cheerio = require('cheerio');
const startUrl = 'https://www.gianvitorossi.com/it_it';
async function scrape(url) {
try {
const response = await axios.get(url);
const $ = cheerio.load(response.data);
// Extract product categories
const productPages = $('a[role="menuitem"]').map(function() {
return $(this).attr('href');
}).get();
for (const productPage of productPages) {
await getProducts(`https://www.gianvitorossi.com${productPage}`);
}
} catch (error) {
console.error(error);
}
}
async function getProducts(url) {
try {
const response = await axios.get(url);
const $ = cheerio.load(response.data);
// Extract product links
const productLinks = $('a.b-product_tile-image_link').map(function() {
return $(this).attr('href');
}).get();
for (const link of productLinks) {
await getProductDetails(`https://www.gianvitorossi.com${link}`);
}
// Check for more product pages
try {
const nextPage = $('a[data-event-click.prevent="loadMore"]').attr('href');
await getProducts(`https://www.gianvitorossi.com${nextPage}`);
} catch (error) {
// No more product pages
}
} catch (error) {
console.error(error);
}
}
async function getProductDetails(url) {
try {
const response = await axios.get(url);
const $ = cheerio.load(response.data);
// Extract JSON data
const jsonText = $('script[type="application/ld+json"]')[0].children[0].data;
const data = JSON.parse(jsonText);
// Extract product details
const productCode = data.mpn;
const fullPrice = data.offers.price;
const price = fullPrice;
const productUrl = response.config.url;
// Output data
console.log({
productCode: productCode,
fullPrice: fullPrice,
price: price,
productUrl: productUrl
});
} catch (error) {
console.error(error);
}
}
scrape(startUrl);
Это здорово. Скребок исправен и работает отлично.
Заключительные замечания
Должен признаться, я впечатлен результатами этих тестов. Хотя это правда, что это не сэкономило мне много времени, когда я написал парсер Python, это позволило мне написать парсер Node.js.
ИИ может снизить барьеры для принятия нового языка и помочь в разработке парсеров, продолжая его изучать, а также помогая отлаживать написанный код. Это не заменяет старую добрую практическую практику, но помогает быстрее учиться.
В конце концов, ИИ на данный момент больше, чем помощь, чем угроза, которая может заменить человека в ближайшем будущем.
:::информация Также опубликовано здесь.
:::
Оригинал