Java豆瓣電影爬蟲——抓取電影詳情和電影短評數據


  一直想做個這樣的爬蟲:定制自己的種子,爬取想要的數據,做點力所能及的小分析。正好,這段時間寶寶出生,一邊陪寶寶和寶媽,一邊把自己做的這個豆瓣電影爬蟲的數據采集部分跑起來。現在做一個概要的介紹和演示。

 

動機

  采集豆瓣電影數據包括電影詳情頁數據和電影的短評數據。

  電影詳情頁如下圖所示

  需要保存這些詳情字段如導演、編劇、演員等還有圖中右下方的標簽。

 

  短評頁面如下圖所示

  需要保存的字段有短評所屬的電影名稱,每條評論的詳細信息如評論人名稱、評論內容等。

  

數據庫設計

  有了如上的需求,需要設計表,其實很簡單,只需要一張電影詳情表movie和一張電影短評表comments,另外還需要一張存儲網頁提取的超鏈接的記錄表record。

  movie表

  • movieId:主鍵,自增長
  • Name:電影名
  • Director:導演
  • Scenarist:編劇
  • Actors:主演
  • Type:類型
  • Country:制片國家/地區
  • Language:語言
  • releaseData: 上映日期
  • Runtime: 片長
  • ratingNum:豆瓣評分
  • Tags:標簽

 

  comments表

  • commentId:主鍵,自增長
  • commentInfo:評論內容
  • commentAuthor:評論者
  • commentAuthorImgUrl:評論者頭像鏈接
  • commentVote:評論點贊數
  • commentForMovie:評論的電影名
  • recordId:鏈接record表,暫時未用到

 

  record表

  • recordId:主鍵,自增長
  • URL:爬取解析的超鏈接
  • Crawled:是否被爬過

 

  注意:數據庫設計是在不斷調整的,比如之前設計了一張tags表,用於存儲每部電影的標簽,經過調整發現直接放到movie中作為一個字段更加方便,又比如comments表中,commentForMovie是后來加上的,方便查找當前的評論針對哪部電影。

 

使用的技術

  語言:Java(語言是一門工具,網上用python,java,nodejs比較多)

  數據庫:Mysql(輕便易用)

  解析頁面:Jsoup(比較熟悉httpparser,雖然功能強大,但是稍顯繁瑣,這里用Jsoup,因為其為類javascript語法)、正則表達式(對於一些結構比較奇怪的dom結構,采用了正則表達式的方式來提取信息,其實也可以用xpath,但是xpath極易受dom結構變化而失效)

  比如對於網頁源碼如下

<!DOCTYPE html>
<html lang="zh-cmn-Hans" class="ua-windows ua-webkit">
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
    <meta name="renderer" content="webkit">
    <meta name="referrer" content="always">
    <title>
        肖申克的救贖 (豆瓣)
</title>
    
    .....
    
    <meta name="keywords" content="肖申克的救贖,The Shawshank Redemption,肖申克的救贖影評,劇情介紹,電影圖片,預告片,影訊,在線購票,論壇,肖申克的救贖在線觀看,肖申克的救贖高清,肖申克的救贖在線播放">
    <meta name="description" content="肖申克的救贖電影簡介和劇情介紹,肖申克的救贖影評、圖片、預告片、影訊、論壇、在線購票、肖申克的救贖在線觀看、高清、在線播放">
   
.........                   


<div id="info">
        <span ><span class='pl'>導演</span>: <span class='attrs'><a href="/celebrity/1047973/" rel="v:directedBy">弗蘭克·德拉邦特</a></span></span><br/>
        <span ><span class='pl'>編劇</span>: <span class='attrs'><a href="/celebrity/1047973/">弗蘭克·德拉邦特</a> / <a href="/celebrity/1049547/">斯蒂芬·金</a></span></span><br/>
        <span class="actor"><span class='pl'>主演</span>: <span class='attrs'><a href="/celebrity/1054521/" rel="v:starring">蒂姆·羅賓斯</a> / <a href="/celebrity/1054534/" rel="v:starring">摩根·弗里曼</a> / <a href="/celebrity/1041179/" rel="v:starring">鮑勃·岡頓</a> / <a href="/celebrity/1000095/" rel="v:starring">威廉姆·賽德勒</a> / <a href="/celebrity/1013817/" rel="v:starring">克蘭西·布朗</a> / <a href="/celebrity/1010612/" rel="v:starring">吉爾·貝羅斯</a> / <a href="/celebrity/1054892/" rel="v:starring">馬克·羅斯頓</a> / <a href="/celebrity/1027897/" rel="v:starring">詹姆斯·惠特摩</a> / <a href="/celebrity/1087302/" rel="v:starring">傑弗里·德曼</a> / <a href="/celebrity/1074035/" rel="v:starring">拉里·布蘭登伯格</a> / <a href="/celebrity/1099030/" rel="v:starring">尼爾·吉恩托利</a> / <a href="/celebrity/1343305/" rel="v:starring">布賴恩·利比</a> / <a href="/celebrity/1048222/" rel="v:starring">大衛·普羅瓦爾</a> / <a href="/celebrity/1343306/" rel="v:starring">約瑟夫·勞格諾</a> / <a href="/celebrity/1315528/" rel="v:starring">祖德·塞克利拉</a></span></span><br/>
        <span class="pl">類型:</span> <span property="v:genre">劇情</span> / <span property="v:genre">犯罪</span><br/>
        
        <span class="pl">制片國家/地區:</span> 美國<br/>
        <span class="pl">語言:</span> 英語<br/>
        <span class="pl">上映日期:</span> <span property="v:initialReleaseDate" content="1994-09-10(多倫多電影節)">1994-09-10(多倫多電影節)</span> / <span property="v:initialReleaseDate" content="1994-10-14(美國)">1994-10-14(美國)</span><br/>
        <span class="pl">片長:</span> <span property="v:runtime" content="142">142 分鍾</span><br/>
        <span class="pl">又名:</span> 月黑高飛(港) / 刺激1995(台) / 地獄諾言 / 鐵窗歲月 / 消香克的救贖<br/>
        <span class="pl">IMDb鏈接:</span> <a href="http://www.imdb.com/title/tt0111161" target="_blank" rel="nofollow">tt0111161</a><br>

</div>




                </div>
                    


<div id="interest_sectl">
    <div class="rating_wrap clearbox" rel="v:rating">
        <div class="rating_logo">豆瓣評分</div>
        <div class="rating_self clearfix" typeof="v:Rating">
            <strong class="ll rating_num" property="v:average">9.6</strong>
            <span property="v:best" content="10.0"></span>
            <div class="rating_right ">
                <div class="ll bigstar50"></div>
                <div class="rating_sum">
                    <a href="collections" class="rating_people"><span property="v:votes">740373</span>人評價</a>
                </div>
            </div>
        </div>
            
                
                <span class="stars5 starstop" title="力薦">
                    5星 
                </span>
                <div class="power" style="width:64px"></div>
                <span class="rating_per">81.5%</span>
                <br />
                
                <span class="stars4 starstop" title="推薦">
                    4星 
                </span>
                <div class="power" style="width:12px"></div>
                <span class="rating_per">16.2%</span>
                <br />
                
                <span class="stars3 starstop" title="還行">
                    3星 
                </span>
                <div class="power" style="width:1px"></div>
                <span class="rating_per">2.1%</span>
                <br />
                
                <span class="stars2 starstop" title="較差">
                    2星 
                </span>
                <div class="power" style="width:0px"></div>
                <span class="rating_per">0.1%</span>
                <br />
                
                <span class="stars1 starstop" title="很差">
                    1星 
                </span>
                <div class="power" style="width:0px"></div>
                <span class="rating_per">0.1%</span>
                <br />
            
    </div>
        <div class="rating_betterthan">
            好於 <a href="/typerank?type_name=劇情&type=11&interval_id=100:90&action=">99% 劇情片</a><br/>
            好於 <a href="/typerank?type_name=犯罪&type=3&interval_id=100:90&action=">99% 犯罪片</a><br/>
        </div>
</div>


                
            </div>
        
.........

    <!-- sindar19a-docker-->

  <script>_SPLITTEST=''</script>
</body>

</html>

 

  可以通過如下代碼來解析相應字段(其中有用Jsoup和正則表達式的)

for (Element info : infos) {
    if (info.childNodeSize() > 0) {
        String key = info.getElementsByAttributeValue("class", "pl").text();
        if ("導演".equals(key)) {
            movie.setDirector(info.getElementsByAttributeValue("class", "attrs").text());
        } else if ("編劇".equals(key)) {
            movie.setScenarist(info.getElementsByAttributeValue("class", "attrs").text());
        } else if ("主演".equals(key)) {
            movie.setActors(info.getElementsByAttributeValue("class", "attrs").text());
        } else if ("類型:".equals(key)) {
            movie.setType(doc.getElementsByAttributeValue("property", "v:genre").text());
        } else if ("制片國家/地區:".equals(key)) {
            Pattern patternCountry = Pattern.compile(".制片國家/地區:</span>.+[\\u4e00-\\u9fa5]+.+[\\u4e00-\\u9fa5]+\\s+<br>");
            Matcher matcherCountry = patternCountry.matcher(doc.html());
            if (matcherCountry.find()) {
                movie.setCountry(matcherCountry.group().split("</span>")[1].split("<br>")[0].trim());// for example: >制片國家/地區:</span> 中國大陸 / 香港     <br>
            }
        } else if ("語言:".equals(key)) {
            Pattern patternLanguage = Pattern.compile(".語言:</span>.+[\\u4e00-\\u9fa5]+.+[\\u4e00-\\u9fa5]+\\s+<br>");
            Matcher matcherLanguage = patternLanguage.matcher(doc.html());
            if (matcherLanguage.find()) {
                movie.setLanguage(matcherLanguage.group().split("</span>")[1].split("<br>")[0].trim());
            }
        } else if ("上映日期:".equals(key)) {
            movie.setReleaseDate(doc.getElementsByAttributeValue("property", "v:initialReleaseDate").text());
        } else if ("片長:".equals(key)) {
            movie.setRuntime(doc.getElementsByAttributeValue("property", "v:runtime").text());
        }
    }
}
movie.setTags(doc.getElementsByClass("tags-body").text());
movie.setName(doc.getElementsByAttributeValue("property", "v:itemreviewed").text());
movie.setRatingNum(doc.getElementsByAttributeValue("property", "v:average").text());

  

對於服務端返回不同狀態的http status,本程序對於如304,401,403,404等都采取了丟棄處理,不作解析。

 

效果展示

 

  record表記錄

 

  movie表記錄

 

  comments表記錄

 

  以上只是一個爬取數據的后台實現雛形,還有很多細節的問題需要解決。后期可能會補上環境搭建以及遇到的問題和解決方法相關的文章。

  Java豆瓣電影爬蟲——使用Word2Vec分析電影短評數據

  Java豆瓣電影爬蟲——小爬蟲成長記(附源碼)

  程序爬取控制在豆瓣可接受范圍內,不會給豆瓣服務器帶來很大的壓力,寫此程序也是個人把玩,絕無惡意,萬望豆瓣君諒解^_^

 

如果您覺得閱讀本文對您有幫助,請點一下“推薦”按鈕,您的“推薦”將是我最大的寫作動力!如果您想持續關注我的文章,請掃描二維碼,關注JackieZheng的微信公眾號,我會將我的文章推送給您,並和您一起分享我日常閱讀過的優質文章。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM