Як використовувати grep та cut у скрипті, щоб отримати URL-адреси веб-сайту з HTML-файлу


21

Я намагаюся використовувати grep та cut для отримання URL-адрес з HTML-файлу. Посилання виглядають так:

<a href="http://examplewebsite.com/">

Інші веб-сайти є .net, .govале я припускаю, що я міг би зробити точку відключення прямо раніше >. Тож я знаю, що можу використовувати греп і вирізати якось, щоб відрізати все перед http та після .com, але я на цьому тримався на деякий час.


Я її відредагував. Деякі ігнорують пробіл між <і a, HTML без нього не відображатиметься. Дякуємо, що це зробили!
eltigre

Використовуйте форматування коду (виберіть текст і натисніть Ctrl-K). Інакше <>змушує його сприйматись як тег HTML.
муру

чому б не відповідати початковій і кінцевій цитаті параметра href? окрім того, я вважаю, що регулярні вирази не найкраще підходять для HTML.
把 友情 留 在 无 盐

Я хочу написати команду, використовуючи спеціально grep і cut для цього. Я усвідомлюю, що є й інші способи, але я хотів знати про них.
eltigre

9
Взагалі не дуже гарна ідея розбирати HTML з регулярними виразами, оскільки HTML не є звичайною мовою. Якщо ви можете гарантувати, що HTML, який ви розбираєте, досить простий, а речі, які ви намагаєтеся витягти, передбачувані, ви, можливо, зможете піти з ним. Але подивіться , будь ласка , stackoverflow.com/a/1732454/4014959
PM 2Ring

Відповіді:


25

Як я вже говорив у своєму коментарі, звичайно не годиться розбирати HTML з регулярними виразами, але іноді ви можете піти з ним, якщо HTML, який ви розбираєте, добре ведеться.

Щоб отримати лише URL-адреси, які є в hrefатрибуті <a>елементів, мені найпростіше це зробити на декількох етапах. З ваших коментарів виходить, що вам потрібно лише домен верхнього рівня, а не повну URL-адресу. У такому випадку ви можете використовувати щось подібне:

grep -Eoi '<a [^>]+>' source.html |
grep -Eo 'href="[^\"]+"' | 
grep -Eo '(http|https)://[^/"]+'

де source.htmlфайл, що містить HTML-код для розбору.

Цей код буде надрукувати всі URL-адреси верхнього рівня, які є hrefатрибутом будь-яких <a>елементів у кожному рядку. -iВаріант першої grepкоманди є забезпечення того , вона буде працювати на обох <a>і <A>елементів. Я думаю, ви також можете дати -i2-му grepзахоплюванню HREFатрибутів верхнього регістру , OTOH, я вважаю за краще ігнорувати такий зламаний HTML. :)

Для обробки вмісту http://google.com/

wget -qO- http://google.com/ |
grep -Eoi '<a [^>]+>' | 
grep -Eo 'href="[^\"]+"' | 
grep -Eo '(http|https)://[^/"]+'

вихід

http://www.google.com.au
http://maps.google.com.au
https://play.google.com
http://www.youtube.com
http://news.google.com.au
https://mail.google.com
https://drive.google.com
http://www.google.com.au
http://www.google.com.au
https://accounts.google.com
http://www.google.com.au
https://www.google.com
https://plus.google.com
http://www.google.com.au

Мій висновок трохи відрізняється від інших прикладів, коли я переспрямовуюсь на австралійську сторінку Google.


ДЯКУЮ. Зараз це саме те, що я шукав. Це найчистіший спосіб зробити це.
eltigre

@eltigre: Моє задоволення! Але будь ласка, уважно ставтесь до попередження, на яке я посилався у своєму коментарі вище. :)
PM 2Ring

Я прийшов до цього питання, очікуючи легких моментів ... і ти вже повністю вдарив цвях по голові
Марк К Коуан

Дякую, @MarkKCowan. :) FWIW, я спочатку почав писати відповідь за допомогою awk, але потім вирішив, що рішення, засноване на грепі, буде легше зрозуміти для тих, хто не знайомий з awk. І як би там не було, код вище, ніж мій awk-код.
PM 2Cing,

2
@mavavilj: Оскільки ОП хотіла лише домену верхнього рівня, то після ://ми приймаємо лише символи перед першим /або ". Але якщо ви хочете побачити повну URL-адресу, змініть цю команду на grep -Eo '(http|https)://[^"]+. Інший варіант для цього рядка - це те, grep -Eo '(http|https)://[^?"]+'що скорочує параметри запитів. Однак ця версія все одно буде друкувати URL-адреси, які містяться в іншій URL-адресі як параметр запиту, але вони будуть надруковані в окремому рядку.
PM 2Ring

25

Не впевнений, чи обмежений ви інструментами:

Але регулярний вираз може бути не найкращим способом, як згадувалося, але ось приклад, який я зібрав:

cat urls.html | grep -Eo "(http|https)://[a-zA-Z0-9./?=_-]*" | sort -u
  • grep -E: те саме, що і egrep
  • grep -o: виводить лише те, що було знято
  • (http | https): є або / або
  • az: це все нижнє регістр
  • AZ: це вся справа
  • . : є крапкою
  • \ ?: є?
  • *: це повторити групу [...]
  • uniq: видалить всі дублікати

Вихід:

bob@bob-NE722:~s$  wget -qO- https://stackoverflow.com/ | grep -Eo "(http|https)://[a-zA-Z0-9./?=_-]*" | sort -u
https://stackauth.com
https://meta.stackoverflow.com
https://cdn.sstatic.net/Img/svg-icons
https://stackoverflow.com
https://www.stackoverflowbusiness.com/talent
https://www.stackoverflowbusiness.com/advertising
https://stackoverflow.com/users/login?ssrc=head
https://stackoverflow.com/users/signup?ssrc=head
https://stackoverflow.com
https://stackoverflow.com/help
https://chat.stackoverflow.com
https://meta.stackoverflow.com
...

Ви також можете додати, \dщоб зловити інші типи цифр.


2
Регексери IRI! Використовуйте одну з них і лякайте ОП! :)
муру

2
@muru ... тремтячи я ... Я не знаю, що сказати. Це навіть реально !?
jmunsch

4
@jmunsch, uniq просто видаліть сусідні дублікати. sort -u?
JJoao

1
це чудово працює, найкраща відповідь !!
Гері

@JJoao є джерелом для сортування -у швидше, ніж трубопроводи? Просто продуманий експеримент, я повинен шукати. Але ви, напевно, маєте рацію щодо програмного забезпечення оболонки.
jmunsch

9

Якщо ваша греп підтримує виразки Perl:

grep -Po '(?<=href=")[^"]*(?=")'
  • (?<=href=")і (?=")є орієнтовними виразами для hrefатрибута. Для цього потрібен -Pваріант.
  • -o друкує відповідний текст.

Наприклад:

$ curl -sL https://www.google.com | grep -Po '(?<=href=")[^"]*(?=")'
/search?
https://www.google.co.in/imghp?hl=en&tab=wi
https://maps.google.co.in/maps?hl=en&tab=wl
https://play.google.com/?hl=en&tab=w8
https://www.youtube.com/?gl=IN&tab=w1
https://news.google.co.in/nwshp?hl=en&tab=wn
...

Як завжди, немає гарантії, що це дійсні URI або що HTML, який ви розбираєте, буде дійсним.


8

Як альтернативу , що не є регулярною виразкою , використовуйте pup :

pup 'a[href] attr{href}' < yourfile.html

Знайдемо всі aелементи, які мають hrefатрибут, а потім відобразимо значення hrefатрибута.

Щоб встановити pup, вам потрібно Go (мова програмування):

sudo apt-get install golang
sudo go get github.com/ericchiang/pup

Перевага цього рішення полягає в тому, що воно не покладається на правильне форматування HTML .


1
+1 для pup, час встановити це ....
Марк К Коуан

Ви також можете помістити їх у файл. pup 'a.classname[href] attr{href}' < tut.html >links.md
Ахмад Авайс

1

Тут я знайшов рішення, яке IMHO набагато простіше і потенційно швидше, ніж запропоновано тут. Я трохи налаштувався на підтримку файлів https. Але версія TD; TR - це ...

PS: Ви можете замінити URL-адресу сайту на шлях до файлу, і він буде працювати так само.

lynx -dump -listonly -nonumbers "http://www.goggle.com" > links.txt

lynx -dump -listonly -nonumbers "some-file.html" > links.txt

Якщо ви просто хочете побачити посилання, а не розміщувати їх у файлі, то спробуйте це замість ...

lynx -dump -listonly -nonumbers "http://www.google.com"

lynx -dump -listonly -nonumbers "some-file.html"

Результат буде схожий на наступний ...

http://www.google.ca/imghp?hl=en&tab=wi
http://maps.google.ca/maps?hl=en&tab=wl
https://play.google.com/?hl=en&tab=w8
http://www.youtube.com/?gl=CA&tab=w1
http://news.google.ca/nwshp?hl=en&tab=wn
https://mail.google.com/mail/?tab=wm
https://drive.google.com/?tab=wo
https://www.google.ca/intl/en/options/
http://www.google.ca/history/optout?hl=en
...
etc.

Для мого використання це спрацювало чудово. Але будьте обережні, що сьогодні люди додають посилання типу src = "// blah.tld" для URI CDN бібліотек. Я не хотів бачити їх у знайдених посиланнях.

Не потрібно намагатися перевіряти href чи інші джерела на наявність посилань, оскільки "lynx -dump" за замовчуванням вилучає всі посилання, які можна натиснути, з певної сторінки. Тож єдина думка, яку вам потрібно зробити після цього - проаналізувати результат "lynx-dump", використовуючи grep, щоб отримати більш чисту необроблену версію того ж результату.


Але питання говорить "витягнути URL-адреси з HTML- файлу [виглядає] як" (приклад), а не "витягувати URL-адреси з веб-сторінки". Якщо вашу відповідь можна використати проти файлу, який знаходиться на локальній машині, поясніть як. Будь ласка, не відповідайте на коментарі; відредагуйте свою відповідь, щоб зробити її більш зрозумілою та повною.
G-Man каже: "Відновіть Моніку"

1
Ви можете замінити URL на ім'я файлу.
asiby

@ G-Man, чому -1? Вам потрібно спробувати код і переконатися, що він також працює для локальних файлів. Я додав, що уточнення у випадку, якщо воно не було очевидним.
asiby

Це дуже зручно .. якщо ви використовуєте з xargs, варто додати | сортувати | uniq для обрізки дублікатів посилань.
Стюарт Ексон

0
wget -qO- google.com |
tr \" \\n | grep https\*://

... мабуть, зробив би досить добре. Як написано, він друкує:

http://schema.org/WebPage
http://www.google.com/imghp?hl=en&tab=wi
http://maps.google.com/maps?hl=en&tab=wl
https://play.google.com/?hl=en&tab=w8
http://www.youtube.com/?tab=w1
http://news.google.com/nwshp?hl=en&tab=wn
https://mail.google.com/mail/?tab=wm
https://drive.google.com/?tab=wo
http://www.google.com/intl/en/options/
http://www.google.com/history/optout?hl=en
https://accounts.google.com/ServiceLogin?hl=en&continue=http://www.google.com/
https://www.google.com/culturalinstitute/project/the-holocaust?utm_source=google&amp;utm_medium=hppromo&amp;utm_campaign=auschwitz_q1&amp;utm_content=desktop
https://plus.google.com/116899029375914044550

Якщо важливо, щоб ви відповідали лише посиланням і з цих доменів вищого рівня, ви можете:

wget -qO- google.com |
sed '/\n/P;//!s|<a[^>]*\(https*://[^/"]*\)|\n\1\n|;D'

... або щось подібне - хоча для деяких seds може знадобитися замінити буквальний \nсимвол ewline для кожного з останніх двох ns.

Як написано, наведена вище команда друкує:

http://www.google.com
http://maps.google.com
https://play.google.com
http://www.youtube.com
http://news.google.com
https://mail.google.com
https://drive.google.com
http://www.google.com
http://www.google.com
http://www.google.com
https://www.google.com
https://plus.google.com

... і в будь-якому випадку (але, мабуть, найбільш корисно для останнього) ви можете натиснути на |sort -uфільтр до кінця, щоб отримати список sortредагування та скинути дублікати.



-1
echo "<a href="http://examplewebsite.com/">"|sed -r 's:<.*"::g'|sed 's:/">$::g'

Я не впевнений, що ті "розумні" цитати - це те, що ви там мали намір - можливо, звичайні "подвійні" цитати?
Джефф Шаллер
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.