Jak mogę pobrać linki do strony internetowej i skopiować adresy URL linków za pomocą Pythona?
141
Jak mogę pobrać linki do strony internetowej i skopiować adresy URL linków za pomocą Pythona?
Oto krótki fragment wykorzystujący klasę SoupStrainer w BeautifulSoup:
import httplib2
from bs4 import BeautifulSoup, SoupStrainer
http = httplib2.Http()
status, response = http.request('http://www.nytimes.com')
for link in BeautifulSoup(response, parse_only=SoupStrainer('a')):
if link.has_attr('href'):
print(link['href'])
Dokumentacja BeautifulSoup jest w rzeczywistości całkiem dobra i obejmuje kilka typowych scenariuszy:
https://www.crummy.com/software/BeautifulSoup/bs4/doc/
Edycja: Zwróć uwagę, że użyłem klasy SoupStrainer, ponieważ jest nieco bardziej wydajna (pod względem pamięci i szybkości), jeśli wiesz, co analizujesz z wyprzedzeniem.
/usr/local/lib/python2.7/site-packages/bs4/__init__.py:128: UserWarning: The "parseOnlyThese" argument to the BeautifulSoup constructor has been renamed to "parse_only."
has_attr
. Zamiast tego widzę, że coś się nazywahas_key
i działa.Ze względu na kompletność wersja BeautifulSoup 4, również wykorzystująca kodowanie dostarczone przez serwer:
lub wersja Python 2:
oraz wersja korzystająca z
requests
biblioteki , która jak napisano będzie działać zarówno w Pythonie 2, jak i 3:soup.find_all('a', href=True)
Wywołanie znajdzie wszystkie<a>
elementy, które mająhref
atrybut; elementy bez atrybutu są pomijane.BeautifulSoup 3 zatrzymał rozwój w marcu 2012; nowe projekty naprawdę powinny używać BeautifulSoup 4, zawsze.
Zauważ, że powinieneś pozostawić dekodowanie HTML z bajtów do BeautifulSoup . Możesz poinformować BeautifulSoup o zestawie znaków znajdującym się w nagłówkach odpowiedzi HTTP, aby pomóc w dekodowaniu, ale może to być błędne i sprzeczne z
<meta>
informacjami nagłówka znalezionymi w samym kodzie HTML, dlatego powyższe używa metody wewnętrznej klasy BeautifulSoup,EncodingDetector.find_declared_encoding()
aby upewnić się, że takie wbudowane wskazówki dotyczące kodowania wygrywają z błędnie skonfigurowanym serwerem.W
requests
przypadkuresponse.encoding
atrybutu wartość domyślna to Latin-1, jeśli odpowiedź matext/*
typ MIME, nawet jeśli nie został zwrócony żaden zestaw znaków. Jest to zgodne ze specyfikacjami HTTP RFC, ale jest bolesne, gdy jest używane z analizą HTML, więc należy zignorować ten atrybut, jeślicharset
w nagłówku Content-Type ustawiono no .źródło
SoupStrainer
masz na myśli? To nie idź nigdzie, nadal jest częścią projektu .Inni polecili BeautifulSoup, ale znacznie lepiej jest użyć lxml . Pomimo swojej nazwy służy również do analizowania i zgrywania kodu HTML. Jest dużo, dużo szybszy niż BeautifulSoup, a nawet obsługuje „zepsuty” HTML lepiej niż BeautifulSoup (ich roszczenia do sławy). Ma również interfejs API zgodności dla BeautifulSoup, jeśli nie chcesz uczyć się lxml API.
Ian Blicking zgadza się .
Nie ma już powodu, aby używać BeautifulSoup, chyba że korzystasz z Google App Engine lub czegoś, w czym coś, co nie jest czysto Python, jest niedozwolone.
lxml.html obsługuje również selektory CSS3, więc tego rodzaju rzeczy są trywialne.
Przykład z lxml i xpath wyglądałby tak:
źródło
lxml
jako domyślnego parsera, jeśli zostanie zainstalowany.źródło
Poniższy kod służy do pobierania wszystkich linków dostępnych na stronie internetowej przy użyciu
urllib2
iBeautifulSoup4
:źródło
Pod maską BeautifulSoup używa teraz lxml. Żądania, lxml i listy składają się na zabójczą kombinację.
W zestawieniu list „if” // ”i„ url.com ”not in x” to prosta metoda przeglądania listy adresów URL „wewnętrznych” adresów URL nawigacji witryn itp.
źródło
tylko po to, aby uzyskać linki, bez B.soup i regex:
dla bardziej złożonych operacji, oczywiście BSoup jest nadal preferowana.
źródło
<a
ahref
? Powiedzrel="nofollow"
lubonclick="..."
po prostu nową linijkę? stackoverflow.com/questions/1732348/…Ten skrypt robi to, czego szukasz, ale także rozwiązuje względne linki do bezwzględnych linków.
źródło
Aby znaleźć wszystkie linki, w tym przykładzie użyjemy modułu urllib2 razem z re.module * Jedną z najpotężniejszych funkcji w module re jest „re.findall ()”. Podczas gdy re.search () służy do znalezienia pierwszego dopasowania dla wzorca, re.findall () znajduje wszystkie dopasowania i zwraca je jako listę ciągów, z których każdy reprezentuje jedno dopasowanie *
źródło
Dlaczego nie użyć wyrażeń regularnych:
źródło
(r"<a.*?\s*href=\"(.*?)\".*?>(.*?)</a>", page)
to znaczy? dzięki!Łącza mogą mieć różne atrybuty, więc możesz przekazać listę tych atrybutów do wyboru
na przykład z atrybutem src i href (tutaj używam operatora rozpoczyna się od ^, aby określić, że każda z tych wartości atrybutów zaczyna się od http.
Atrybut = selektory wartości
źródło
Oto przykład z użyciem @ars Zaakceptowanych odpowiedź i
BeautifulSoup4
,requests
orazwget
moduły do obsługi plików do pobrania.źródło
Znalazłem odpowiedź, którą @ Blairg23 działała, po następującej poprawce (obejmującej scenariusz, w którym nie działał poprawnie):
W przypadku Pythona 3:
urllib.parse.urljoin
należy użyć zamiast tego w celu uzyskania pełnego adresu URL.źródło
Parser BeatifulSoup może działać wolno. Bardziej realne może być użycie lxml, który jest w stanie analizować bezpośrednio z adresu URL (z pewnymi ograniczeniami wymienionymi poniżej).
Powyższy kod zwróci linki bez zmian, aw większości przypadków będą to linki względne lub bezwzględne względem katalogu głównego witryny. Ponieważ moim przypadkiem użycia było wyodrębnianie tylko określonego typu linków, poniżej znajduje się wersja, która konwertuje linki na pełne adresy URL i która opcjonalnie akceptuje wzorzec glob, taki jak
*.mp3
. Nie obsługuje jednak pojedynczych i podwójnych kropek na ścieżkach względnych, ale do tej pory nie było takiej potrzeby. Jeśli chcesz przeanalizować fragmenty adresów URL zawierające urlparse.urljoin../
lub./
wtedy, może się przydać.UWAGA : Bezpośrednie parsowanie adresu URL lxml nie obsługuje ładowania z
https
i nie wykonuje przekierowań, więc z tego powodu poniższa wersja używaurllib2
+lxml
.Sposób użycia jest następujący:
źródło
lxml
obsługuje tylko prawidłowe dane wejściowe, w jaki sposób można je zastąpićBeautifulSoup
?lxml.html
jest nieco bardziej wyrozumiały niżlxml.etree
. Jeśli dane wejściowe nie są poprawnie sformułowane, możesz jawnie ustawić parser BeautifulSoup: lxml.de/elementsoup.html . A jeśli zdecydujesz się na BeatifulSoup, lepszym wyborem będzie BS3.źródło
Może istnieć wiele zduplikowanych linków razem z linkami zewnętrznymi i wewnętrznymi. Aby rozróżnić te dwa elementy i po prostu uzyskać unikalne linki za pomocą zestawów:
źródło