2012-04-03 100 views
2

我正在做關於在互聯網上處理新聞文本的研究。所以,我正在編寫一個程序,通過新聞網址獲取和存儲數據庫中的新聞。從HTML內容獲取社交網絡信息

例如,這是一個隨機news url(西班牙新聞網站)。所以,我使用BeautifulSoup來獲取HTML內容,經過一些簡單的過程後,我獲得了新聞標題,摘要,內容,類別以及有關新聞的更多信息。

但是,正如你可以在我的例子中使用的消息看,還存在一些「社交網絡」的信息(新聞圖像的右側):

  • 的建議數量(臉譜)
  • 號鳴叫特(Twitter)
  • 號+ 1S(谷歌+)

的,我想也獲得這些信息,所以我試圖處理從該部分HTML內容,但它不存在!這是我做了什麼:

>>> import urllib 
>>> from BeautifulSoup import BeautifulSoup as Soup 
>>> news = urllib.urlopen('http://elcomercio.pe/mundo/1396187/noticia-horror-eeuu-cinco-ninos-muertos-deja-tiroteo-escuela-religiosa') 
>>> soup = Soup(news.read()) 
>>> sociales = soup.findAll('ul', {'class': 'sociales'})[0].findAll('li') 
>>> len(sociales) 
3 

這是Facebook的部分HTML內容:

>>> sociales[0] # facebook 
<li class="top"> 
<div class="fb-plg"> 
<div id="fb-root"></div> 
<script>(function(d, s, id) { 
    var js, fjs = d.getElementsByTagName(s)[0]; 
    if (d.getElementById(id)) {return;} 
    js = d.createElement(s); js.id = id; 
    js.src = "//connect.facebook.net/en_US/all.js#xfbml=1&appId=224939367568467"; 
    fjs.parentNode.insertBefore(js, fjs); 
}(document, 'script', 'facebook-jssdk'));</script> 
<div class="fb-like" data-href="http://elcomercio.pe/noticia/1396187/horror-eeuu-cinco-ninos-muertos-deja-tiroteo-escuela-religiosa" data-send="false" data-layout="box_count" data-width="70" data-show-faces="false" data-action="recommend"></div></div></li> 

Twitter的一部分:

>>> sociales[1] # twitter 
<li><a href="https://twitter.com/share" class="twitter-share-button" data-count="vertical" data-via="elcomercio" data-lang="es">Tweet</a><script type="text/javascript" src="//platform.twitter.com/widgets.js"></script></li> 

Google+的部分:

>>> sociales[2] # google+ 
<li><script type="text/javascript" src="https://apis.google.com/js/plusone.js"> 
    {lang: 'es'} 
</script><g:plusone size="tall"></g:plusone></li> 

正如你所看到的,我正在尋找的信息因爲沒有包含在HTML內容中,所以我猜測它是通過一些API鏈接獲得的。

所以我的問題是:無論如何,我可以從某個新聞的HTML內容中獲得我正在尋找的信息(Facebook推薦數量,推文數量,+ 1的數量)?

回答

2

這是我的解決方案。我發佈它,因爲也許有一天有人會有同樣的問題。我遵循@Hoff的建議,我用phantomjs

所以首先我安裝了它(Linux,Windows或MacOS,無所謂)。你只需要能夠在您提示/控制檯一樣運行它作爲一個命令:

phantomjs file.js 

這裏是phantomjs installation guide

於是,我做了一個簡單的腳本,接收一個URL,並返回一個BeautifulSoup對象(執行所有的JavaScript後):

import os 
import os.path 
import hashlib 
import subprocess 
from BeautifulSoup import BeautifulSoup 

PHANTOM_DIR = os.path.join(os.getcwd(), 'phantom') 

try: 
    os.stat(PHANTOM_DIR) 
except OSError: 
    os.mkdir(PHANTOM_DIR) 

PHANTOM_TEMPLATE = """var page = require('webpage').create(); 
page.open('%(url)s', function (status) { 
    if (status !== 'success') { 
     console.log('Unable to access network'); 
    } else { 
     var p = page.evaluate(function() { 
      return document.getElementsByTagName('html')[0].innerHTML 
     }); 
     console.log(p); 
    } 
    phantom.exit(); 
});""" 

def get_executed_soup(url): 
    """ Returns a BeautifulSoup object with the parsed HTML of the url 
     passed, after executing all the scripts in it. """ 
    file_id = hashlib.md5(url).hexdigest() 
    PHANTOM_ABS_PATH = os.path.join(PHANTOM_DIR, 'phantom%s.js' % file_id) 
    OUTPUT_ABS_PATH = os.path.join(PHANTOM_DIR, 'output%s.html' % file_id) 
    phantom = open(PHANTOM_ABS_PATH, 'w') 
    phantom.write(PHANTOM_TEMPLATE % {'url': url}) 
    phantom.close() 
    cmd = 'phantomjs ' + PHANTOM_ABS_PATH + ' > ' + OUTPUT_ABS_PATH 
    stdout, stderr = subprocess.Popen(cmd, shell=True).communicate() 
    output = open(OUTPUT_ABS_PATH, 'r') 
    soup = BeautifulSoup(output.read()) 
    output.close() 
    os.remove(PHANTOM_ABS_PATH) 
    os.remove(OUTPUT_ABS_PATH) 
    return soup 

這就是它!

PS:我只在Linux上測試過,所以如果有人在Windows和/或MacOS上嘗試這個,請分享你的「體驗」。謝謝:)

PS 2:我也在Windows中測試過,像魅力一樣工作!

我還張貼這在我的personal blog :)

+1

好東西,謝謝發佈! – Hoff 2012-04-15 16:07:10

1

您使用的客戶端(urllib)不會執行任何JavaScript,大多數社交插件都會使用它來顯示您想要的數據。

你需要的是一個能夠運行javascipt的客戶端,phantomjs是一個不錯的選擇,並且here's a good explanation on how to do just what you want

+0

有任何phantomjs Python模塊? – juliomalegria 2012-04-03 17:40:50

+0

曾經是PyPhantomJs,但它已經停產,對於簡單的用例,您可以簡單地使用子進程來運行phantomjs linux命令 – Hoff 2012-04-05 09:16:54