#ruby #web-scraping #nokogiri
#ruby #очистка веб-страниц #nokogiri
Вопрос:
Я создаю скребок для статей из www.dev.to , который должен быть указан в названии, авторе и тексте статьи. Я использую #scan, чтобы избавиться от пробелов и других символов после имени автора. Сначала я предположил, что имя автора будет состоять из имени и фамилии, затем понял, что у некоторых указано только одно имя. Теперь, когда я соответствующим образом изменил регулярное выражение, метод перестал работать, и #scan возвращает пустой массив. Как я могу это исправить?
def scrape_post(path)
url = "https://dev.to/#{path}"
html_content = open(url).read
doc = Nokogiri::HTML(html_content)
doc.search('.article-wrapper').each do |element|
title = element.search('.crayons-article__header__meta').search('h1').text.strip
author_raw = element.search('.crayons-article__subheader').text.strip
author = author_raw.scan(/Aw (s|w)w /).first
body = doc.at_css('div#article-body').text.strip
@post = Post.new(id: @next_id, path: path, title: title, author: author, body: body, read: false)
end
@post
end
Пример входных данных:
path = rahxuls/preventing-copying-text-in-a-webpage-4acg
Ожидаемый результат:
title = "Preventing copying text in a webpage 😁"
author_raw = "Rahuln nn n Nov 6nnn ・2 min read"
author = "Rahul"
Комментарии:
1. Не могли бы вы добавить несколько примеров входных данных и ожидаемый результат?
2. будет сделано! секундочку
3. Включало ли изменение, которое вы внесли в свое регулярное выражение, добавление круглых скобок в середину?
4. да. я сделал это на случай, если есть только одно имя, а не имя фамилия. у вас есть предложение, как я могу его изменить?
5. Почему бы не выбрать элемент / узел, который содержит только имя?
author = element.search('.crayons-article__subheader a').text.strip #=> "Rahul"
Ответ №1:
Из scan
документации.
Если шаблон не содержит групп, каждый отдельный результат состоит из совпадающей строки, $amp; . Если шаблон содержит группы, каждый отдельный результат сам по себе является массивом, содержащим одну запись на группу.
Добавив круглые скобки в середину вашего регулярного выражения, вы создали группу захвата. Сканирование вернет все, что захватывает эта группа. В приведенном вами примере так и будет 'u'
.
"Rahuln nn n Nov 6nnn ・2 min read".scan(/Aw (s|w)w /) #=> [["u"]]
Группа может быть помечена как не захватываемая, чтобы вернуться к вашей старой реализации
"Rahuln nn n Nov 6nnn ・2 min read".scan(/Aw (?:s|w)w /) #=> ["Rahul"]
# ^
Или вы можете добавить именованную группу захвата к тому, что вы на самом деле хотите извлечь.
"Rahuln nn n Nov 6nnn ・2 min read".match(/A(?<name>w (s|w)w )/)[:name] #=> "Rahul"
Комментарии:
1. спасибо 🙂 я очень новичок в регулярных выражениях, и это многое объясняет!