基于python的单词查询
本篇博客是对我python网络编程所学知识的运用及总结。以下是具体内容:
1、 采用HTTP客户端的Python库(如request或urllib等)编写HTTP客户端爬虫,爬取某个网站的指定数据,并将获取的数据整理成自己的格式。
2、 采用HTTP服务器框架(Flask或Django)编写Web站点,对第一部爬去的数据进行展示。(也可以将第一步的代码结合,根据用户的请求再去爬取数据,然后将爬取的数据通过网站展示出来)
爬取数据案例:
单词查询
- 先抓包分析一些查询不同单词请求的URL的区别,返回的页面有用内容的格式及使用正则等方法提取的规则。
- 第1步:可以让用户的输入单词,从网站爬取该单词对应的释义、例句、甚至发音等信息,展示到屏幕上。
- 第2步:在第一步的基础上,设计一个站点,用户输入一个单词,实时爬取该单词对应的释义、例句、甚至发音等信息,生成页面并返回给浏览器。
当博主看到这个题目的时候,突然想起来自己六级还没有过,痛心中。。。 这里我选择爬取的是http://dict.cn。这是一个单词查询网站,当输入英文单词时,会输出单词的词性、音标、发音以及例句等。具体如下:说干就干,我的大致思路是这样的:用户先在我搭建的网站上输入要查询的单词,后台获取单词后去dict.cn查询,并将查询结果通过爬虫爬取,整理成Json字符串格式返回给我网站的前端,前端将Json格式对象化后输出。
所选用的Python库介绍
(以下只是简单介绍,以后可能会对应这一系列的库写相应的博客,先占个坑)
1.Flask
Flask是一个基于Python开发并且依赖jinja2模板和Werkzeug WSGI服务的一个微型框架,对于Werkzeug本质是Socket服务端,其用于接收http请求并对请求进行预处理,然后触发Flask框架,开发人员基于Flask框架提供的功能对请求进行相应的处理,并返回给用户,如果要返回给用户复杂的内容时,需要借助jinja2模板来实现对模板的处理,即:将模板和数据进行渲染,将渲染后的字符串返回给用户浏览器。
2.bs4
BeautifulSoup是一种非常优雅的专门用于进行HTML/XML数据解析的一种描述语言,可以很好的分析和筛选HTML/XML这样的标记文档中的指定规则数据在数据筛选过程中其基础技术是通过封装HTML DOM树实现的一种DOM操作,通过加载网页文档对象的形式,从文档对象树模型中获取目标数据。
3.json
json数据解析库。
4.urllib
urllib提供了一系列用于操作URL的功能。
爬虫设计
爬虫分为三个子模块,第一个名为get_page(),向dict.cn发送查询单词的请求,用于获取页面数据;第二个get_wordmeaning()提取返回响应的数据,并根据网页规则获取单词释义;get_phonetic_pronunciation()用来提取返回响应的数据,并根据网页规则获取单词释义获取单词的音标和读音。最后get_word()函数调用子模块,实现指定单词的爬取并返回json格式,方便前端处理展示。
Web站点设计
因为重点是爬虫的编写,所以我这次编写的Web站点的功能比较简单,即返回单词响应的结果。因此就一个标题,一个输入框以及一个提交按钮。为了美观,我将这三者放在一个
程序运行过程:
运行flask.py,并在浏览器输入localhost+端口号。
输入单词并查询:
总结
在完成这次Web站点爬取任务中,我学会的主要是下面几点:1.爬虫的编写 2.对flask框架的理解以及应用 3.javascript对后台返回的数据进行处理。在编写爬虫时,我先用了etree来对网页内容进行提取,但是因为要爬取的网页不规范或者自身水平不够,因而转向使用bs4(对于我来说,bs4已经够用了,etree也是一个提取html标签元素的库,使用者若是熟练dom树的话肯定是使用etree会更加得心应手)。因此就正常获取到了要爬取的数据;flask框架我学到的主要是路由这一概念。用户在请求对应的页面即url发生变化时,就会触发flask的路由功能,执行对应的函数;在使用js处理后台数据时,一开始不论怎么添加音频都是失败的,后来解决了以下两个问题后,成功:1.添加audio标签,通过动态添加src并设置鼠标事件实现播放功能2.后台传回的是json字符串,利用json.(str)将其转成json对象后就可以对应输出了。
源代码
"""
Routes and views for the flask application.
"""
from datetime import datetime
from flask import render_template
from FlaskWeb2 import app
import sys,os
import urllib.request
from bs4 import BeautifulSoup
import re
import time
from functools import reduce
import json
#获得页面数据
def get_page(myword):
basurl='http://dict.cn/'
searchurl=basurl+myword
response = urllib.request.urlopen(searchurl)
html = response.read()
return html
#获得单词释义
def get_wordmeaning(html_selector):
selector = BeautifulSoup(html_selector,"lxml")
#print(get_hanyi)
attribute = {}
word = {}
for item in selector.find_all('div',{'class':'layout detail'}):
for i in item.find_all('span'):#获取单词词性
attribute.setdefault('attribute',[]).append(i.get_text())
for i in item.find_all('ol'):#获取单词释义
word.setdefault('word',[]).append(i.get_text())
if len(word)>0 and len(attribute):
return attribute,word #返回词性、单词释义
else:
return ''
#获得单词音标和读音
def get_phonetic_pronunciation(html_selector):
phonetic={}
pronunciation={}
selector = BeautifulSoup(html_selector,"lxml")
result = selector.find_all('div',{'class':'phonetic'})
base_url = 'http://audio.dict.cn/'
i=1
for item in result:
for i in item.find_all('bdo',{'lang':'EN-US'}):#获取音标,
phonetic.setdefault('phonetic',[]).append(i.get_text())
#print(i.get_text())
#print(item.i['naudio'])
#print(item.i.attrs)
for a in item.find_all('i'):
pronunciation.setdefault('pronunciation',[]).append(base_url+a['naudio'])
if len(phonetic)>0 and len(pronunciation)>0:
return phonetic,pronunciation #返回音标、读音
else:
return " "
def get_word1(word):
#获得页面
pagehtml=get_page(word)
attribute = []
word = []
phonetic = []
pronunciation = []
#单词释义
attribute,word = get_wordmeaning(pagehtml)
#单词音标及读音
phonetic,pronunciation = get_phonetic_pronunciation(pagehtml)
attribute.update(word)
attribute.update(phonetic)
attribute.update(pronunciation)
return json.dumps(attribute)
@app.route('/getword/<word>')
def getword(word):
return format(get_word1(word))
@app.route('/user/<name>')
def user(name):
return '<h1>Hello, %s!</h1>' % name
if __name__ == '__main__':
app.run(debug=True)
@app.route('/home')
def home():
"""Renders the home page."""
return render_template(
'index.html',
title='Home Page',
year=datetime.now().year,
)
@app.route('/contact')
def contact():
"""Renders the contact page."""
return render_template(
'contact.html',
title='Contact',
year=datetime.now().year,
message='Your contact page.'
)
@app.route('/') //默认页面
def text():
return render_template(
'text.html',
title='search',
message='find words'
)
@app.route('/about')
def about():
"""Renders the about page."""
return render_template(
'about.html',
title='About',
year=datetime.now().year,
message='Your application description page.'
)
Web前端源码:search.html
<html>
<head>
<title>单词查询(数据源自dict.cn)</title>
<meta charset="UTF-8">
<style type="text/css">
*{
margin: 0;
padding: 0;
}
div{
width: 500px;
height: 500px;
border: 0px;
}
.center-in-center{
background-image: url('https://ss3.bdstatic.com/70cFv8Sh_Q1YnxGkpoWK1HF6hhy/it/u=3904922212,1268945217&fm=26&gp=0.jpg');
background-repeat:no-repeat;
position: absolute;
top: 50%;
left: 50%;
-webkit-transform: translate(-50%, -50%);
-moz-transform: translate(-50%, -50%);
-ms-transform: translate(-50%, -50%);
-o-transform: translate(-50%, -50%);
transform: translate(-50%, -50%);
}
</style>
<!--来自 https://www.jianshu.com/p/5a3cfcc764f5 -->
<script type="text/javascript">
xmlHttp = null;
var responseText= "";
function search(){
var word = document.getElementById("word1").value;
if (word.length==0)
{
document.getElementById("show").innerHTML="";
return;
}
try
{
xmlHttp=new XMLHttpRequest();
}
catch(e)
{// Old IE
try
{
xmlHttp=new ActiveXObject("Microsoft.XMLHTTP");
}
catch(e)
{
alert ("Your browser does not support XMLHTTP!");
return;
}
}
url="/getword/"+word;
xmlHttp.open("GET",url,false);
xmlHttp.send(null);
try <!—前端获取查询数据 –->
{
responseText = unescape(xmlHttp.responseText.replace(/\\u/g,"%u"));
responseText = JSON.parse(responseText);
<!--document.getElementById("show").innerHTML=responseText;-->
document.getElementById("show").innerHTML=responseText.attribute;
document.getElementById("show0").innerHTML=responseText.phonetic[0];
document.getElementById("show1").innerHTML=responseText.phonetic[1];
document.getElementById("show2").innerHTML=responseText.word;
}
catch(e)
{
document.getElementById("show").innerHTML="好像发生了一些错误,查询失败或是查询的单词不存在!"
}
var div = document.getElementById("audio");
div.setAttribute("src",responseText.pronunciation[0]);
}
</script>
</head>
<body>
<div class="center" style="width:100px; height:100px; ;">
<div class="center-in-center" ">
<h2>单词查询</h2>
<input type="text" id="word1" >
<input type="button" id="search" onClick="search()" value="搜索" x-webkit-speech>
<p>词性: <span id="show"></span></p>
<p>美式音标: <span id="show0"></span></p>
<p>英式音标: <span id="show1"></span></p>
<p>单词释义: <span id="show2"></span></p>
<audio id="audio" ></audio>
<button type="button" onclick="play1()">女生(英)</button>
<button type="button" onclick="play2()">男生(英)</button>
<button type="button" onclick="play3()">女生(美)</button>
<button type="button" onclick="play4()">男生(美)</button>
<script type="text/javascript">
function play1(){ <!--给audio标签添加语言来源-->
var div = document.getElementById("audio");
div.setAttribute("src",responseText.pronunciation[0]);
document.getElementById("audio").play();
}
function play2(){
var div = document.getElementById("audio");
div.setAttribute("src",responseText.pronunciation[1]);
document.getElementById("audio").play();
}
function play3(){
var div = document.getElementById("audio");
div.setAttribute("src",responseText.pronunciation[2]);
document.getElementById("audio").play();
}
function play4(){
var div = document.getElementById("audio");
div.setAttribute("src",responseText.pronunciation[3]);
document.getElementById("audio").play();
}
</script>
</div>
</div>
</body>
</html>