PythonWeb开发.复制别人的空白代码复制,在自己的电脑上却提示服务器找不到URL

[Python] 利用Django进行Web开发系列(二)
1 编写第一个静态页面——Hello world页面
  在上一篇博客中,我们创建了自己的目录mysite。
  Step1:创建视图文件
  在编写第一个页面之前,我们首先要在mysite目录下创建一个名称为views.py的文件。当然,命名是没有要求的,你也可以命名为a.py,b.py... ... 根据自己的喜好命名就行。在已创建好的views.py中写入如下代码,并保存:
from django.http import HttpResponse
def hello(request):
return HttpResponse(&Hello world! This is my first trial. [Poll的笔记]&)
  我们逐行分析一下这段代码:
  首先,我们从django.http模块导入HttpResponse类。
  接下来,我们定义一个叫做hello的视图函数。每个视图函数至少要有一个参数,通常被叫作request。这是一个触发这个视图、包含当前Web请求信息的对象,是类django.http.HttpResponse的一个实例。在这个示例中,我们虽然不用request做任何事情,然而它仍必须是这个视图的第一个参数。注意视图函数的名称并不重要;并不一定非得以某种特定的方式命名才能让Django识别它。
在这里我们把它命名为:hello,是因为这个名称清晰的显示了视图的用意。同样地,你可以用诸如:hello_wonderful_beautiful_world,这样难看的短句来给它命名。
  这个函数只有简单的一行代码: 它仅仅返回一个HttpResponse对象,这个对象包含了文本“Hello world”。
  在这里要记住的是:一个视图就是Python的一个函数。这个函数第一个参数的类型是HttpRequest;它返回一个HttpResponse实例。为了使一个Python的函数成为一个Django可识别的视图,它必须满足这两个条件。&
  Step2:进行URL配置
  现在,如果你再运行:python manage.py runserver,你还将看到Django的欢迎页面,而看不到我们刚才写的Hello world显示页面。 那是因为我们的mysite项目还对hello视图一无所知。我们需要通过一个详细描述的URL来显式的告诉它并且激活这个视图。为了绑定视图函数和URL,我们使用URLconf。 
  URLconf&就像是 Django 所支撑网站的目录。 它的本质是 URL 模式以及要为该 URL 模式调用的视图函数之间的映射表。 你就是以这种方式告诉 Django,对于这个 URL 调用这段代码,对于那个 URL 调用那段代码。 例如,当用户访问/foo/时,调用视图函数foo_view(),这个视图函数存在于Python模块文件view.py中。上一篇博文中执行django-admin.py&startproject时,该脚本会自动为你建了一份URLconf,即urls.py文件。
  如果想在URLconf中加入URL和view,只需增加映射URL模式和view功能的Python tuple即可. 这里演示如何添加view中hello功能。
from django.conf.urls import *
from mysite.views import hello
urlpatterns = patterns('',
('^hello/$', hello),
  我们逐行分析一下这段代码:
  首先,我们从模块中引入了hello视图。
  其实做一个Django-powered页面了,只需要写视图函数并用 URLconfs把它们和URLs对应起来就ok了。
2 编写第一个动态页面——current time页面
  我们的Hello world视图是用来演示基本的Django是如何工作的,但是它不是一个动态网页的例子,因为网页的内容一直是一样的. 每次去查看/hello/,你将会看到相同的内容,它类似一个静态HTML文件。在第二个例子里,博主通过一个显示当前时间的页面来简单示范一下动态页面。动态页面和静态页面的编写是一样的,两部分:创建视图和配置URL。
  视图文件views.py代码如下:
from django.http import HttpResponse
import time
def current_time(request):
return HttpResponse(&Current time is: &+time.strftime('%Y-%m-%d %H:%M:%S'))
  URLconf文件urls.py代码如下:
from django.conf.urls import *
from mysite.views import current_time
urlpatterns = patterns('',
('^current_time/$', current_time),
  然后我们通过网址http://127.0.0.1:8000/current_time/就可以看到编写的第一个动态页面了,它显示的内容是你访问该页面时的当前时间,如下图所示:
  看到这里,大家是不是感觉利用python Django进行Web开发真的很简单。当然,我们页面实在是太单薄了,不光没有啥模板科研,就连一些颜色都没有,哈哈,不过后边楼主会慢慢学习,并和大家分享经验。相信经过这系列的努力,最后一定可以随心所欲地设计出一个属于自己的完美的页面。
3 参考内容
  [1] Django book 第三章:
看过本文的人也看了:
我要留言技术领域:
取消收藏确定要取消收藏吗?
删除图谱提示你保存在该图谱下的知识内容也会被删除,建议你先将内容移到其他图谱中。你确定要删除知识图谱及其内容吗?
删除节点提示无法删除该知识节点,因该节点下仍保存有相关知识内容!
删除节点提示你确定要删除该知识节点吗?用Python实现一个简单的能够上传下载的HTTP服务器
&更新时间:日 09:14:45 & 作者:xrzs
这篇文章主要介绍了用Python实现一个简单的能够上传下载的HTTP服务器,是Python网络编程学习当中的基础,本文示例基于Windows操作系统实现,需要的朋友可以参考下
#!/usr/bin/env python
#coding=utf-8
# modifyDate:
# 原作者为:bones7456, http://li2z.cn/
# 修改者为:
# v1.2,changeLog:
# +: 文件日期/时间/颜色显示、多线程支持、主页跳转
# -: 解决不同浏览器下上传文件名乱码问题:仅IE,其它浏览器暂时没处理。
# -: 一些路径显示的bug,主要是 cgi.escape() 转义问题
# ?: notepad++ 下直接编译的server路径问题
简介:这是一个 python 写的轻量级的文件共享服务器(基于内置的SimpleHTTPServer模块),
支持文件上传下载,只要你安装了python(建议版本2.6~2.7,不支持3.x),
然后去到想要共享的目录下,执行:
python SimpleHTTPServerWithUpload.py 1234
其中1234为你指定的端口号,如不写,默认为 8080
然后访问 http://localhost:1234 即可,localhost 或者 1234 请酌情替换。
"""Simple HTTP Server With Upload.
This module builds on BaseHTTPServer by implementing the standard GET
and HEAD requests in a fairly straightforward manner.
__version__ = "0.1"
__all__ = ["SimpleHTTPRequestHandler"]
__author__ = "bones7456"
__home_page__ = ""
import os, sys, platform
import posixpath
import BaseHTTPServer
from SocketServer import ThreadingMixIn
import threading
import urllib, urllib2
import cgi
import shutil
import mimetypes
import time
from cStringIO import StringIO
except ImportError:
from StringIO import StringIO
def get_ip_address(ifname):
import socket
import fcntl
import struct
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
return socket.inet_ntoa(fcntl.ioctl(
s.fileno(),
0x8915, # SIOCGIFADDR
struct.pack('256s', ifname[:15])
class GetWanIp:
def getip(self):
myip = self.visit("http://ip.taobao.com/service/getIpInfo.php?ip=myip")
print "ip.taobao.com is Error"
myip = self.visit("http://www.bliao.com/ip.phtml")
print "bliao.com is Error"
myip = self.visit("http://www.whereismyip.com/")
except: # 'NoneType' object has no attribute 'group'
print "whereismyip is Error"
myip = "127.0.0.1"
return myip
def visit(self,url):
#req = urllib2.Request(url)
#values = {'User-Agent': 'Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.31 (KHTML, like Gecko) Chrome/26.0.1410.64 Safari/537',
'Referer': 'http://ip.taobao.com/ipSearch.php',
'ip': 'myip'
#data = urllib.urlencode(values)
opener = urllib2.urlopen(url, None, 3)
if url == opener.geturl():
str = opener.read()
return re.search('(\d+\.){3}\d+',str).group(0)
def showTips():
print '-----------------------------------------------------------------------&& '
port = int(sys.argv[1])
except Exception, e:
print '--------&& Warning: Port is not given, will use deafult port: 8080 '
print '--------&& if you want to use other port, please execute: '
print '--------&& python SimpleHTTPServerWithUpload.py port '
print "--------&& port is a integer and it's range: 1024 & port & 65535 "
port = 8080
if not 1024 & port & 65535: port = 8080
# serveraddr = ('', port)
print '--------&& Now, listening at port ' + str(port) + ' ...'
osType = platform.system()
if osType == "Linux":
print '--------&& You can visit the URL:
http://'+ GetWanIp().getip() + ':' +str(port)
print '--------&& You can visit the URL:
http://127.0.0.1:' +str(port)
print '-----------------------------------------------------------------------&& '
return ('', port)
serveraddr = showTips()
def sizeof_fmt(num):
for x in ['bytes','KB','MB','GB']:
if num & 1024.0:
return "%3.1f%s" % (num, x)
num /= 1024.0
return "%3.1f%s" % (num, 'TB')
def modification_date(filename):
# t = os.path.getmtime(filename)
# return datetime.datetime.fromtimestamp(t)
return time.strftime("%Y-%m-%d %H:%M:%S",time.localtime(os.path.getmtime(filename)))
class SimpleHTTPRequestHandler(BaseHTTPServer.BaseHTTPRequestHandler):
"""Simple HTTP request handler with GET/HEAD/POST commands.
This serves files from the current directory and any of its
subdirectories. The MIME type for files is determined by
calling the .guess_type() method. And can reveive file uploaded
by client.
The GET/HEAD/POST requests are identical except that the HEAD
request omits the actual contents of the file.
server_version = "SimpleHTTPWithUpload/" + __version__
def do_GET(self):
"""Serve a GET request."""
# print "....................", threading.currentThread().getName()
f = self.send_head()
self.copyfile(f, self.wfile)
def do_HEAD(self):
"""Serve a HEAD request."""
f = self.send_head()
def do_POST(self):
"""Serve a POST request."""
r, info = self.deal_post_data()
print r, info, "by: ", self.client_address
f = StringIO()
f.write('&!DOCTYPE html PUBLIC "-//W3C//DTD HTML 3.2 Final//EN"&')
f.write("&html&\n&title&Upload Result Page&/title&\n")
f.write("&body&\n&h2&Upload Result Page&/h2&\n")
f.write("&hr&\n")
f.write("&strong&Success:&/strong&")
f.write("&strong&Failed:&/strong&")
f.write(info)
f.write("&br&&a href=\"%s\"&back&/a&" % self.headers['referer'])
f.write("&hr&&small&Powered By: bones7456, check new version at ")
f.write("&a href=\"http://li2z.cn/?s=SimpleHTTPServerWithUpload\"&")
f.write("here&/a&.&/small&&/body&\n&/html&\n")
length = f.tell()
self.send_response(200)
self.send_header("Content-type", "text/html")
self.send_header("Content-Length", str(length))
self.end_headers()
self.copyfile(f, self.wfile)
def deal_post_data(self):
boundary = self.headers.plisttext.split("=")[1]
remainbytes = int(self.headers['content-length'])
line = self.rfile.readline()
remainbytes -= len(line)
if not boundary in line:
return (False, "Content NOT begin with boundary")
line = self.rfile.readline()
remainbytes -= len(line)
fn = re.findall(r'Content-Disposition.*name="file"; filename="(.*)"', line)
if not fn:
return (False, "Can't find out file name...")
path = self.translate_path(self.path)
osType = platform.system()
if osType == "Linux":
fn = os.path.join(path, fn[0].decode('gbk').encode('utf-8'))
fn = os.path.join(path, fn[0])
except Exception, e:
return (False, "文件名请不要用中文,或者使用IE上传中文名的文件。")
while os.path.exists(fn):
line = self.rfile.readline()
remainbytes -= len(line)
line = self.rfile.readline()
remainbytes -= len(line)
out = open(fn, 'wb')
except IOError:
return (False, "Can't create file to write, do you have permission to write?")
preline = self.rfile.readline()
remainbytes -= len(preline)
while remainbytes & 0:
line = self.rfile.readline()
remainbytes -= len(line)
if boundary in line:
preline = preline[0:-1]
if preline.endswith('\r'):
preline = preline[0:-1]
out.write(preline)
out.close()
return (True, "File '%s' upload success!" % fn)
out.write(preline)
preline = line
return (False, "Unexpect Ends of data.")
def send_head(self):
"""Common code for GET and HEAD commands.
This sends the response code and MIME headers.
Return value is either a file object (which has to be copied
to the outputfile by the caller unless the command was HEAD,
and must be closed by the caller under all circumstances), or
None, in which case the caller has nothing further to do.
path = self.translate_path(self.path)
if os.path.isdir(path):
if not self.path.endswith('/'):
# redirect browser - doing basically what apache does
self.send_response(301)
self.send_header("Location", self.path + "/")
self.end_headers()
return None
for index in "index.html", "index.htm":
index = os.path.join(path, index)
if os.path.exists(index):
path = index
return self.list_directory(path)
ctype = self.guess_type(path)
# Always read in binary mode. Opening files in text mode may cause
# newline translations, making the actual size of the content
# transmitted *less* than the content-length!
f = open(path, 'rb')
except IOError:
self.send_error(404, "File not found")
return None
self.send_response(200)
self.send_header("Content-type", ctype)
fs = os.fstat(f.fileno())
self.send_header("Content-Length", str(fs[6]))
self.send_header("Last-Modified", self.date_time_string(fs.st_mtime))
self.end_headers()
def list_directory(self, path):
"""Helper to produce a directory listing (absent index.html).
Return value is either a file object, or None (indicating an
error). In either case, the headers are sent, making the
interface the same as for send_head().
list = os.listdir(path)
except os.error:
self.send_error(404, "No permission to list directory")
return None
list.sort(key=lambda a: a.lower())
f = StringIO()
displaypath = cgi.escape(urllib.unquote(self.path))
f.write('&!DOCTYPE html PUBLIC "-//W3C//DTD HTML 3.2 Final//EN"&')
f.write("&html&\n&title&Directory listing for %s&/title&\n" % displaypath)
f.write("&body&\n&h2&Directory listing for %s&/h2&\n" % displaypath)
f.write("&hr&\n")
f.write("&form ENCTYPE=\"multipart/form-data\" method=\"post\"&")
f.write("&input name=\"file\" type=\"file\"/&")
f.write("&input type=\"submit\" value=\"upload\"/&")
f.write("&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp")
f.write("&input type=\"button\" value=\"HomePage\" onClick=\"location='/'\"&")
f.write("&/form&\n")
f.write("&hr&\n&ul&\n")
for name in list:
fullname = os.path.join(path, name)
colorName = displayname = linkname = name
# Append / for directories or @ for symbolic links
if os.path.isdir(fullname):
colorName = '&span style="background-color: #CEFFCE;"&' + name + '/&/span&'
displayname = name
linkname = name + "/"
if os.path.islink(fullname):
colorName = '&span style="background-color: #FFBFFF;"&' + name + '@&/span&'
displayname = name
# Note: a link to a directory displays with @ and links with /
filename = os.getcwd() + '/' + displaypath + displayname
f.write('&table&&tr&&td width="60%%"&&a href="%s"&%s&/a&&/td&&td width="20%%"&%s&/td&&td width="20%%"&%s&/td&&/tr&\n'
% (urllib.quote(linkname), colorName,
sizeof_fmt(os.path.getsize(filename)), modification_date(filename)))
f.write("&/table&\n&hr&\n&/body&\n&/html&\n")
length = f.tell()
self.send_response(200)
self.send_header("Content-type", "text/html")
self.send_header("Content-Length", str(length))
self.end_headers()
def translate_path(self, path):
"""Translate a /-separated PATH to the local filename syntax.
Components that mean special things to the local file system
(e.g. drive or directory names) are ignored. (XXX They should
probably be diagnosed.)
# abandon query parameters
path = path.split('?',1)[0]
path = path.split('#',1)[0]
path = posixpath.normpath(urllib.unquote(path))
words = path.split('/')
words = filter(None, words)
path = os.getcwd()
for word in words:
drive, word = os.path.splitdrive(word)
head, word = os.path.split(word)
if word in (os.curdir, os.pardir): continue
path = os.path.join(path, word)
return path
def copyfile(self, source, outputfile):
"""Copy all data between two file objects.
The SOURCE argument is a file object open for reading
(or anything with a read() method) and the DESTINATION
argument is a file object open for writing (or
anything with a write() method).
The only reason for overriding this would be to change
the block size or perhaps to replace newlines by CRLF
-- note however that this the default server uses this
to copy binary data as well.
shutil.copyfileobj(source, outputfile)
def guess_type(self, path):
"""Guess the type of a file.
Argument is a PATH (a filename).
Return value is a string of the form type/subtype,
usable for a MIME Content-type header.
The default implementation looks the file's extension
up in the table self.extensions_map, using application/octet-stream
however it would be permissible (if
slow) to look inside the data to make a better guess.
base, ext = posixpath.splitext(path)
if ext in self.extensions_map:
return self.extensions_map[ext]
ext = ext.lower()
if ext in self.extensions_map:
return self.extensions_map[ext]
return self.extensions_map['']
if not mimetypes.inited:
mimetypes.init() # try to read system mime.types
extensions_map = mimetypes.types_map.copy()
extensions_map.update({
'': 'application/octet-stream', # Default
'.py': 'text/plain',
'.c': 'text/plain',
'.h': 'text/plain',
class ThreadingServer(ThreadingMixIn, BaseHTTPServer.HTTPServer):
def test(HandlerClass = SimpleHTTPRequestHandler,
ServerClass = BaseHTTPServer.HTTPServer):
BaseHTTPServer.test(HandlerClass, ServerClass)
if __name__ == '__main__':
# srvr = BaseHTTPServer.HTTPServer(serveraddr, SimpleHTTPRequestHandler)
srvr = ThreadingServer(serveraddr, SimpleHTTPRequestHandler)
srvr.serve_forever()
1、httpserver
=======================================
This httpserver is a enhanced version of SimpleHTTPServer.
It was write in python, I use some code from bottle[https://github.com/defnull/bottle]
It support resuming download, you can set the document root, it has more
friendly error hit, and it can handle mimetype gracefully
https://github.com/lerry/httpserver/blob/master/httpserver.py
2、基于 java netty 的 SimpleHTTPServer,
由于windows不支持某些 netty low-level API,该代码仅能运行在 linux 下:
https://github.com/dvliman/SimpleHTTPServer
您可能感兴趣的文章:
大家感兴趣的内容
12345678910
最近更新的内容
常用在线小工具离上一篇更新的博文应该过了挺久的了( ),因为中间考完试紧接着就去实习的缘故,然后到新环境各种熟悉什么的,所以后面有所学到的东西就来不及汇总,终于在某个礼拜天的下午,喝着我的雀巢速溶咖啡,一边写着这篇总结。
上一篇我自己也回去又看了一遍,其实上一篇的博文主要还是用的是 传参 的方法,什么叫传参的方法?就是着重点在分析交互中各种数据请求来源,然后找到我们需要的数据来源,再写个脚本把数据请求回来,最后做个提取就OK了,这种办法的优点在于执行得很快,对比于后面我要说的一种 模拟浏览器 的方法来说,在请求页面的效率上会快上很多,而传参方法的难点在于寻找数据来源的那个URL还有它尾巴的一堆参数的构建,当然简单的比如上一篇的艺龙的酒店评论的话,直接用chrome的开发者工具XHR项目里面就可以找到,但当遇到更为复杂的页面结构,或者采用更加复杂技术的页面(比如混淆代码啊,压缩代码之类的),传参这种办法的工作就变得十分繁琐,特别是在XHR里面没有找到数据来源的URL的时候,要在一堆js脚本里面找到你要的数据的请求来源的时候,你会彻底懵逼了,反正我是懵逼了好几次,而且爬虫有个真理——越是接近人的操作的爬虫越是好的爬虫。因为网站是为了人去访问而服务的,那么就算网站反爬很厉害,但是也不可能去因为爬虫而误伤了正常的用户,对于一个网站而言得不偿失,所以当我懵逼了几次以后,果断转用模拟浏览器的方法,我在这里要明确一点,传参的思路和模拟浏览器的思路是不一样的,所以要分开来认识他们
爬虫制作总览
经过实习这一段时间以来的学习和研究,包括对python这门语言更加深入的了解,还有对爬虫中遇到的问题的总结,我觉得大致上爬虫的制作思路如下:
P.s.更正上图lxml.etee为lxml.etree
上图中需要补充的是,有时候有登录的需求,登录里面会涉及验证码的问题,其实说白了就是OCR技术的应用,还有访问过频,封IP或者是弹验证码的问题,这些都是爬虫会遇到的独特问题,不过一般按照上图的思路去做爬虫,遇到上面这些问题再相对应的做应对策略就好.
其实爬虫好玩的地方在于与网站程序猿的之间的博弈,一般而言,没有哪个网站是希望自己的数据被爬虫爬去的,当然谷歌百度这种大的搜索引擎除外,每天都被成百上千的练手也好,娱乐也罢的大大小小的爬虫们爬网站内容,哪个服务器受得了,所以对于山那头的程序猿而言,爬虫生死之战在于把关好请求页面这一步,不让爬虫程序拿到完整静态页面;对于开发爬虫的程序猿而言,爬虫生死之战就在能否成功到达拿到完整静态文本那一步——请求页面(完整是针对动态页面而言需要完整加载出目的数据的文本),因为拿到静态文本以后,我要怎么做网站那头的程序猿就算使用洪荒之力也已经限制不了我了,这时候慢慢做提取都可以,请求页面就是前言里面说的两种办法:传参or模拟浏览器.
【P.s.传参和模拟浏览器最大的不同是获取数据的地方不一样。传参让人感觉更加底层,就是有点贴近http协议的那种底层,总给人一种要做非常细致推敲工作的过程的感觉,传参取得数据的地方就是你所请求的URL返回的文本,而难就难在这个URL怎么构造才能骗过山那头的各种脚本顺利请求回包含目的数据的源码;
而模拟浏览器的办法,就有点取巧,但是却是面对现在越来越复杂的网站架构技术的最佳办法,也是最贴合人操作浏览器这种想法的方法(最不容易被封),模拟浏览器操作的办法取得数据的地方是浏览器的内核,因为模拟浏览器方法的核心思想是:无论你中间技术怎么复杂,怎么变化,你最终还是要在浏览器内核中渲染好加载好数据来呈现给用户,而渲染好加载好后的必定是一个静态文本,那么我直接拿这个静态文本再提取数据就好了。模拟浏览器操作的方法虽然比传参的方法慢,但是胜在它稳,而且爬取思路非常清晰简单:D】
模拟浏览器动作
模拟浏览器的方法其实就是把一个人每天到目的网站上复制黏贴目的数据的过程用程序和机器实现,这过程为:用浏览器打开网站→输入信息和提交等动作→浏览器请求相关网页→浏览器渲染返回信息→人把渲染出来的信息复制黏贴保存系下来.
这样日复一日,每天都重复一样的机械性 的动作,这毫无疑问是很低效的,但是却是最保险稳定的,因为被封IP的几率很小,甚至可以忽略不计,但是估计这个人得累死,那么我们这些懒鬼当然希望能够让机器帮助我们实现日复一日的这样机械的过程,那么就得模拟这一个过程,这里我们要用到selenium来模拟人来操作浏览器。
(1)模拟登陆–Selenium
首先是模拟用户登录,以登录后的状态去请求接下来的页面,因为项目内容保密的缘故,一些信息不方便透露,不过单纯用到的技术还有思想还是可以分享一下的
Q:为什么最好用登录后状态去请求数据?
A:(收集自网上的回答)
1.一方面可能是因为你要的数据在登录后才有,比如微博;
2.另外一方面也可能是因为你需要会员登录获得优惠的价格信息;
3.而从单纯的技术的角度的来说,用登录状态来爬是有好处的:
①携程网站对于爬虫的频率是有限制的,爬取频率过高,服务器会返回429错误,此时如果没有登录用户无法正确获取数据;
②建议:登录账号后利用Cookie进行数据的爬取,虽然登录后过于频繁请求也会导致429错误(python的话20线程10min就会出现),但只要等3min就可以继续快乐地爬取了,而且爬取的数据不会出错,而不登录会数据出错
③而值得注意的是,用账号登录之后生成的Cookie不到几个小时就会失效
模拟用户登录在很久以前还没有验证码的时候还是很简单的,特别是配合selenium的情况下是非常容易做到的,但是自从山那头的程序猿们发明和发展了验证码后,模拟用户登录就没有那么容易了
补充:关于selenium安装,pip install也可以,apt-get install 也可以,通过pip
安装的都是比较新的版本,而且扯多一句,用pip的话还可以安装一些历史版本,而apt-get是系统安装过的方法,这样安装的永远只有一个版本,但是是比较稳定的版本而且是全局的,但是apt-get有时候会出现一些奇奇怪怪的问题,所以我的建议是如果原来系统里面已经安装的python-xxxxx的库你就可以不用管它,接下来你要新安装的库尽可能都用pip统一管理,还有,无论是pip安装的库还是apt-get安装的库,都会显示在pip list命令打印出来的已安装列表里面,所以有时候你pip uninstall了的库,还会在pip list里面打印出来的原因是因为你的系统自己本身也有一个这样的库,这个系统级的py库你用pip来卸载是卸载不了的.
(库,模块都是指module,要特别注意,别以为python的库和模块是两码事就好)
①没有验证码情况
from selenium import webdriver
firefox_login=webdriver.Firefox()
firefox_login.get('###你的URL地址###')
firefox_login.maximize_window()
firefox_login.find_element_by_id('username').clear()
firefox_login.find_element_by_id('username').send_keys(u'###你的账户###')
firefox_login.find_element_by_name('password').clear()
firefox_login.find_element_by_name('password').send_keys(u'###你的密码###')
firefox_login.find_element_by_name('login').click()
firefox_login.quit()
P.s.要学会用谷歌浏览器的开发者工具(F12或者Ctrl+Shift+I)的Elements去看
你要输入的框框的信息(id/name/xpath….),或者直接右键你要定位的目标,选择【检查】.举个栗子:
②有验证码情况(验证码识别深似海,建议学好数字图像处理)
验证码这块实在太多了,特别是经过这么多年的发展,已经有各种不同种类的验证码的,我计划着好好研究一番以后另外写一个专门介绍验证码的博文,而下面只是简单聊聊而已。
对于有验证码(这里指旧式验证码)的登录,其实就是在上面只需要用户名和密码的界面多给你一张验证码的图片(验证码图片请求来源的URL的格式大都是前面相同的地址后面加一串随机数,要知道这个随机数是多少,你就得看看关于请求验证码的js脚本怎么写,不然你连验证码这张图都拿不到,又谈何识别与登录),然后用户看出图片内容,再输入,验证码刚出现是非常正常的字母数字,因为要反爬的缘故,山那边的猿又对验证码图片做了增加噪点,扭曲挤压等图像处理,后来中国的汉字引入,验证码似乎就成了爬虫的专业杀虫剂,现在我见过的最有魔性的验证码是一个卖火车票的网站:D.
可是还是那句话,如果爬虫很难识别到验证码,用户体验也不会好,为了不伤了用户的心情,程序猿们还是小心翼翼地设计验证码,关于验证码发展史以及山那头的程序猿和爬虫程序猿之间的大战,你可以到知乎这个帖看看
上面的知乎帖子里面有一个名词:OCR。OCR技术是爬虫们应对验证码图片的神器,OCR全称Optical Character Recognition(光学字符识别),如果你把ocr当成一个黑匣子,那么如果你往这个黑匣子里面丢图片,他就会给你识别出图片内的字符,并输出文本给你,关于ocr的历史自己可以wiki一下,我先来说说ocr的实现思路:输入图片→中值滤波去噪点、二值化图片、分割等图片预处理→紧缩重排→字库特征匹配→字符
上面实现思路中,关键是:第一,前面对图片的预处理,如果预处理越好,得出的二值化图片越清晰正规,那么后面字库特征匹配准确率就越高;第二,字库的搭建要丰富,特征值要选好。
当然因为我不是做图像处理的,而且数字图像处理的课我也没有上好,所以上面基本都是班门弄斧,我就直接用现在已经有的轮子——摆在我前面的一堆图像处理和ocr库了,比如:
1.PIL(Python Image Library,python专属图像处理库,现在较新版本是原来PIL的一个fork叫Pillow,原PIL停止更新)
2.OpenCV(Open Source Computer Vision Library,是一个在图像操作和处理上比PIL更加先进的库,在python中OpenCV进行图像处理是通过cv2和numpy库实现的,换言之就是依赖于cv2和numpy这两个库)
3.Tesseract-ocr(前面转手很多次,现在属于google开发的ocr技术项目)
4.pyocr(依赖于Tesseract-ocr)等等,网上有人推荐先用OpenCV做图片预处理,再用Tesseract-ocr做识别,但是我只是用了PIL和pyocr/Tesseract-ocr,没有用OpenCV,PIL+pyocr识别差强人意,几乎没有几张能出东西,也难怪,因为pyocr已经没有更新很久了,而PIL+Teserract-ocr也只是好一点,可能是我没有训练够的原因,两种识别结果我就不方便给出来了,有机会你可以自己拿一些验证码试试,我这里只是捋顺一下思路,推荐可以直接上OpenCV+Tesseract-ocr试试.
P.s.扯一下打码平台,打码平台有做好了并且封装好了的ocr平台识别的,还有人工识别打码的,可笑的是,我一开始还以为只有人工打码。这种打码平台一般都是要收费的,而且识别率见仁见智,因为针对性不一定高,我个人的话还是推荐你,在你项目允许的情况下,请尽量自己折腾这一块验证码的识别工作,方便后期排错或者目标网站的验证码有变化的时候,也可以相对应地迅速及时作出调整。详细看
上面谈论的旧式验证码都是“基于知识进行人机判断”(有点像看图说话),而新式验证码是“基于人类固有的生物特征以及操作的环境信息综合决策,来判断是人类还是机器”(看图做动作?),比方说谷歌老大发明的reCaptcha和阿里巴巴的NoCaptcha等(相信不少人都看过拖动块识别的那种验证吧,有兴趣的可以直接搜搜~).但是就算是新式的也有人做了,还是那句验证码要做还是能识别的,只是成本值不值得而已.
更多关于验证码的,后面单独一篇慢慢聊,具体地聊,但是这里我先挖个坑:-) ========&
【传参能做么?
其实上面说的用户登录这一步(假设是旧式验证码而且已经识别到了),用传参的方法也可以做到的,一般的登录过程都是POST的方式提交账号密码(和验证码),然后服务器会给你写cookie(而会话状态一般都存在服务器的session中),而cookie又和验证码的生成息息相关,讲真,目前为止我是还没有实际折腾过传参的方式,如果你要折腾实验一下就抓住POST方式和cookie/session这几个点入手】
Selelnium支持的真·浏览器驱动:
FireFox Driver
Safari Driver
Chrome Driver
Opera Driver
Selelnium支持的伪·浏览器驱动:
Selelnium支持的移动端·浏览器驱动:
Windows Phone Driver
Selendroid
IOS Driver
Appium[支持iPhone,iPad,Android和FirefoxOS]
(2)无头(无GUI)浏览器–PhantomJS
Synopsis:PhantomJS is a headless Webkit scriptable with a js API.It has fast & native support for various Web standards: DOM handling,CSS selector,JSON,Canvas,and SVG.
To Be Brief:PhantomJS is web browser without a graphical user inferface.
好吧,前面的简单介绍其实是我想打下英文,你完全可以自己上它的官网自己慢慢看,都有。
再一个就是phantomjs的使用场景:
1.无需浏览器的Web测试;
2.页面自动化测试;
Page Automation
3.屏幕捕获;
Screen Capture
4.网络监控;
Network Monitoring
(LinkedIn,Twitter等都在用PhantomJS做测试)
其实phantomjs这个东西一开始本意是用来做自动测试的(使用场景并没有提到爬虫),结果因为效果很好,很多人就拿来做爬虫.
而这里我想说说自己对于PhantomJS在爬虫中应用的看法:
首先,在一般人的认识里浏览器都是像chrome、firefox之类的有图形界面的(当然你要是说你不是一般人…- -b),但是这种GUI浏览器其实执行效率还是算慢的,因为要渲染出图形来,那么无GUI的浏览器的优势就有了,无GUI意味着占用资源少了,执行效率快了,而且适合linux纯CLI界面服务器来跑(纯CLI的linux服务器上面我还真没有试过FireFox和Chrome这种GUI的浏览器是不是能跑~),而爬虫中如果是选择了模拟浏览器这条路子来做页面请求,那么把GUI的浏览器换成无GUI的浏览器是必要的。
然后,phantomjs在爬虫中的应用,我认为你把它当成一个纯粹的浏览器就够了,当成Chrome一样的浏览器,并不怎么需要操作到phantomjs里面的方法,我们写爬虫的时候写的更多的反而是selenium下面的方法,通过selenium去操作浏览器,无论是phantomjs、HTMLUnit等无GUI的浏览器,还是Chrom、FireFox这种有GUI的浏览器,至于能不能用HTMLUnit代替PhantomJS这个问题,我只能说python和PhantomJS配合比较好,而且js解析十分稳健,相对而言HTMLUnit稍显逊色,但并不是不能用HTMLUnit来作为爬虫用的无头浏览器。
PhantomJS的渲染引擎是QtWebkit,而它的js解析引擎是Chrome的V8.
PhantomJS在哪层构建就在哪层quit();
PhantomJS每个版本都是以花命名,有点浪漫
①PhantomJS推荐去官网下载编译好的二进制,因为debian系的distros的源里面那个PhantonJS是不完整的——“It seems that it’s not full-function.”,不完整会导致什么问题么?其他没有遇到过,就遇到过下面这个错误:
"selenium.common.exception.WebDriverException:
Message:ErrorUnable to load Atom 'find_elements' from file':
/ghostdriver/third_party/webdriver-atoms/find_elements.js'"
看到开头的 selenium我以为是selenium的问题,google了半天没有结果,回来再详细看看错误信息,最后直接把错误贴上去才找到,真觉得自己Too Young .Too Naive,一开始直接贴上去搜索就好了.- -
②如果是selenium+phantomjs的搭配,要注意selenium的版本问题,因为selenium从2.27开始才支持PhantomJS,一般pip装最新的selenium就没有问题.
Selenum+PhantomJS
现在来实际结合起来做一下,我稍微修改了一下项目代码做成示例:
import sys
reload (sys)
sys.setdefaultencoding('utf-8')
from selenium import webdriver
from selenium.webdriver.support.ui import WebDriverWait
def Phantomjs_Get_WebPage(a,b,c):
print 'PhantomJS Browser Structing ...\n'
browser=webdriver.PhantomJS()
print 'Opening Original Website....\n'
url='这里填入你的URL'
browser.get(url)
browser.find_element_by_xpath('xpath_a').clear()
browser.find_element_by_xpath('xpath_a').send_keys(a)
browser.find_element_by_xpath('xpath_a').click()
browser.find_element_by_xpath('xpath_b').clear()
browser.find_element_by_xpath('xpath_b').send_keys(b)
browser.find_element_by_xpath('xpath_b').click()
browser.find_element_by_xpath('xpath_c').clear()
browser.find_element_by_xpath('xpath_c').send_keys(c)
browser.find_element_by_xpath('xpath_d').click()
if(YorN_Xpath(browser,wait_time=10,xpath_Probe="xpath_e")):
webpage_sourcecode=browser.find_element_by_xpath('//*').get_attribute('outerHTML')
browser.quit()
extracted_Data_singlePage=Extract(webpage_sourcecode,a,b)
save(extracted_Data_singlePage,a,b)
return True
print '请求AJAX超时'
browser.quit()
return False
def YorN_Xpath(browser,wait_time=10,xpath_Probe):
wait_for_ajax_element=WebDriverWait(browser,wait_time)
wait_for_ajax_element.until(
the_driver:the_driver.find_element_by_xpath(xpath_Probe).is_displayed())
print '获取AJAX数据成功\n'
return True
print '获取AJAX数据失败\n'
return False
其实上面这段代码大部分都是上面讲selenium的时候的那些selenium的方法,关键要注意两个地方:
①browser=webdriver.PhantomJS()这一句就是selenium和PhantomJS结合的地方,这样说出来你是不是感觉也没有什么特别的。会不会觉得当想换成FireFox浏览器看一下的时候,就直接把语句改成browser=webdriver.FireFox()这样就好了?大多数情况下这样改是没问题的,使可以调通不出错的,可是由于FireFox和PhantomJS之间还是有区别的,所以在某些情况下直接这么改会导致程序报错;
②YorN_Xpath(browser,wait_time,xpath_Probe)这一个函数的功能就是为了解决PhantomJS没有等到异步的AJAX数据加载完就返回页面源码的问题。用到的是selenium.webdriver.support.ui下的WebDriverWait 方法,这是显式等待(Explicit Waits,)。我们把上面构造的PhantomJS浏览器放进函数的browser那一项,wait_time就是等待AJAX上限时间,xpath_Probe是xpath探针,xpath_Probe这里需要填入的是只有AJAX加载成功才会出现的异步加载的那部分数据的xpath。WebDriverWait 方法固定是每500ms检测一次你的输入的xpath_Probe,如果检测有东西,就返回True,如果没有就继续等待500ms,如果总的等待时间超过了我设定的wait_time就会返回False。所以按照上面输入的wait_time=10来说,10s=10 000ms=20x500ms,换言之就是会在10s内对xpath_Probe最多检测20次,20次之中都没有检测到,那就不好意思了,返回False跳出了~
使用场景:如果你发现你直接用PhantomJS返回的源码里面没有找到一些你要的数据,那么可能是由于你的这些数据是通过异步加载的方式加载的,比如AJAX的方法,而PhantomJS没有等到你的这些异步加载的数据就直接返回了源码,当你遇到这个情况的时候不妨用上面这个函数试试,希望能帮到你.
Explicit Waits文档里面有一段关于为什么要用WebDriverWait的解释,我觉得讲的很有逻辑,现在单独提出来写在最后(其实我就是想多打打英文- -)
It is worth nothing that if your page uses a lot of AJAX on load then WebDriver may not know when
it has completely loaded.
These days most of the webapps are using AJAX techniques when a page is loaded to browser,the elements within that page may load at different time intervals.
This makes locating elements difficult,if the element is not present in the DOM,it
will raise ElementVisibleException.
Using waits,we can solve this issue.Waiting provides some time intervals between actions performed(mostly locating element or any other operation with the element)
16.8.26更新:如果你遇到下面这个错误,尤其是在最开始的几次页面的请求中报错:
urllib2.URLError:[urlopen error Error 111]Connection Refused
那么很有可能是因为你的浏览器退出时机不对导致的,这就我说过的为什么浏览器的构建和退出应该是同一层完成,因为不这样的话,很容易就会出现循环内层退出了浏览器,可是我是在上层构造的浏览器,结果内层的下一次循环浏览器是不可用的状态,也就是“Connection Refused”状态(我一开始还以为urlopen的问题,但是想想我好像没有直接用到urlopen啊,那就应该是浏览器的问题了)
本博文只是为了分享技术和共同学习为目的,并不出于商业目的和用途,也不希望用于商业用途,特此声明。
最后思考一个问题:传参方法的效率和浏览器的稳定能不能做一个结合互补?这是我接下来要做的一个尝试.
python模拟打开Google浏览器并打开网页(selenium+chrome)
python模拟打开Google浏览器并打开网页
python中使用requests 模拟浏览器发送请求数据
import requests
url='http://####'
proxy={'http':'http://####:80'}
&Accept&:&text/html...
python爬虫模拟浏览器的两种方法
爬虫爬取网站出现403,因为站点做了防爬虫的设置
一、Herders 属性
爬取CSDN博客
import urllib.request
url = &http://blog.cs...
python学习之6 requests模拟浏览器抓数据
python学习之 requests模拟浏览器抓数据在爬网站时,有时候会遇到返回500,被服务器拒绝的情况。
需要做的是,模拟浏览器登录。
即增加,headersheaders = {
python中模拟浏览器抓取网页(-)
对于平时我们抓取网页的内容时,比较倾向于直接利用urllib进行抓取(这里我就基于python的2.7版本进行解说,对于python3之后的版本,是将python中的urllib和urllib2和并成...
python模拟浏览器请求web服务器的网页过程
一、浏览器请求的基本流程:用户输入网址.浏览器请求DNS服务器, 获取域名对应的IP地址.请求连接该IP地址服务器.发送资源请求. (HTTP协议)web服务器接收到请求, 并解析请求, 判断用户意图...
Python模拟浏览器登录
'''import gzip
import sys
import urllib.request
import urllib.parse
import urllib.error
python模拟浏览器访问网站
import urllib
class AppURLopener(urllib.FancyURLopener):
version = &Mozilla/5.0&...
python3实现网络爬虫(5)--模拟浏览器抓取网页
本来准备继续分析BeautifulSoup的,但是好多网页都是反爬虫的,想分析没法分析了 ,那么就跳一节吧,我们先看看如何模拟浏览器进行访问网页,然后在折回去继续说BeautifulSoup。...
python模仿浏览器访问网站
#coding:utf-8
import random
import socket
import urllib2
import cookielib
'0':'Ca...
没有更多推荐了,}

我要回帖

更多关于 方舟进化电脑上怎么复制代码 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信