1. 程式人生 > >網路爬蟲爬取資料 本地資料庫儲存 遠端api分析 模型

網路爬蟲爬取資料 本地資料庫儲存 遠端api分析 模型

序言

20161119 寫

一個星期多一點,在眾多的爬蟲框架中選擇了WebmagicWebMagic簡單靈活的爬蟲框架。
簡單易用,在這之前用的是WebCollector JAVA爬蟲框架,它的模組劃分弄了一天也沒搞清楚,文件沒有webmagic的全,上手太慢,所以放棄
webmagic是國人做的,目前我使用的功能很少,對其框架的擴充套件定製內容很少,感覺不出什麼優點來,基本功能使用上手很快

正文

有個概念:
分散式:一個業務分拆多個子業務,部署在不同的伺服器上
叢集:同一個業務,部署在多個伺服器上
爬蟲可以做很多事,將網路上感興趣的資源通過爬蟲大規模的抓取,然後進行分析等其他操作,可以做出很多有意思的東西,比如‘輿情分析系統’‘網路環境文明用語情況分析’還可以‘爬取某個網站的圖片、文字、視訊’相當於一鍵直接下載,非常方便;
我做的這個小模型是
webmagic框架爬蟲抓取某位微博使用者的每條微博


下載儲存本地並儲存到本地資料庫Mysql
呼叫Watson的Tone Analyzer API逐條分析本地資料庫的資料並收集分析Json結果
用JAVA GUI顯示情感變化趨勢
四部分,
前兩部分由於微博網站頁面的顯示方式是由 JSP 函式獲取顯示的,導致webmagic的xpath和css無法正常使用,還有他的正則表示式解析也不正常;最後不得不放棄這三個函式,老老實實的用java自帶的正則解析函式才解析正常,

要點

1 大概瞭解網頁的構成
2 webmagic熟悉基本用法(官網文件很詳細)
3 JDBC等連線資料庫的操作 和資料庫的基本使用
4 正這表示式(重點!好好研究)
5 還是 get/post方法 和 Json解析
6 學會呼叫開源庫 開源模板,比如這個折線圖開源包

先分析網頁的構成 然後再測試抓取是否成功。
這裡我以 DwyaneWade NBA球星德維恩·韋德的微博為例 抓取

我將第一第二步建了一個工程 webmagic_test,第三第四步也建立一個工程JFreeChart;兩個工程分開執行

webmagic_test工程目錄如下
這裡寫圖片描述
JFreeChart工程目錄如下
這裡寫圖片描述

筆記
webmagic框架的兩個java檔案SinaBlogProcessor.java****OneFilePipeline.java
程式碼如下:
SinaBlogProcessor.java


package main;

import
java.io.File; import java.io.FileNotFoundException; import java.io.UnsupportedEncodingException; import us.codecraft.webmagic.downloader.Downloader; import java.util.ArrayList; import java.util.List; import us.codecraft.webmagic.Page; import us.codecraft.webmagic.Site; import us.codecraft.webmagic.Spider; import us.codecraft.webmagic.Task; import us.codecraft.webmagic.pipeline.FilePipeline; import us.codecraft.webmagic.pipeline.Pipeline; import us.codecraft.webmagic.processor.PageProcessor; /** * @author [email protected] <br> */ public class SinaBlogProcessor implements PageProcessor { public static String PATHNAME = "H:/php/wamp/wamp/www/_webmagicdata/weibodata_jdbc/jdbc_weibodata_page"; private static long userNum = 0; private static String userId = ""; private Site siteold = Site.me().setSleepTime(3000);// .setUserAgent( // "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like // Gecko) Chrome/45.0.2454.101 Safari/537.36"); private volatile static int maini = 0; private Site site = new Site().setRetryTimes(3).setSleepTime(2000).setTimeOut(10000) // 新增cookie之前一定要先設定主機地址,否則cookie資訊不生效 .setDomain(".weibo.com") // 新增抓包獲取的cookie資訊(某些網站如果沒有設定cookice無法訪問) .addCookie("Apache", "6047605616040.527.1448080352314") /*如何新增 cookice:[http://blog.csdn.net/kingsonyoung/article/details/51753639] */ // 新增請求頭,有些網站會根據請求頭判斷該請求是由瀏覽器發起還是由爬蟲發起的 .addHeader("User-Agent", "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/45.0.245") .addHeader("Accept", "*/*").addHeader("Accept-Encoding", "gzip, deflate, sdch") .addHeader("Accept-Language", "zh-CN,zh;q=0.8").addHeader("Connection", "keep-alive").addHeader("Referer", "http://weibo.com/p/1003062264358493/home?is_search=0&visible=0&is_all=1&is_tag=0&profile_ftype=1&page=1#feedtop"); @Override public void process(Page page) { String str = "" + page.getUrl().toString(); // System.out.println("#1"); if (str.indexOf("#feedtop") >= 0) { // System.out.println("#2"); if (page.getHtml().toString().indexOf("抱歉,你訪問的頁面地址有誤,或者該頁面不存在") < 0 && page.getHtml().toString().indexOf("請檢查輸入的網址是否正確") < 0 && page.getHtml().toString().indexOf("網路繁忙") < 0 && page.getHtml().toString().indexOf("請稍後再試") < 0) { // System.out.println("#3"); str = str.substring(0, str.indexOf("#feedtop")); str = str.substring(str.indexOf("&page=") + 6, str.length()); int cnt = 0; int pagenum = Integer.parseInt(str); System.out.println("pagenum=" + pagenum); // 獲取頁數 String xialaURL1 = "http://weibo.com/p/aj/v6/mblog/mbloglist?ajwvr=6&domain=100505&is_search=0&visible=0&is_all=1&is_tag=0&profile_ftype=1" + "&page=" + pagenum + "&pagebar=0" + "&pl_name=Pl_Official_MyProfileFeed__23&id=" + userId + "&script_uri=/p/" + userId + "/home&feed_type=0" + "&pre_page=" + pagenum + "&domain_op=100505&__rnd=1479123380183"; String xialaURL2 = "http://weibo.com/p/aj/v6/mblog/mbloglist?ajwvr=6&domain=100505&is_search=0&visible=0&is_all=1&is_tag=0&profile_ftype=1" + "&page=" + pagenum + "&pagebar=1" + "&pl_name=Pl_Official_MyProfileFeed__23&id=" + userId + "&script_uri=/p/" + userId + "/home&feed_type=0" + "&pre_page=" + pagenum + "&domain_op=100505&__rnd=1479123380183"; List<String> listurl = new ArrayList<String>(); listurl.add(xialaURL1); listurl.add(xialaURL2); page.addTargetRequests(listurl); page.putField("[Chushiyemian]", page.getHtml()); } else { System.out.println("userId=" + userId + "頁面不存在 404"); // userId++; maini = -1; } } else { // 兩個下拉重新整理頁面 page.putField("[Xialashuaxin]", page.getJson()); if (page.getJson().toString().indexOf("WB_feed_detail clearfix") < 0) { maini = -1; System.out.println("userId=" + userId + "到達最後一頁"); } } } @Override public Site getSite() { return site; } public static void main(String[] args) { // http://weibo.com/p/1005055317970558/home? // http://weibo.com/kevindurant?is_search=0&visible=0&is_all=1&is_tag=0&profile_ftype=1&page=2#feedtop // http://weibo.com/p/1003061735538085/home?from=page_100306_profile&wvr=6&mod=data&is_all=1#place for (userNum = 93; userNum < 99; userNum++) { userId = "10030622643584" + userNum; PATHNAME = "H:/php/wamp/wamp/www/_webmagicdata/weibodata_jdbc/" + userId + "jdbc_weibodata_page"; OneFilePipeline.cnt = 0;// 置0 String pageURLs = "http://weibo.com/p/" + userId + "/home?is_search=0&visible=0&is_all=1&is_tag=0&profile_ftype=1&page=";// 1#feedtop"; String pageURLe = "#feedtop"; String xialaPagebars = ""; for (maini = 1; maini <= 999 && maini > 0; maini++) { try { Spider.create(new SinaBlogProcessor()) // .addUrl("http://weibo.com/languageexchange?refer_flag=1001030201_&is_all=1") // .addPipeline(new // FilePipeline("H:/php/wamp/wamp/www/_webmagicdata")) .addPipeline(new OneFilePipeline(PATHNAME)).addUrl(pageURLs + maini + pageURLe).thread(50) .run(); } catch (FileNotFoundException | UnsupportedEncodingException e) { // TODO 自動生成的 catch 塊 e.printStackTrace(); } } System.out.println("userId=" + userId + "處理完畢/n傳送至watson分析並返回顯示"); } } // @Override // public void process(ResultItems arg0, Task arg1) { // // TODO 自動生成的方法存根 // System.out.println("process 2引數函式"+arg0.get("content1")); // // }1005053610038332 }

注意新增 cookice才能正常訪問微博,每個人的不同,此處不貼出來了

OneFilePipeline.java

package main;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import us.codecraft.webmagic.ResultItems;
import us.codecraft.webmagic.Task;
import us.codecraft.webmagic.pipeline.Pipeline;
import us.codecraft.webmagic.utils.FilePersistentBase;
import utils.Jdbc;

import java.io.*;
import java.util.Map;

/**
 * @author [email protected]
 */
public class OneFilePipeline extends FilePersistentBase implements Pipeline {

    public static int cnt = 0;

    private Logger logger = LoggerFactory.getLogger(getClass());

    private PrintWriter printWriter;

    /**
     * create a FilePipeline with default path"/data/webmagic/"
     */
    public OneFilePipeline() throws FileNotFoundException, UnsupportedEncodingException {
        this("/data/webmagic/");
        // this("H:\php\wamp\wamp\www/_webmagicdata/");
    }

    public OneFilePipeline(String path) throws FileNotFoundException, UnsupportedEncodingException {
        setPath(path);
        printWriter = new PrintWriter(new OutputStreamWriter(new FileOutputStream(getFile(path)), "UTF-8"));
    }

    @Override
    public synchronized void process(ResultItems resultItems, Task task) {
        printWriter.println("url:\t" + resultItems.getRequest().getUrl());
        for (Map.Entry<String, Object> entry : resultItems.getAll().entrySet()) {
            if (entry.getValue() instanceof Iterable) {
                Iterable value = (Iterable) entry.getValue();
                printWriter.println(entry.getKey() + ":");
                for (Object o : value) {
                    printWriter.println(o);
                }
            } else {
                new Jdbc();

                printWriter.println(entry.getKey() + ":\t" + entry.getValue());
                // 先儲存 再處理本地
                Jdbc.saveToMysql(Jdbc.parseData(entry.getValue()));
            }
        }
        printWriter.flush();
    }

    @Override
    public java.io.File getFile(java.lang.String fullName) {
        cnt++;
        System.out.println("fullname=" + fullName + cnt);
        return new File(fullName + cnt);

    }
}

模組劃分很清楚,不多說

一段很長的正則:

//////////////////////////////////////////////////////////////////////
1 獲取 正常微博文字
網頁程式碼

   <div class=\"WB_text W_f14\" node-type=\"feed_list_content\" nick-name=\"DwyaneWade\">\n                                                                                                    Game day! - 比賽日!                                            <\/div>

正則表示式

(?<=(<div\Wclass=\\"WB_text\WW_f14\\"\Wnode-type=\\"feed_list_content\\"\Wnick-name=\\"\w+\\">\\n)).*?(?=<(\\\/div>))

2 轉發別人的微博時,沒有nick-name=\”DwyaneWade\”
網頁程式碼

<div class=\"WB_text W_f14\" node-type=\"feed_list_content\" >\n                                                                                                    Single Days, end today. 脫單,就在今天。<a target=\"_blank\" render=\"ext\" suda-uatrack=\"key=topic_click&value=click_topic\" class=\"a_topic\" extra-data=\"type=topic\" href="http://weibo.com/p/1003062264358493/\""http:\/\/huati.weibo.com\/k\/%E5%93%88%E5%95%A4%E8%81%94%E7%9B%9F?from=501\">#哈啤聯盟#<\/a>                                            <\/div>\n

正則表示式

(?<=(<div\Wclass=\\"WB_text\WW_f14\\"\Wnode-type=\\"feed_list_content\\"\W((>\\\w)|(.{10}\\"\w{0,50}\\">\\n)))).*?(?=<(\\\/div>))
//////////////////////////////////////////////

Java String表示


"(?<=(<div\\Wclass=\\\\\"WB_text\\WW_f14\\\\\"\\Wnode-type=\\\\\"feed_list_content\\\\\"\\W((>\\\\\\w)|(.{10}\\\\\"\\w{0,50}\\\\\">\\\\n)))).*?(?=<(\\\\\\/div>))"

這麼長的正則效率可能略低,但提升了程式碼整潔度,而且由於xpath css無法使用,沒辦法的辦法

注意

log4j.properties檔案,webmagic呼叫了什麼必須有這個檔案包含才能顯示log日誌

# Configure logging for testing: optionally with log file
log4j.rootLogger=WARN, stdout
# log4j.rootLogger=WARN, stdout, logfile

log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%d %p [%c] - %m%n

log4j.appender.logfile=org.apache.log4j.FileAppender
log4j.appender.logfile.File=target/spring.log
log4j.appender.logfile.layout=org.apache.log4j.PatternLayout
log4j.appender.logfile.layout.ConversionPattern=%d %p [%c] - %m%n

end
略累
睡覺
20161119JJ401 16:24

相關推薦

網路爬蟲資料 本地資料庫儲存 遠端api分析 模型

序言 20161119 寫 一個星期多一點,在眾多的爬蟲框架中選擇了Webmagic,WebMagic簡單靈活的爬蟲框架。 簡單易用,在這之前用的是WebCollector JAVA爬蟲框架,它的模組劃分弄了一天也沒

python爬蟲ithome的新聞儲存本地資料庫

爬IT之家首頁的新聞,並讀取每篇新聞,並將新聞存到本地資料庫。 效率不是很高,請求各位大神指點。  from bs4 import BeautifulSoup import urllib.request import re import pymysql conn

網路爬蟲-指定城市空氣質量檢測資料

爬取指定城市空氣質量檢測資料 網站連結 → https://www.aqistudy.cn/historydata/ 以月資料為例,見下圖: 然後我們通過console除錯可以發現 這個網頁在items裡面已經將資料打包好了,如下圖所示 沒毛病,資料全都對得上,接下來的思

關於java實現需要登入且帶驗證碼的定時網路爬蟲(資料存庫)

 博主6月初的時候換了個工作,剛進來的時候什麼事沒有,愣是上班喝茶逛網站渡過了一週。那週週五的boss突然問我會不會爬蟲。 作為一個才工作一年的javaer表示根本沒接觸過,但是那種情況下你還敢說不會麼,但是當時也不敢說的很絕對,因此就和boss就會一點。 當時就隱隱約約有爬

python:爬蟲資料的處理之Json字串的處理(2)

#Json字串的處理 Json字串轉化為Python資料型別 import json JsonStr ='{"name":"sunck","age":"18","hobby":["money","power","English"],"parames":{"a":1,"b":2}}' Js

python :通過爬蟲資料(1)

(1)通過url爬取網頁資料 import urllib.request #指定url url ="https://www.baidu.com" #向伺服器發起請求,返回響應的資料,通過infor接收 infor = urllib.request.urlopen(url)

python網路爬蟲汽車之家的最新資訊和照片

實現的功能是爬取汽車之家的最新資訊的連結 題目和文章中的照片 爬蟲需要用到我們使用了 requests 做網路請求,拿到網頁資料再用 BeautifulSoup 進行解析 首先先檢查是否安裝了pip,如果已經安裝了pip,直接pip install requests,pip uninstal

Python爬蟲 資料存入MongoDB

from bs4 import BeautifulSoup import requests import time import pymongo client = pymongo.MongoClient('Localhost', 27017) ceshi = client[

一個簡單的網路爬蟲---網頁中的圖片

這裡貼上py原始碼,這個爬蟲很簡單,爬取網頁的圖片,通過正則表示式匹配對應的圖片的url 然後下載之,基本上也沒有什麼容錯處理,僅供學習之用 # -*- coding: utf-8 -*-       import urllib2   import urllib   im

用python寫網路爬蟲-新浪微博評論

新浪微博需要登入才能爬取,這裡使用m.weibo.cn這個移動端網站即可實現簡化操作,用這個訪問可以直接得到的微博id。 分析新浪微博的評論獲取方式得知,其採用動態載入。所以使用json模組解析json程式碼 單獨編寫了字元優化函式,解決微博評論中的嘈雜干擾

爬蟲資料時各種中文亂碼問題

學爬蟲有一段時間了,期間總是覺得內容編碼會傻傻分不清楚,尤其是直接網頁拿資料的時候,遇見中文有時候特別麻煩,看大神介紹的東西太多,只記下了處理方式,僅供參考,不對地方歡迎大家指正~~ 一般請求返回內容編碼方式步驟如下: 1、檢視資料來源網頁的編碼形式--爬取資料所在網頁原始碼就有寫: 2

網路爬蟲新浪新聞----Python網路爬蟲實戰學習筆記

今天學完了網易雲課堂上Python網路爬蟲實戰的全部課程,特在此記錄一下學習的過程中遇到的問題和學習收穫。 我們要爬取的網站是新浪新聞的國內版首頁 下面依次編寫各個功能模組 1.得到某新聞頁面下的評論數 評論數的資料是個動態內容,應該是存在伺服器

學會用python網路爬蟲鬥圖網的表情包,聊微信再也不怕鬥圖了

最近總是有人跟我鬥圖,想了想17年中旬時在網上看過一篇關於爬取鬥圖網表情包的py程式碼,但是剛想爬的時候發現網頁結構發生了變化,而且鬥圖網還插入了很多廣告,變化其實挺大的,所以臨時寫了一個爬蟲,簡單的爬取了鬥圖網的表情包。從這連結上看,page表示的是第幾頁,我

python網路爬蟲房價資訊

爬取房天下(http://newhouse.cd.fang.com/house/s/)成都地區的新房資訊。開啟http://newhouse.cd.fang.com/house/s/,F12進入控制檯點選控制檯的左上角的按鈕,這是你可以將滑鼠移至房天下頁面的任何一個地方然後單

網路爬蟲該網頁所有頁碼的所有圖片

import urllib.request import time import re global x # 使用前初次宣告 x=1 #獲取網頁的html,與requests包一樣的功能 def getHtml(url): #開啟網頁 pag

用python的matplotlib和numpy庫繪製股票K線均線的整合效果(含從網路介面資料和驗證交易策略程式碼)

    本人最近在嘗試著發表“以股票案例入門Python程式語言”系列的文章,在這些文章裡,將用Python工具繪製各種股票指標,在講述各股票指標的含義以及計算方式的同時,驗證基於各種指標的交易策略,本文是第一篇,通過K線和均線案例講述Numpy,Maplotlib

Python爬蟲-利用百度地圖API介面資料儲存至MySQL資料庫

首先,我這裡有一份相關城市以及該城市的公園數量的txt檔案: 其次,利用百度地圖API提供的介面爬取城市公園的相關資訊。 所利用的API介面有兩個: 1、http://api.map.baidu.com/place/v2/search?q=公園&

Python網路爬蟲之股票資料Scrapy爬蟲例項介紹,實現與優化!(未成功生成要的內容!)

結果TXT文本里面竟然沒有內容!cry~ 編寫程式: 步驟: 1. 建立工程和Spider模板 2. 編寫Spider 3. 編寫ITEM Pipelines 程式碼:成功建立 D:\>cd pycodes D:\pycodes>

scrapy-redis例項,分佈爬蟲騰訊新聞,儲存資料庫

本篇文章為scrapy-redis的例項應用,原始碼已經上傳到github: https://github.com/Voccoo/NewSpider 使用到了: python 3.x redis scrapy-redis pymysql Redis-Desktop-Manage

JAVA爬蟲網頁資料資料庫中,並且去除重複資料

pom檔案 <!-- 新增Httpclient支援 --> <dependency> <groupId>org.apache.httpcomponents</groupId> <artifactId&