利用Eclipse-Python簡單爬取京東商城書籍資訊進行視覺化
【實驗目的】
- 熟悉從網上爬取資料到將資料進行視覺化的全部流程,通過例項瞭解並掌握每個過程。
- 瞭解爬蟲爬取資料的原理,並選擇一種語言程式設計,將資料獲取到資料庫。
- 熟練使用 eclipse 中 Java 語言操作資料庫資料。
- 瞭解 ECharts 中各種圖的特性,選取合適的圖將所獲取到的資料進行視覺化展示。
【實驗原理】
爬蟲爬取資料原理:
網路爬蟲是捜索引擎抓取系統的重要組成部分。爬蟲的主要目的是將網際網路上的網頁下載到本地形成一個或聯網內容的映象備份。一個通用的網路爬蟲的框架如圖所示:
網路爬蟲的基本工作流程如下:
- 首先選取一部分精心挑選的種子URL;
- 將這些URL放入待抓取URL佇列;
- 從待抓取URL佇列中取出待抓取在URL,解析DNS,並且得到主機的ip,並將URL對應的網頁下載下來,儲存進已下載網頁庫中。此外,將這些URL放進已抓取URL佇列。
- 分析已抓取URL佇列中的URL,分析其中的其他URL,並且將URL放入待抓取URL佇列,從而進入下一個迴圈。
本次實驗只是簡單的獲取商城中書籍的價格以及名稱,所以只需要寫相應獲取資料的程式碼就行,並沒有迴圈抓取網頁中相關連結以獲取更多資料。
操作資料庫原理:
新建servlet,通過JDBC連線資料庫進行查詢。
ECharts實現原理:
echarts頁面的開發主要有兩部步:
- 設定一個存放圖示的div;
- 呼叫畫圖方法進行畫圖;
初始化將要存放echarts圖表的DOM物件(div);
myChart = echarts.init(document.getElementById(‘main’));
編寫echarts圖表需要的屬性(option);
var options = { …… };
將屬性注入圖表
myChart.setOption(options);
【實驗環境】
Eclipse 4.5.1
作業系統 win7 64位
MySQL服務
Navicat for MySQL 視覺化工具
Python 2.7.13 (Anaconda2 4.3.1 64-bit)
Python 2.7 MySQL-python-1.2.3
tomcat伺服器
【實驗內容】
- 啟動MySQL服務,使用MySQL視覺化工具建立資料庫,名為python,新建表 ajax_table 和
python_table,在兩張表中包含主鍵id(設定為自增),書籍名稱 bookName,書籍價格 bookPrice。
- 現從京東商城中使用python工具獲取ajax書籍以及python書籍的書籍名稱和書籍價格。
使用eclipse完成資料庫訪問,獲取資料庫兩張表中的資料。
將獲取到的資料使用ECharts中南丁格爾圖展示出來,效果如下:
【實驗步驟】下載Python工具。
(1)進入Anaconda2下載相應系統相應版本的Python工具。
(3)進入PyDev外掛下載eclipse中的python外掛
安裝eclipse外掛
(1)把下載後的pydev壓縮包內的plugins和features資料夾內的內容複製到eclipse的解壓目錄的相應資料夾中,重啟eclipse。(2)開啟eclipse中的選單window,選擇Preference.找到左側邊欄的pydev,展開,點選Interpreters->Python Interpreter
(3)點選new,找到python安裝路徑, ok就行了
利用工具爬取資料
(1)開啟命令視窗(cmd),輸入如下命令,會自動開啟瀏覽器,點選右上角
new->python2,會進入命令列模式,這裡你可以測試程式碼,檢視你爬取的資料是否是你想要的:jupyter notebook
(2)輸入以下程式碼,按ctrl+回車,你將看到相應資料,爬取成功#coding:utf8 import urllib2 from bs4 import BeautifulSoup root_url="http://search.jd.com/Search?keyword=Python&enc=utf-8&book=y&wq=Python&pvid=33xo9lni.p4a1qb" response = urllib2.urlopen(root_url) html_cont = response.read() soup = BeautifulSoup(html_cont,'html.parser', from_encoding='utf-8') res_data = {} links = soup.select('.gl-i-wrap') count = 1 for link in links: if count <= 10: res_data['name']=link.select(".p-name a em")[0].text res_data['price']=float(link.select(".p-price strong i")[0].text) print res_data['name'] count = count +1
(3)新建一個PyDev工程,取名為 bookprice
(4)建立包取名為 book_spider,右擊包名 ->new->PyDev Module,取名python_book(ajax_book)。寫一個主函式,將測試好的程式碼貼上進去,並新增對python對資料庫的操作,這樣就將所爬取得資料寫進了資料庫中(我這裡限制爬取個數為10條,並且這只是獲取到了Python書籍的書籍,進行相同操作獲取ajax資料)#coding:utf8 import MySQLdb import urllib2 from bs4 import BeautifulSoup if __name__=="__main__": root_url="http://search.jd.com/Search?keyword=Python&enc=utf-8&book=y&wq=Python&pvid=33xo9lni.p4a1qb" response = urllib2.urlopen(root_url) conn = MySQLdb.Connect(host='127.0.0.1', user='hive', passwd='123456', port=3306, charset='utf8', db='python') cursor = conn.cursor() html_cont = response.read() soup = BeautifulSoup(html_cont,'html.parser', from_encoding='utf-8') res_data = {} links = soup.select('.gl-i-wrap') count = 1 for link in links: if count <= 10: res_data['name']=link.select(".p-name a em")[0].text res_data['price']=float(link.select(".p-price strong i")[0].text) try: sql = "insert into python_table(bookName,bookPrice) values('%s',%f)" % (res_data['name'],res_data['price']) cursor.execute(sql) conn.commit() except: print 'craw failed' count = count-1 count=count+1 cursor.close() conn.close()
4. 切換工作環境,改為javaEE
新建動態WEB專案,取名為 book ,在 Java Resources->src 中建立四個包(cn.lk.Dao , cn.lk.DBUtil , cn.lk.Servlet , cn.lk.VO), 在 WebContent 中建立一個名為 book.jsp 的檔案,分別實現各個模組程式碼的實現
(1)在 cn.lk.VO 中建立實體類,命名為 Book.java 。開啟 Book.java 頁面,編寫實體類程式碼(屬性名及資料型別與建表時一致)
```
package cn.lk.VO;
public class Book {
private String bookName;
private float bookPrice;
public String getBookName() {
return bookName;
}
public void setBookName(String bookName) {
this.bookName = bookName;
}
public float getBookPrice() {
return bookPrice;
}
public void setBookPrice(float bookPrice) {
this.bookPrice = bookPrice;
}
@Override
public String toString() {
return "book [bookName=" + bookName + ", bookPrice=" + bookPrice + "]";
}
public Book(String bookName, float bookPrice) {
super();
this.bookName = bookName;
this.bookPrice = bookPrice;
}
public Book(){}
}
```
(2)在cn.lk.DBUtil中建立類DBUtil.java,編寫程式碼(實現與資料庫的連線)
```
package cn.lk.DBUtil;
import java.sql.DriverManager;
import java.sql.SQLException;
import com.mysql.jdbc.Connection;
public class DBUtil {
private static final String DBDriver="org.gjt.mm.mysql.Driver";
private static final String DBURl="jdbc:mysql://localhost:3306/python";
private static final String DBUser="hive";
private static final String DBPassword="123456";
private static Connection conn=null;
static{
try {
Class.forName(DBDriver);
conn=(Connection) DriverManager.getConnection(DBURl,DBUser,DBPassword);
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public void labManageDButil(){
}
public static Connection getConnection(){
return conn;
}
public void close(){
if(conn!=null){
try {
conn.close();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
```
(3)在cn.lk.Dao包中建立類BookDao.java ,編寫程式碼(實現對資料庫的查詢操作)
```
package cn.lk.Dao;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
import com.mysql.jdbc.Connection;
import com.mysql.jdbc.Statement;
import cn.lk.DBUtil.DBUtil;
import cn.lk.VO.Book;
public class BookDao {
public List<Book> getPythonData(){
Connection conn = DBUtil.getConnection();
String sql = "select bookName,bookPrice from python_table;";
ResultSet set = null;
Statement stmt = null;
List<Book> list = new ArrayList<Book>();
try {
stmt = (Statement) conn.createStatement();
set = stmt.executeQuery(sql);
while (set.next()) {
Book bean = new Book();
bean.setBookName(set.getString("bookName"));
bean.setBookPrice(set.getFloat("bookPrice"));
list.add(bean);
}
} catch (SQLException e) {
System.err.println(e.getMessage());
}
return list;
}
public List<Book> getAjaxData(){
Connection conn = DBUtil.getConnection();
String sql = "select bookName,bookPrice from ajax_table;";
ResultSet set = null;
Statement stmt = null;
List<Book> list = new ArrayList<Book>();
try {
stmt = (Statement) conn.createStatement();
set = stmt.executeQuery(sql);
while (set.next()) {
Book bean = new Book();
bean.setBookName(set.getString("bookName"));
bean.setBookPrice(set.getFloat("bookPrice"));
list.add(bean);
}
} catch (SQLException e) {
System.err.println(e.getMessage());
}
return list;
}
}
```
(4)在cn.lk.Servlet包中建立類BookServlet.java ,實現程式碼(呼叫方法將Dao層獲取到的資料傳到 jps 介面 )
```
package cn.lk.Servlet;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.List;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import com.alibaba.fastjson.JSON;
import cn.lk.Dao.BookDao;
import cn.lk.VO.Book;
/**
* Servlet implementation class PieServlet
*/
public class BookServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
/**
* @see HttpServlet#HttpServlet()
*/
public BookServlet() {
super();
// TODO Auto-generated constructor stub
}
/**
* @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
*/
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// TODO Auto-generated method stub
response.setContentType("text/html;charset=utf-8");
BookDao pd = new BookDao();
List<Book> python = pd.getPythonData();
List<Book> ajax = pd.getAjaxData();
String jsonString = JSON.toJSONString(python);
String jsonString_Java = "#"+JSON.toJSONString(ajax);
System.err.println(jsonString);
//System.err.println(jsonString_Java);
PrintWriter out = response.getWriter();
out.print(jsonString);
out.print(jsonString_Java);
System.out.println(python.toString());
System.out.println(ajax.toString());
out.flush();
out.close();
}
/**
* @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
*/
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// TODO Auto-generated method stub
doGet(request, response);
}
}
```
(5)開啟WebContent->WEB-INF 中的web.xml,配置相關對映,程式碼如下:
```
<?xml version="1.0" encoding="UTF‐8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" version="3.0">
<display‐name></display‐name>
<servlet>
<servlet-name>BookServlet</servlet-name>
<servlet-class>cn.lk.Servlet.BookServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>BookServlet</servlet-name>
<url-pattern>/BookServlet</url-pattern>
</servlet-mapping>
</web‐app>
```
(6)匯入相應JAR包與JS包
在lib目錄中複製進去相應JAR包,在WebContent中建立目錄echarts,將所需js包放入即可
(7)在jps介面編寫程式碼(獲取傳過來的資料,並使用ECharts技術,實現南丁格爾圖視覺化)
```
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%
String path = request.getContextPath();
String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<base href="<%=basePath%>">
<title></title>
<script type="text/javascript" src="echarts/jquery-2.1.4.min.js"></script>
<script type="text/javascript" src="echarts/echarts.min.js"></script>
</head>
<body>
<div id="main" style="width: 100%;height:100%; "></div>
</body>
<script type="text/javascript">
// 基於準備好的dom,初始化echarts例項
var myChart = echarts.init(document.getElementById('main'));
// 指定圖表的配置項和資料
myChart.setOption({
title : {
text: '書籍價格',
subtext: '來自京東',
x:'center'
},
tooltip : {
trigger: 'item',
formatter: '{a} <br/>{b} : {c} ({d}%)'
},
legend: {
orient: 'vertical',
left: 'right',
data: []//不修改,從資料庫調取
},
series : [
{
name:'python',
type: 'pie',
radius : [30,110],
center: ['25%', '30%'],
data:[],//不修改,從資料庫調取
roseType : 'radius',
itemStyle: {
emphasis: {
shadowBlur: 10,
shadowOffsetX: 0,
shadowColor: 'rgba(0, 0, 0, 0.5)'
}
}
},
{
name:'ajax',
type: 'pie',
radius : [30,110],
center: ['25%', '80%'],
data:[],//不修改,從資料庫調取
roseType : 'radius',
itemStyle: {
emphasis: {
shadowBlur: 10,
shadowOffsetX: 0,
shadowColor: 'rgba(0, 0, 0, 0.5)'
}
}
}
]
});
// 非同步載入資料
var python_price = [];
var python_name = [];
var ajax_price = [];
var ajax_name = [];
var python = [];
var ajax = [];
$.post("./BookServlet", function(datas){
//alert(datas)
var arr = datas.split("#");
/*for(var i=0;i<arr.length;i++){
alert(arr[i])
} */
var pythons = JSON.parse(arr[0]);
var ajaxs = JSON.parse(arr[1]);
for(var m=0;m<pythons.length;m++){
python_name.push(pythons[m].bookName);
python.push({"name":pythons[m].bookName,"value":pythons[m].bookPrice});
python_price.push(pythons[m].bookPrice);
}
for(var n=0;n<ajaxs.length;n++){
ajax_name.push(ajaxs[n].bookName);
ajax.push({"name":ajaxs[n].bookName,"value":ajaxs[n].bookPrice});
ajax_price.push(ajaxs[n].bookPrice);
}
for(var i=0;i<ajax_name.length;i++){
python_name.push(ajax_name[i])
}
// 填入資料
myChart.setOption({
legend: {
//類別
data: python_name
},
series: [{
// 根據名字對應到相應的系列
data: python
},{
data: ajax
}]
});
// 使用剛指定的配置項和資料顯示圖表。
});
</script>
</html>
```
(8)tomcat伺服器上執行book.jsp檔案,將連結複製到瀏覽器中,檢視效果圖