使用BeautifulSoup从维基百科中获取特定图像

时间:2015-01-18 02:51:24

标签: python html css web-scraping beautifulsoup

我试图通过使用BeautifulSoup 4和lxml作为解析器从某些维基百科页面获取特定图像。例如,我试图从这个维基百科页面右侧获得专辑封面: http://en.wikipedia.org/wiki/Animal_House_(U.D.O._album)

执行抓取的功能是:

def get_cover_from_wikipedia(url):
    r = requests.get(url)
    if r.status_code == 200:
        soup = BeautifulSoup(r.content, 'lxml')
        elements = soup.find_all('a', class_='image')
        for element in elements:
            print '%s\n\n' % element.prettify()

    return False

打印输出如下:

<a class="image" href="/wiki/File:Question_book-new.svg">
 <img alt="" data-file-height="204" data-file-width="262" height="39" src="//upload.wikimedia.org/wikipedia/en/thumb/9/99/Question_book-new.svg/50px-Question_book-new.svg.png" srcset="//upload.wikimedia.org/wikipedia/en/thumb/9/99/Question_book-new.svg/75px-Question_book-new.svg.png 1.5x, //upload.wikimedia.org/wikipedia/en/thumb/9/99/Question_book-new.svg/100px-Question_book-new.svg.png 2x" width="50"/>
</a>

<a class="image" href="/wiki/File:UDO_animal_house.jpg">
 <img alt="" data-file-height="302" data-file-width="300" height="221" src="//upload.wikimedia.org/wikipedia/en/thumb/4/4e/UDO_animal_house.jpg/220px-UDO_animal_house.jpg" srcset="//upload.wikimedia.org/wikipedia/en/4/4e/UDO_animal_house.jpg 1.5x, //upload.wikimedia.org/wikipedia/en/4/4e/UDO_animal_house.jpg 2x" width="220"/>
</a>

我想要提取的图像是第二个块中以<a class...开头的图像,而不是第一个块中图像的书籍图像

我想在这里完成的是:

  1. 我只想获得用src指定的链接,而不是该类附带的所有内容。

  2. 我希望能够区分书籍图像和我想要提取的图像。书籍图像就在那里,因为如果您查看维基百科页面,它会说该文章需要引用,并且那里有书籍图像。显然,它匹配我对标记a和类image的搜索,但根据相关文章,它可能会也可能不存在。

  3. 获得我感兴趣的图片的唯一方法是什么,这是图片右侧的图片?

2 个答案:

答案 0 :(得分:2)

您的搜索不够具体。书籍图像嵌套在元数据表中:

<table class="metadata plainlinks ambox ambox-content ambox-Refimprove" role="presentation">

虽然专辑封面嵌套在另一个封面内:

<table class="infobox vevent haudio" style="width:22em">

利用这个优势。

使用CSS selector support可以解决这个问题:

covers = soup.select('table.infobox a.image img[src]')
for cover in covers:
    print cover['src']

CSS选择器会询问具有<img>属性的src代码,前提是它们嵌套在<a class="image">元素内的<table class="infobox">元素中。只有一个这样的形象:

>>> from bs4 import BeautifulSoup
>>> import requests
>>> r = requests.get('http://en.wikipedia.org/wiki/Animal_House_(U.D.O._album)')
>>> soup = BeautifulSoup(r.content)
>>> covers = soup.select('table.infobox a.image img[src]')
>>> for cover in covers:
...     print cover['src']
... 
//upload.wikimedia.org/wikipedia/en/thumb/4/4e/UDO_animal_house.jpg/220px-UDO_animal_house.jpg

答案 1 :(得分:-3)

嗯,你已经得到了你想要的99%,所以这是主要的事情。我的第一个想法是稍微收紧你的过滤器。如果这是一次性案例,并且您不需要在多个地方申请此计划,那么该文本就会出现问题。 BeautifulSoup.find_all()中的参数可以帮助你:

if r.status_code == 200:
    soup = BeautifulSoup(r.content, 'lxml')
    elements = soup.find_all('a', text='.jpg' class_='image')
    for element in 
        print '%s\n\n' % element.prettify()

return False

由于您的目标图片是页面上唯一的.jpg文件,这应该会有所帮助。你可能已经看过了,但如果你遇到困难,这应该会有所帮助: http://www.crummy.com/software/BeautifulSoup/bs4/doc/#find-all