2012-01-29 29 views
5

tôi đang sử dụng mô-đun BeautifulSoup để chọn tất cả href từ html bằng cách này:Python mô-đun BeautifulSoup neo chiết href

def extract_links(html): 
    soup = BeautifulSoup(html) 
    anchors = soup.findAll('a') 
    print anchors 
    links = [] 
    for a in anchors: 
    links.append(a['href']) 
    return links 

nhưng đôi khi nó thất bại bằng tin nhắn này lỗi:

Traceback (most recent call last): 
File "C:\py\main.py", line 33, in <module> 
urls = extract_links(page) 
File "C:\py\main.py", line 11, in extract_links 
links.append(a['href']) 
File "C:\py\BeautifulSoup.py", line 601, in __getitem__ 
return self._getAttrMap()[key] 
KeyError: 'href' 

Trả lời

5

Không phải tất cả neo thẻ sẽ có thuộc tính href. Bạn nên kiểm tra xem anchor có một href hay không trước khi bạn cố truy cập thuộc tính đó.

if a.has_key('href') 
    links.append(a['href']) 

Sau khi kiểm tra một số nhận xét tại đây, tôi nghĩ đây là cách xử lý nhiệt tình nhất.

+0

Cảm ơn, nhưng bây giờ IR trở lại thông báo lỗi này: Traceback (gần đây nhất gọi cuối cùng): File "C: \ py \ chính .py ", dòng 34, trong url = extract_links (trang) Tệp" C: \ py \ main.py ", dòng 11, trong extract_links nếu 'href' trong a.keys(): LoạiError: ' Đối tượng NoneType không được gọi là – Michal

+0

@micheal Bạn đang đặt các thẻ 'a' trong từ điển của mình mà không có thuộc tính' href'. Thay vì yêu cầu từ điển ho lên các thẻ có thể hoặc không thể đưa ra thuộc tính 'href', hãy hỏi dữ liệu nếu nó * trước * đưa nó vào từ điển. – Droogans

+0

Tôi nghĩ rằng lỗi mới là bởi vì một nút BeautifulSoup không phải là một từ điển, do đó, các phím 'không phải là những gì bạn mong đợi. –

0

Các Pythonic cách sẽ là một cái gì đó như thế này:

for a in anchors: 
    try: 
     links.append(a['href']) 
    except KeyError: 
     pass 

Đó chỉ đơn giản là bỏ qua bất kỳ <a> thẻ mà không có một href.

+1

Tôi nghĩ rằng 'has_key()' là Pythonic hơn là sử dụng lỗi cho logic, nhưng mọi người dường như không đồng ý về điều đó trong cộng đồng. –

+0

@MattLuongo: Nó phụ thuộc vào những gì bạn đang làm. Tôi cảm thấy nó được thể hiện rõ nhất là "lấy địa chỉ của mỗi liên kết, và nếu nó không có liên kết, đừng bận tâm", thay vì "kiểm tra xem mỗi liên kết có địa chỉ không, và nếu có, hãy lấy nó." Nó không giúp 'has_key' bị từ chối đối với các từ điển, nhưng' in' không làm điều tương tự đối với các nút BS. –

+0

Tôi đoán đó là lý do tại sao 'Tag' không phải là hậu duệ của' dict'. Dù sao, việc không dùng nữa không quá liên quan vì lý do đó. –

2

Hãy thử điều này.

links = [a['href'] for a in anchors if a.has_key('href')] 

Hoặc, nếu bạn muốn thay vì đột biến một danh sách hiện

links = [] 
#... 
links.extend(a['href'] for a in anchors if a.has_key('href')) 
+0

Đẹp một lớp lót. – tjarratt

+0

Hoặc, như các tài liệu thích, 'if 'href' trong một' :) – Gabriel

+0

@Gabriel các tài liệu có thể thích nó, nhưng hãy xem xét điều này. 's = BeautifulSoup (' href'); 'href' trong s.findAll ('a') [0] 'đánh giá thành' True'. 'has_key' không bị rò rỉ theo cách đó. –

0

Bạn cần phải cast a.attrs đến một dict đầu tiên, sau đó truy cập vào phần tử.

links.append(dict(a.attrs)['href']) 
+0

Erm, tôi nghĩ bạn có nghĩa là 'links.append (dict (a.attrs) ['href'])' ..? Nhưng điều đó không giải quyết được trường hợp có thẻ với 'href'. –

+0

Ý của bạn là * không có * 'href'? Sau đó, bạn đã chính xác. Kinh nghiệm cá nhân của tôi cho thấy rằng tôi cần phải đúc. – 0605002

+0

Ha, * không, cảm ơn. Tôi chỉ có nghĩa là đoạn mã trên không gán 'a.attrs' vào một' dict', nó đưa 'a.attrs ['href']' vào một 'dict', nó tạo ra một' TypeError'. –

2

soup.findAll() trả về một danh sách các "thẻ", có chứa các từ điển của các thuộc tính. Vì vậy, bạn cần phải trích xuất các thuộc tính của nó và làm việc trên chúng.

Lấy ví dụ và sửa đổi của bạn, đây là mã mà hoạt động:

def extract_links(html): 
    soup = BeautifulSoup(html) 
    anchors = soup.findAll('a') 
    print anchors 
    links = [] 
    for a in anchors: 
    if a.attrs.has_key('href'): 
     links.append(a['href']) 
return links 
Các vấn đề liên quan