Làm cách nào để truy xuất các liên kết của trang web và sao chép địa chỉ url của các liên kết bằng Python?truy xuất các liên kết từ trang web bằng python và BeautifulSoup
Trả lời
Dưới đây là một đoạn ngắn bằng cách sử dụng lớp SoupStrainer trong BeautifulSoup:
import httplib2
from BeautifulSoup import BeautifulSoup, SoupStrainer
http = httplib2.Http()
status, response = http.request('http://www.nytimes.com')
for link in BeautifulSoup(response, parseOnlyThese=SoupStrainer('a')):
if link.has_attr('href'):
print link['href']
Các tài liệu BeautifulSoup thực sự là khá tốt, và bao gồm một số tình huống điển hình:
http://www.crummy.com/software/BeautifulSoup/documentation.html
Chỉnh sửa: Lưu ý rằng tôi đã sử dụng lớp SoupStrainer vì nó hiệu quả hơn một chút (bộ nhớ và tốc độ khôn ngoan), nếu bạn biết những gì bạn đang phân tích cú pháp trước.
import urllib2
import BeautifulSoup
request = urllib2.Request("http://www.gpsbasecamp.com/national-parks")
response = urllib2.urlopen(request)
soup = BeautifulSoup.BeautifulSoup(response)
for a in soup.findAll('a'):
if 'national-park' in a['href']:
print 'found a url with national-park in the link'
chỉ để nhận được các liên kết, mà không B.soup và regex:
import urllib2
url="http://www.somewhere.com"
page=urllib2.urlopen(url)
data=page.read().split("</a>")
tag="<a href=\""
endtag="\">"
for item in data:
if "<a href" in item:
try:
ind = item.index(tag)
item=item[ind+len(tag):]
end=item.index(endtag)
except: pass
else:
print item[:end]
cho các hoạt động phức tạp hơn, tất nhiên BSoup vẫn ưa thích.
Những người khác đã đề xuất BeautifulSoup, nhưng tốt hơn hết là sử dụng lxml. Mặc dù tên của nó, nó cũng là để phân tích cú pháp và cào HTML. Nó nhanh hơn rất nhiều so với BeautifulSoup và thậm chí còn xử lý HTML "bị hỏng" tốt hơn so với BeautifulSoup (yêu cầu của họ đối với danh tiếng). Nó cũng có API tương thích cho BeautifulSoup nếu bạn không muốn tìm hiểu API lxml.
Không có lý do gì để sử dụng BeautifulSoup nữa, trừ khi bạn đang sử dụng Google App Engine hoặc thứ gì đó không hoàn toàn là Python không được phép.
lxml.html cũng hỗ trợ bộ chọn CSS3 để loại điều này là tầm thường.
Một ví dụ với lxml và xpath sẽ trông như thế này:
import urllib
import lxml.html
connection = urllib.urlopen('http://www.nytimes.com')
dom = lxml.html.fromstring(connection.read())
for link in dom.xpath('//a/@href'): # select the url in href for all a tags(links)
print link
BeautifulSoup 4 sẽ sử dụng 'lxml' làm trình phân tích cú pháp mặc định nếu được cài đặt. –
Tại sao không sử dụng biểu thức thông thường:
import urllib2
import re
url = "http://www.somewhere.com"
page = urllib2.urlopen(url)
page = page.read()
links = re.findall(r"<a.*?\s*href=\"(.*?)\".*?>(.*?)</a>", page)
for link in links:
print('href: %s, HTML text: %s' % (link[0], link[1]))
Tôi rất muốn có thể hiểu được điều này, ở đâu tôi có thể tìm ra những gì '(r '
Thực sự là một ý tưởng tồi. HTML bị hỏng ở khắp mọi nơi. – Ufoguy
Tại sao không sử dụng cụm từ thông dụng để phân tích cú pháp html: http: // stackoverflow.com/questions/1732348/regex-match-open-tags-ngoại trừ-xhtml-self-contained-tags? page = 1 & tab = votes # 1732454 – allcaps
Dưới mui xe BeautifulSoup bây giờ sử dụng lxml. Yêu cầu, lxml & việc hiểu danh sách làm cho một combo sát thủ.
import requests
import lxml.html
dom = lxml.html.fromstring(requests.get('http://www.nytimes.com').content)
[x for x in dom.xpath('//a/@href') if '//' in x and 'nytimes.com' not in x]
Trong danh sách comp, "if '//' và 'url.com' not in x" là một phương pháp đơn giản để xóa danh sách url của url điều hướng nội bộ của trang web, v.v.
Nếu nó là một repost, tại sao không phải là bài gốc bao gồm: 1. yêu cầu 2.list comp 3. logic để chà trang nội bộ & liên kết rác ?? Hãy thử và so sánh kết quả của hai bài viết, danh sách comp của tôi thực hiện một công việc tốt đáng ngạc nhiên khi quét các liên kết rác. – cheekybastard
OP không yêu cầu các tính năng đó và phần mà anh ta yêu cầu đã được đăng và giải quyết bằng cách sử dụng cùng một phương thức giống như bạn đăng. Tuy nhiên, tôi sẽ loại bỏ các downvote như danh sách hiểu không thêm giá trị cho những người mà muốn những tính năng và bạn làm rõ ràng đề cập đến họ trong cơ thể của bài viết. Ngoài ra, bạn có thể sử dụng đại diện :) – dotancohen
Các mã sau đây là để lấy tất cả các liên kết có sẵn trong một trang web sử dụng urllib2 và BeautifulSoup4
import urllib2
from bs4 import BeautifulSoup
url = urllib2.urlopen("http://www.espncricinfo.com/").read()
soup = BeautifulSoup(url)
for line in soup.find_all('a'):
print(line.get('href'))
Đối với đầy đủ sake, phiên bản BeautifulSoup 4, làm cho việc sử dụng mã hóa được cung cấp bởi các máy chủ cũng như:
from bs4 import BeautifulSoup
import urllib2
resp = urllib2.urlopen("http://www.gpsbasecamp.com/national-parks")
soup = BeautifulSoup(resp, from_encoding=resp.info().getparam('charset'))
for link in soup.find_all('a', href=True):
print link['href']
hoặc phiên bản Python 3:
from bs4 import BeautifulSoup
import urllib.request
resp = urllib.request.urlopen("http://www.gpsbasecamp.com/national-parks")
soup = BeautifulSoup(resp, from_encoding=resp.info().get_param('charset'))
for link in soup.find_all('a', href=True):
print(link['href'])
và một phiên bản sử dụng requests
library, mà như viết sẽ làm việc trong cả hai Python 2 và 3:
from bs4 import BeautifulSoup
from bs4.dammit import EncodingDetector
import requests
resp = requests.get("http://www.gpsbasecamp.com/national-parks")
http_encoding = resp.encoding if 'charset' in resp.headers.get('content-type', '').lower() else None
html_encoding = EncodingDetector.find_declared_encoding(resp.content, is_html=True)
encoding = html_encoding or http_encoding
soup = BeautifulSoup(resp.content, from_encoding=encoding)
for link in soup.find_all('a', href=True):
print(link['href'])
Cuộc gọi soup.find_all('a', href=True)
tìm tất cả <a>
yếu tố mà có một thuộc tính href
; các phần tử không có thuộc tính được bỏ qua.
BeautifulSoup 3 ngừng phát triển vào tháng 3 năm 2012; các dự án mới thực sự nên sử dụng BeautifulSoup 4, luôn luôn.
Lưu ý rằng bạn nên để giải mã HTML từ byte thành BeautifulSoup. Bạn có thể thông báo cho BeautifulSoup về các ký tự trả lời được tìm thấy trong tiêu đề phản hồi HTTP để hỗ trợ giải mã, nhưng có thể sai và xung đột với thông tin tiêu đề <meta>
được tìm thấy trong chính HTML, đó là lý do tại sao sử dụng phương thức lớp nội bộ BeautifulSoup EncodingDetector.find_declared_encoding()
để đảm bảo rằng các gợi ý mã hóa được nhúng như vậy sẽ giành chiến thắng trên máy chủ được định cấu hình sai.
Với requests
, thuộc tính response.encoding
mặc định là Latin-1 nếu đáp ứng có giá trị text/*
mimetype, ngay cả khi không có ký tự nào được trả về. Điều này phù hợp với RFC HTTP nhưng đau đớn khi được sử dụng với phân tích cú pháp HTML, vì vậy bạn nên bỏ qua thuộc tính đó khi không có charset
được đặt trong tiêu đề Kiểu nội dung.
Có điều gì đó giống như StrainedSoup cho bs4 không? (Tôi không cần nó bây giờ nhưng chỉ tự hỏi, nếu có bạn có thể muốn thêm rằng) –
@AnttiHaapala: 'SoupStrainer' bạn có nghĩa là gì? Nó [không đi đâu cả, nó vẫn là một phần của dự án] (https://www.crummy.com/software/BeautifulSoup/bs4/doc/#soupstrainer). –
import urllib2
from bs4 import BeautifulSoup
a=urllib2.urlopen('http://dir.yahoo.com')
code=a.read()
soup=BeautifulSoup(code)
links=soup.findAll("a")
#To get href part alone
print links[0].attrs['href']
Tập lệnh này thực hiện những gì bạn đang tìm kiếm, Nhưng cũng giải quyết liên kết tương đối đến liên kết tuyệt đối.
import urllib
import lxml.html
import urlparse
def get_dom(url):
connection = urllib.urlopen(url)
return lxml.html.fromstring(connection.read())
def get_links(url):
return resolve_links((link for link in get_dom(url).xpath('//a/@href')))
def guess_root(links):
for link in links:
if link.startswith('http'):
parsed_link = urlparse.urlparse(link)
scheme = parsed_link.scheme + '://'
netloc = parsed_link.netloc
return scheme + netloc
def resolve_links(links):
root = guess_root(links)
for link in links:
if not link.startswith('http'):
link = urlparse.urljoin(root, link)
yield link
for link in get_links('http://www.google.com'):
print link
Để tìm tất cả các liên kết, trong ví dụ này, chúng ta sẽ sử dụng các mô-đun urllib2 cùng với re.module * Một trong những chức năng mạnh mẽ nhất trong các mô-đun lại là "re.findall() ". Trong khi re.search() được sử dụng để tìm các trận đấu đầu tiên cho một mẫu, re.findall() tìm thấy tất cả các trận đấu và trả họ như là một danh sách các chuỗi, mỗi chuỗi đại diện cho một trận đấu *
import urllib2
import re
#connect to a URL
website = urllib2.urlopen(url)
#read html code
html = website.read()
#use re.findall to get all the links
links = re.findall('"((http|ftp)s?://.*?)"', html)
print links
BeatifulBộ phân tích cú pháp của riêng mình có thể bị chậm. Có thể khả thi hơn để sử dụng lxml có khả năng phân tích trực tiếp từ URL (với một số hạn chế được đề cập bên dưới).
import lxml.html
doc = lxml.html.parse(url)
links = doc.xpath('//a[@href]')
for link in links:
print link.attrib['href']
Đoạn mã trên sẽ trả lại các liên kết như là, và trong nhiều trường hợp họ sẽ liên kết tương đối hoặc tuyệt đối từ gốc trang web. Vì trường hợp sử dụng của tôi chỉ trích xuất một loại liên kết nhất định, bên dưới là phiên bản chuyển đổi liên kết thành URL đầy đủ và tùy chọn chấp nhận mẫu hình cầu như *.mp3
. Nó sẽ không xử lý dấu chấm đơn và đôi trong các đường dẫn tương đối mặc dù, nhưng cho đến nay tôi không có nhu cầu cho nó. Nếu bạn cần phân tích cú pháp các đoạn URL chứa ../
hoặc ./
thì urlparse.urljoin có thể hữu ích.
LƯU Ý: lxml Direct url phân tích cú pháp không xử lý tải từ https
và không làm chuyển hướng, nên vì lý do này các phiên bản dưới đây được sử dụng urllib2
+ lxml
.
#!/usr/bin/env python
import sys
import urllib2
import urlparse
import lxml.html
import fnmatch
try:
import urltools as urltools
except ImportError:
sys.stderr.write('To normalize URLs run: `pip install urltools --user`')
urltools = None
def get_host(url):
p = urlparse.urlparse(url)
return "{}://{}".format(p.scheme, p.netloc)
if __name__ == '__main__':
url = sys.argv[1]
host = get_host(url)
glob_patt = len(sys.argv) > 2 and sys.argv[2] or '*'
doc = lxml.html.parse(urllib2.urlopen(url))
links = doc.xpath('//a[@href]')
for link in links:
href = link.attrib['href']
if fnmatch.fnmatch(href, glob_patt):
if not href.startswith(('http://', 'https://' 'ftp://')):
if href.startswith('/'):
href = host + href
else:
parent_url = url.rsplit('/', 1)[0]
href = urlparse.urljoin(parent_url, href)
if urltools:
href = urltools.normalize(href)
print href
Việc sử dụng như sau:
getlinks.py http://stackoverflow.com/a/37758066/191246
getlinks.py http://stackoverflow.com/a/37758066/191246 "*users*"
getlinks.py http://fakedomain.mu/somepage.html "*.mp3"
'lxml' chỉ có thể xử lý thông tin nhập hợp lệ, làm thế nào nó có thể thay thế' BeautifulSoup'? – alexis
@alexis: Tôi nghĩ rằng 'lxml.html' hơi khoan dung hơn' lxml.etree'. Nếu đầu vào của bạn không được định dạng đúng thì bạn có thể đặt trình phân tích cú pháp BeautifulSoup một cách rõ ràng: http://lxml.de/elementsoup.html. Và nếu bạn làm với BeatifulSoup thì BS3 là một lựa chọn tốt hơn. – ccpizza
Dưới đây là một ví dụ sử dụng @ars chấp nhận câu trả lời và BeautifulSoup4
, requests
, và wget
module để xử lý các tải.
import requests
import wget
import os
from bs4 import BeautifulSoup, SoupStrainer
url = 'https://archive.ics.uci.edu/ml/machine-learning-databases/eeg-mld/eeg_full/'
file_type = '.tar.gz'
response = requests.get(url)
for link in BeautifulSoup(response.content, 'html.parser', parse_only=SoupStrainer('a')):
if link.has_attr('href'):
if file_type in link['href']:
full_path = url + link['href']
wget.download(full_path)
Tôi tìm thấy câu trả lời của @ Blairg23 làm việc, sau đợt điều chỉnh sau (bao gồm các kịch bản mà nó không hoạt động chính xác):
for link in BeautifulSoup(response.content, 'html.parser', parse_only=SoupStrainer('a')):
if link.has_attr('href'):
if file_type in link['href']:
full_path =urlparse.urljoin(url , link['href']) #module urlparse need to be imported
wget.download(full_path)
Đối với Python 3:
urllib.parse.urljoin
phải được sử dụng để có được URL đầy đủ để thay thế.
- 1. Sử dụng urllib và BeautifulSoup để truy xuất thông tin từ web với Python
- 2. Trích xuất các liên kết từ một trang web bằng cách sử dụng Go lang
- 3. Python: Làm cách nào để trích xuất URL từ Trang HTML bằng cách sử dụng BeautifulSoup?
- 4. Làm thế nào để trích xuất các liên kết từ một trang web bằng cách sử dụng lxml, XPath và Python?
- 5. Trích xuất dữ liệu từ các tệp HTML với BeautifulSoup và Python
- 6. Trích xuất nội dung bảng từ html bằng python và BeautifulSoup
- 7. Extract Liên kết từ trang web sử dụng R
- 8. Truy xuất toàn bộ trang web bằng Google Cache?
- 9. Trích xuất các liên kết từ bảng html
- 10. Làm cách nào để truy xuất trang web bằng C#?
- 11. Tìm liên kết cụ thể w/beautifulsoup
- 12. Dò web bằng Python
- 13. Cách trích xuất URL từ một trang HTML bằng Python
- 14. Lặp lại thông qua các trang web bằng Python Scrapy
- 15. gói trang web bằng Python
- 16. Bắt đầu từ trang web bên ngoài liên kết với "//"
- 17. Cách tìm các liên kết bị hỏng trên trang web
- 18. Trích xuất Từ khoá Meta Từ Trang web?
- 19. Nhận tất cả các liên kết của trang web bằng Ruby
- 20. cách trích xuất liên kết và tiêu đề từ trang .html?
- 21. duyệt web để điền vào (và truy xuất) các biểu mẫu tìm kiếm?
- 22. Làm cách nào để truy xuất URL từ trang web bằng Java?
- 23. trích xuất tất cả các siêu liên kết (từ trang web bên ngoài) bằng cách sử dụng node.js và yêu cầu
- 24. Cách trích xuất trang trình bày từ video bằng python
- 25. Liên kết trong các trang web JQueryMobile từ xa trong ứng dụng PhoneGap mở safari
- 26. Kết nối với URL và kết xuất trang web trong Groovy
- 27. BeautifulSoup Grab Văn bản trang web có thể nhìn thấy
- 28. Phân tích cú pháp HTML với BeautifulSoup 4 và Python
- 29. Python và BeautifulSoup vấn đề mã hóa
- 30. Đăng nhập vào trang web bằng python
+1, sử dụng bộ lọc súp là một ý tưởng tuyệt vời vì nó cho phép bạn phá vỡ rất nhiều phân tích cú pháp không cần thiết khi tất cả những gì bạn theo sau là các liên kết. –
Tôi đã chỉnh sửa để thêm một lời giải thích tương tự trước khi tôi nhìn thấy lời bình luận của Evan. Cảm ơn bạn đã lưu ý rằng, mặc dù! – ars
cảm ơn, điều này giải quyết vấn đề của tôi, với điều này tôi hoàn thành proyect của tôi cảm ơn rất nhiều – NepUS