bash - 여러 링크가 포함된 html 파일에서 파일 이름 추출

bash - 여러 링크가 포함된 html 파일에서 파일 이름 추출

웹 페이지의 스크립트에 의해 자동으로 생성되는 html 파일을 다운로드했습니다. 파일에 이미지 링크를 포함하여 여러 링크가 포함되어 있습니다. 이미지의 전체 이름을 추출하려고 합니다.

<a href="000000.jpg" title="image name.jpg" target="_blank">Image name.jpg</a>

위에서 "Image name.jpg"파일에 저장하고 싶습니다. 그러한 이름이 수백 개 있으므로 파일을 구문 분석하고 다음 명령을 사용하여 나타나는 대로 각 이름을 저장합니다.

grep -i -E -o "target=\"_blank\">([[:graph:]]*)\.(jpg|png|gif|webm)" "$thread" | cut -f 2 -d '>' | sed 's/ /_/g' - > "$names"

여기서 " $thread"는 html 파일의 이름이고 " $names"는 출력되는 파일 이름 목록입니다. " "를 사용하여 cut해당 부분을 제거한 'target="_blank">'다음 공백을 밑줄로 변환합니다.

파일에 다른 여러 링크가 있으므로 크롤링할 확장명(image 및 webm)을 지정했습니다. 다른 모든 것은 무시되어야 합니다. 이러한 링크만 크롤링하지만 일부 링크가 누락되는 지점에 도달했습니다.

일부 파일에는 공백과 영숫자가 아닌 문자가 포함되어 있습니다. 이 모든 경우를 포괄해야 하는 which를 사용하면 아무것도 얻지 못하거나 html 부분 [[:print:]]만 얻고 다른 것은 아무것도 얻지 못합니다. <head>을 사용하면 [[:graph:][:space:]]아무것도 얻지 못합니다. [[:graph:]]위와 같이 사용하거나 [[:alnum:][:punct:]]영숫자/기타 문자(예: " ")가 포함된 filenamewith(parenthesis).jpg파일을 가져올 수 있지만 공백은 포함하지 않거나 그 반대의 경우에는 [[:alnum:][:space:]]작동하지만 인쇄 가능한 다른 문자를 무시합니다(" file name with spaces.jpg"는 작동하지만 "함께"는 사용하지 않음)(괄호 , 쉼표 또는 기타.jpg").

모든 경우를 포괄한다고 하는데 [[:print:]], 제가 올바르게 이해했다면 필요한 것을 얻지 못하고 있습니다.

grep -E -o(위를 기준으로) 일치해야 합니다: *.jpg *.png *.gif또는*.webm

grep나는 가 있거나 없는 -E/-o/-e다양한 변형을 시도했습니다 .

어떤 아이디어가 있나요? 저는 Arch Linux, grep 2.20, bash 4.3.18을 사용하고 있습니다.

답변1

가장 좋은 전략은 <a>모든 태그의 값을 출력할 수 있는 적합한 HTML 파서를 사용하는 것입니다.

이것은 xmlstarlet특히 XML 파서입니다. HTML이 올바른 형식의 XML이 아닐 수도 있지만 아마도 다음과 같은 아이디어를 얻을 수 있을 것입니다.

echo '<html>
<a href="000000.jpg" title="image name.jpg" target="_blank">Image name.jpg</a>
</html>' | xmlstarlet sel -t -v //a
Image name.jpg

답변2

귀하의 정규식은

target="_blank">([[:graph:]]*)\.(jpg|png|gif|webm)

이는 리터럴 텍스트 target="_blank">, 공백이 아닌 문자의 개수, 마지막으로 4개의 문자열 중 하나인 , .jpg또는 와 일치합니다 . 예를 들어, grep 명령은 다음 줄의 굵은 부분을 출력합니다..png.gif.webm

<하나...target="_blank">뭔가.jpg</a>
<하나...target="_blank">a.gifted.child.txt</a>
<a … target="_blank">기타 사항.jpg</a>
<하나...target="_blank">something.jpg</a>+more.jpg

[[:print:]]대신 사용하면 [[:graph:]]다음과 일치합니다.

<하나...target="_blank">something.jpg</a> 위블 워블 <a … target="_blank">something else.jpg</a>

target …라인에서 첫 번째 일치 비트와 마지막 일치 확장자 사이의 모든 항목이 일치합니다.

일치에서 HTML 마크업 문자를 제외해야 합니다.

target="_blank">[^<>]*\.(jpg|png|gif|webm)</a>

GNU grep을 사용하면 -P옵션을 사용하여 구성을 얻을 수 있습니다펄 정규식,특히너비가 0인 어설션일치 부분에 해당 텍스트를 포함하지 않고 일부 상수 텍스트가 앞이나 뒤에 오도록 지정할 수 있습니다.

grep -o -P '(?<target="_blank">)[^<>]*\.(jpg|png|gif|webm)(?=</a>)'

<a>예상치 못한 공백(예: 태그와 닫는 문자 사이 또는 개행 문자 사이에 개행 문자)이 있으면 </a>여전히 실패할 수 있습니다 . 당신은 할 수 있습니다적절한 HTML 파서를 사용하는 것이 좋습니다.

예를 들어, 파이썬에서는아름다운 수프(테스트되지 않음):

import re, sys, BeautifulSoup
soup = BeautifulSoup(sys.stdin)
for hit in soup.find_all('a', target='_blank'):
    if re.match(r'.*\.(jpg|png|gif|webm)\Z', hit.string):
        print(hit.string)

비슷한 코드는 다음과 같이 작성할 수 있습니다.HTML::Parser펄에서는노코체루비 등에서

답변3

나는 결국 이렇게 했습니다:

w3m -dump -T text/html "$thread" | grep -i -E -o 'File\:+([[:print:]]*)\.(jpg|png|webm|gif)'

w3m이 코드를 정리한 다음 grep을 통해 파일 이름을 찾을 수 있습니다. (링크된 파일을 제목과 구별하려면 리터럴 "파일:" 부분이 필요합니다). 대부분의 공백, 유니코드 문자 및 기타 인쇄 가능한 콘텐츠를 캡처하기 때문에 [[:print:]]가 필요합니다.

예상대로 작동합니다. (비록 같은 이름의 파일을 덮어쓰는 것을 방지하는 방법을 알아내야 하지만 그건 또 다른 날의 싸움입니다.)

관련 정보