AO數據訪問
package dao; ? import java.sql.SQLException; import java.util.ArrayList; import java.util.List; import org.apache.commons.dbutils.QueryRunner; import org.apache.commons.dbutils.handlers.BeanListHandler; import org.apache.commons.dbutils.handlers.ScalarHandler; ? import utils.JdbcUtils; import utils.PageBean; import entity.Muli; ? public class MuliDao { // 創建QueryRunner對象 private QueryRunner qr = JdbcUtils.getQueryRuner(); ? // 查找全部信息列表 public List<Muli> listMuliAll() { String sql = "SELECT * FROM mulihuji "; try { // 多行數據,封裝成對象的集合 List<Muli> listmuli = qr.query(sql, new BeanListHandler<Muli>(Muli.class)); return listmuli; } catch (Exception e) { throw new RuntimeException(e); } } // 分頁顯示全部數據 public void listMuliAll(PageBean<Muli> pb,Muli muli) throws SQLException { ? String countsql = "select count(*) from mulihuji where 1=1"; String sql = "select * from mulihuji where 1=1"; List<Object> params = new ArrayList<Object>(); // 添加查詢條件 String xm = muli.getXm(); if (xm != null && xm != "") { countsql += " and xm like ?"; sql += " and xm like ?"; params.add("%" + xm + "%"); } String sfzh = muli.getSfzh(); if (sfzh != null && sfzh != "") { countsql += " and sfzh like ?"; sql += " and sfzh like ?"; params.add("%" + sfzh + "%"); } //得到總記錄數 Long count = qr.query(countsql, new ScalarHandler<Long>(),params.toArray()); pb.setTotalCount(count.intValue()); /* * 問題: jsp頁面,如果當前頁為首頁,再點擊上一頁報錯! 如果當前頁為末頁,再點下一頁顯示有問題! 解決: 1. 如果當前頁 <= 0; * 當前頁設置當前頁為1; 2. 如果當前頁 > 最大頁數; 當前頁設置為最大頁數 */ // 判斷 if (pb.getCurrentPage() <= 0) { pb.setCurrentPage(1); // 把當前頁設置為1 } else if (pb.getCurrentPage() > pb.getTotalPage()) { pb.setCurrentPage(pb.getTotalPage()); // 把當前頁設置為最大頁數 } ? // 1. 獲取當前頁: 計算查詢的起始行、返回的行數 int currentPage = pb.getCurrentPage(); int index = (currentPage - 1) * pb.getPageCount(); // 查詢的起始行 int pagecount = pb.getPageCount(); // 每頁的行數 sql += " limit ?,?"; params.add(index); params.add(pagecount); List<Muli> pageData = qr.query(sql, new BeanListHandler<Muli>(Muli.class),params.toArray() ); //獲取一頁的數據 // 設置到pb對象中 pb.setPageData(pageData); ? } ? } ?
Servlet設計
package servlet; ? import java.io.IOException; import java.sql.SQLException; ? import javax.servlet.ServletException; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; ? ? import dao.MuliDao; import entity.Muli; import utils.PageBean; ? /** * Servlet implementation class QueryListMuliServlet */ @WebServlet("/querymuli") public class QueryListMuliServlet extends HttpServlet { private static final long serialVersionUID = 1L; ? /** * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response) */ protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { request.setCharacterEncoding("utf-8"); response.setCharacterEncoding("utf-8"); String xm = request.getParameter("xm"); String sfzh = request.getParameter("sfzh"); //實例化實體類并賦值 Muli muli=new Muli(); muli.setXm(xm); muli.setSfzh(sfzh); //1. 獲取“當前頁”參數; (第一次訪問當前頁為null) String currPage = request.getParameter("currentPage"); // 判斷 if (currPage == null || "".equals(currPage.trim())){ currPage = "1"; // 若第一次訪問,設置當前頁為1; } // 轉換為整數型 int currentPage = Integer.parseInt(currPage); //實例化pageben類 PageBean<Muli> pb = new PageBean<Muli>(); pb.setCurrentPage(currentPage); try { //調用數據訪問的方法,傳遞兩個參數 MuliDao mulidao = new MuliDao(); mulidao.listMuliAll(pb,muli); request.setAttribute("pageBean", pb); request.getRequestDispatcher("/querylist.jsp").forward(request, response); return; } catch (SQLException e) { e.printStackTrace(); request.setAttribute("errorMsg", e.getMessage()); } request.getRequestDispatcher("/error.jsp").forward(request, response); } ? /** * @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); } ? }
JSP頁面:分為兩個頁面,1.提交查詢條件,2.返回查詢結果
期,應客戶要求,采集一個舊后臺管理系統中的數據列表,并將數據詳情保存為HTML文件,舊平臺架構為.NET 4.0+easyui,數據列為GridView,這個任務的難點是GridView分頁數據抓取的問題,因為切換分頁的時候,瀏覽器的URL是無變化的,包括HTTP請求頭部、請求參數、請求URL全是一樣,采用常規的方式抓取肯定是行不通的(只能采集到第一頁的數據),下面看看我是如何獲取分頁數據。
廢話不多說,直接上代碼:
我是基于BeautifulSoup+requests+python3.7實現數據的抓取;
首先設置頭部信息,用于保證會話和授權:
headers = {
'User-Agent': 'Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 10.0; WOW64; Trident/8.0; .NET4.0C; .NET4.0E)',
'Accept': 'text/html, application/xhtml+xml, image/jxr, */*',
'Content-Type': 'application/x-www-form-urlencoded',
'Accept-Language': 'zh-CN',
'Host': '瀏覽器F12,根據實際情況填寫',
'Cache-Control': 'no-cache',
'Referer': '瀏覽器F12,根據實際情況填寫',
'Cookie': 'ASP.NET_SessionId=瀏覽器F12,根據實際情況填寫'
}
封裝網絡請求:
def postRequest(url, encoding='utf8', pageno=1):
data = {
'__EVENTTARGET': 'DataPager1',
'__EVENTARGUMENT': f'{pageno}',
'__LASTFOCUS': '',
'GridView1_gesoft_hidScrollOffset': '0,0',
'__VIEWSTATEENCRYPTED': '',
'__VIEWSTATE':'這個必須要填寫,否則實現不了分頁查詢數據',
'__EVENTVALIDATION': '可選,盡量填上',
'HidAddInspectID': '',
'SCAccept$ValueField': '48:105,110,99,108,117,100,101::97,110,100:115,116,114,105,110,103',
'DataPager1_input': f'{pageno}',
'DataPager1$pageSizeList': '10',
'DdlAuthorYear': 'ALL'
}
retryFlag = True
while retryFlag:
retryFlag = False
try:
response = requests.post(url=url, data=data, headers=headers, timeout=10)
response.encoding = encoding
return response
except Exception as e:
print(f'postRequest error({url}) ', e)
retryFlag = True
time.sleep(5)
上述代碼中“__VIEWSTATE”參數配置是核心中的核心,這個數據怎么獲取呢,我是通過Wireshark抓包工具獲取,如下圖所示:
請求參數如圖所示
為了提高數據采集的穩定性,網絡請求增加了超時重試機制。另外特別提醒,請求一定要設置超時時間,否則會導致任務阻塞。
好了,核心部分已經講完,至于采集到的數據如何用BeautifulSoup進行處理,大家自行在網上查找相關資料,比較簡單就不再贅述了。
列表顯示數據時,分頁顯示是必不可少的功能,活不多說,直接干貨拿走,django提供了一個分頁器Paginator,下面的例子說明如何使用它。
1,寫一個帶分頁功能的查詢方法
編輯 myweb\web\views.py文件,加入如下代碼
from models import Tasks
from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger
from django.views.decorators import csrf
#任務列表
def task_list(request):
contact_list = Tasks.objects.all().order_by('-task_start_date')
#每頁顯示25條
paginator = Paginator(contact_list, 25)
page = request.GET.get('page')
try:
contacts = paginator.page(page)
except PageNotAnInteger:
contacts = paginator.page(1)
except EmptyPage:
contacts = paginator.page(paginator.num_pages)
return render(request, 'taskList.html', {'contacts': contacts})
這里是將數據返回到前端頁面 taskList.html頁面。
2,前端頁面獲取并顯示數據
在myweb\web\templates目錄新建一個taskList.html文件,內容如下:
{% extends 'base.html' %}
{% block content %}
<table class="tableList">
<thead>
<tr>
<th>任務名稱</th>
<th>操作者</th>
<th>任務描述</th>
<th>開始日期</th>
<th>結束日期</th>
<th>任務評價</th>
</tr>
</thead>
<tbody>
{% if contacts.paginator.count > 0 %}
{% for contact in contacts %}
<tr>
<td> {{ contact.task_name }} </td>
<td> {{ contact.task_user }} </td>
<td> {{ contact.task_describe }}</td>
<td> {{ contact.task_start_date }} </td>
<td> {{ contact.task_end_date }} </td>
<td> {{ contact.task_result }}</td>
</tr>
{% endfor %}
{% else %}
<tr>
<td colspan="10" align="center">沒有任務數據</td>
</tr>
{% endif %}
</tbody>
</table>
{# 分頁HTML代碼 #}
<div class="pagination">
<span class="step-links">
{% if contacts.has_previous %}
<a href="?page={{ contacts.previous_page_number }}">上一頁</a>
{% endif %}
<span class="current">
Page {{ contacts.number }} of {{ contacts.paginator.num_pages }}.
</span>
{% if contacts.has_next %}
<a href="?page={{ contacts.next_page_number }}">下一頁</a>
{% endif %}
</span>
</div>
{% endblock %}
3,URL映射
編輯urls.py文件,加入:
url(r'^tasklist/', views.task_list),
*請認真填寫需求信息,我們會在24小時內與您取得聯系。