File "androidmarket82.py", line 108, in <module>
main()
File "androidmarket82.py", line 54, in main
pattern=re.compile('<label id="ctl00_AndroidMaster_Content_Apk_SoftVersionName">(.+?)</label>)</div>')#版本号
File "/usr/lib/python2.7/re.py", line 190, in compile
return _compile(pattern, flags)
File "/usr/lib/python2.7/re.py", line 242, in _compile
raise error, v # invalid expression
sre_constants.error: unbalanced parenthesis
#!/usr/env python #-*- coding: utf-8 -*- import requests import os,sys import time import MySQLdb import re num=0 dataresult=[] def main(): try: conn=MySQLdb.connect(host='localhost',user='root',passwd='123456',db='addressbookdb',charset="utf8") conn.query("set names utf8") except Exception,e: print e sys.exit() cursor=conn.cursor() for k in range(51): try: url="http://apk.hiapk.com/apps#"+str(k)+"_1_0_0_0_0_0" print url html=requests.get(url) result=html.content pattern=re.compile('''<a target='_blank' title=".+?" href=/blog_article/"/index.html(.+?)">.+?</a></span>''') daresult=re.findall(pattern,result) global dataresult dataresult+=daresult dataresult=list(set(dataresult)) print len(dataresult) except: time.sleep(30) pass f=file("androidmarket.txt","a+") content=str(len(dataresult)) f.write(content) f.close() print len(dataresult) for i in dataresult: print i try: html=requests.get(i) result=html.content except: time.sleep(30) pass pattern=re.compile('<label id="ctl00_AndroidMaster_Content_Apk_SoftName">(.+?)</label>')#名称 data0=re.findall(pattern,result) print data0[0] pattern=re.compile('<label id="ctl00_AndroidMaster_Content_Apk_SoftVersionName">(.+?)</label>)</div>')#版本号 data1=re.findall(pattern,result) print data1[0] pattern=re.compile('<span )#开发者 data2=re.findall(pattern,result) print data2[0] pattern=re.compile('<label id="ctl00_AndroidMaster_Content_Apk_SoftPublishTime">(.+?)</label>')#发布时间 data3=re.findall(pattern,result) print data3[0] pattern=re.compile('<span )#文件大小 data4=re.findall(pattern,result) print data4[0] pattern=re.compile('<span )#支持固件 data5=re.findall(pattern,result) print data5[0] pattern=re.compile('<span id="ctl00_AndroidMaster_Content_Apk_SoftCategory" )#类别 data6=re.findall(pattern,result) print data6[0] pattern=re.compile('<label id="ctl00_AndroidMaster_Content_Apk_Description">([\s\S]*?)</label>')#介绍 data7=re.findall(pattern,result) for items in data7: pass#print re.sub('<br />',' ',items) sql="insert into androidmarket(name,version,developer,pubtime,filesize,support,classifyintroduction) values(%s,%s,%s,%s,%s,%s,%s,%s)" for items in data7: try: values=(data0[0],data1[0],data2[0],data3[0],data4[0],data5[0],data6[0],re.sub('<br />',' ',items)) except: pass try: cursor.execute(sql,values) conn.commit() except: pass pattern=re.compile(' <div ) data=re.findall(pattern,result) for j in data: print j try: temp=requests.get(j[1:-2]) except: time.sleep(30) pass global num f=file("androidmarket/"+str(num),"w+") num=num+1 print num f.write(temp.content) cursor.close() conn.close() f.close() if __name__=="__main__": main()
HTTP是“Hypertext Transfer Protocol”的所写,整个万维网都在使用这种协议,几乎你在浏览器里看到的大部分内容都是通过http协议来传输的,比如这篇文章。
HTTP Headers是HTTP请求和相应的核心,它承载了关于客户端浏览器,请求页面,服务器等相关的信息。
当你在浏览器地址栏里键入一个url,你的浏览器将会类似如下的http请求:
GET /tutorials/other/top-20-mysql-best-practices/ HTTP/1.1
Host: net.tutsplus.com
User-Agent: Mozilla/5.0 (Windows; U; Windows NT 6.1; en-US; rv:1.9.1.5) Gecko/20091102 Firefox/3.5.5 (.NET CLR 3.5.30729)
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-us,en;q=0.5
Accept-Encoding: gzip,deflate
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7
Keep-Alive: 300
Connection: keep-alive
Cookie: PHPSESSID=r2t5uvjq435r4q7ib3vtdjq120
Pragma: no-cache
Cache-Control: no-cache
第一行被称为“Request Line” 它描述的是这个请求的基本信息,剩下的就是HTTP headers了。
请求完成之后,你的浏览器可能会收到如下的HTTP响应:
HTTP/1.x 200 OK
Transfer-Encoding: chunked
Date: Sat, 28 Nov 2009 04:36:25 GMT
Server: LiteSpeed
Connection: close
X-Powered-By: W3 Total Cache/0.8
Pragma: public
Expires: Sat, 28 Nov 2009 05:36:25 GMT
Etag: "pub1259380237;gz"
Cache-Control: max-age=3600, public
Content-Type: text/html; charset=UTF-8
Last-Modified: Sat, 28 Nov 2009 03:50:37 GMT
X-Pingback: http://net.tutsplus.com/xmlrpc.php
Content-Encoding: gzip
Vary: Accept-Encoding, Cookie, User-Agent
<!-- ... rest of the html ... -->
第一行呢被称为“Status Line”,它之后就是http headers,空行完了就开始输出内容了(在这个案例中是一些html输出)。
但你查看页面源代码却不能看到HTTP headers,虽然它们同你能看到的东西一起被传送至浏览器了。
这个HTTP请求也发出了一些其它资源的接收请求,例如图片,css文件,js文件等等。
下面我们来看看细节。
怎样才能看到HTTP Headers下面这些FireFox扩展能够帮助你分析HTTP headers:
1. firebug
2.Live HTTP Headers
3. 在PHP中:
- getallheaders() 用来获取请求头部. 你也可以使用 $_SERVER 数组.
- headers_list() 用来获取响应头部.
文章下面将会看到一些使用php示范的例子。
HTTP Request 的结构被称作“first line”的第一行包含三个部分:
- “method” 表明这是何种类型的请求. 最常见的请求类型有 GET, POST 和 HEAD.
- “path” 体现的是主机之后的路径. 例如,当你请求 “http://net.tutsplus.com/tutorials/other/top-20-mysql-best-practices/”时 , path 就会是 “/tutorials/other/top-20-mysql-best-practices/”.
- “protocol” 包含有 “HTTP” 和版本号, 现代浏览器都会使用1.1.
剩下的部分每行都是一个“Name:Value”对。它们包含了各式各样关于请求和你浏览器的信息。例如”User-Agent“就表明了你浏览器版本和你所用的操作系统。”Accept-Encoding“会告诉服务器你的浏览可以接受类似gzip的压缩输出。
这些headers大部分都是可选的。HTTP 请求甚至可以被精简成这样子:
GET /tutorials/other/top-20-mysql-best-practices/ HTTP/1.1
Host: net.tutsplus.com
并且你仍旧可以从服务器收到有效的响应。
请求类型三种最常见的请求类型是:GET,POST 和 HEAD ,从html的编写过程中你可能已经熟悉了前两种。
GET:获取一个文档大部分被传输到浏览器的html,images,js,css, … 都是通过GET方法发出请求的。它是获取数据的主要方法。
例如,要获取Nettuts+ 的文章,http request的第一行通常看起来是这样的:
GET /tutorials/other/top-20-mysql-best-practices/ HTTP/1.1
一旦html加载完成,浏览器将会发送GET 请求去获取图片,就像下面这样:
GET /wp-content/themes/tuts_theme/images/header_bg_tall.png HTTP/1.1
表单也可以通过GET方法发送,下面是个例子:
<form action="foo.php" method="GET">
First Name: <input name="first_name" type="text" />
Last Name: <input name="last_name" type="text" />
<input name="action" type="submit" value="Submit" />
</form>
当这个表单被提交时,HTTP request 就会像这样:
GET /foo.php?first_name=John&last_name=Doe&action=Submit HTTP/1.1
...
你可以将表单输入通过附加进查询字符串的方式发送至服务器。
POST:发送数据至服务器尽管你可以通过GET方法将数据附加到url中传送给服务器,但在很多情况下使用POST发送数据给服务器更加合适。通过GET发送大量数据是不现实的,它有一定的局限性。
用POST请求来发送表单数据是普遍的做法。我们来吧上面的例子改造成使用POST方式:
<form action="foo.php" method="POST">
First Name: <input name="first_name" type="text" />
Last Name: <input name="last_name" type="text" />
<input name="action" type="submit" value="Submit" />
</form>
提交这个表单会创建一个如下的HTTP 请求:
POST /foo.php HTTP/1.1
Host: localhost
User-Agent: Mozilla/5.0 (Windows; U; Windows NT 6.1; en-US; rv:1.9.1.5) Gecko/20091102 Firefox/3.5.5 (.NET CLR 3.5.30729)
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-us,en;q=0.5
Accept-Encoding: gzip,deflate
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7
Keep-Alive: 300
Connection: keep-alive
Referer: http://localhost/test.php
Content-Type: application/x-www-form-urlencoded
Content-Length: 43
first_name=John&last_name=Doe&action=Submit
这里有三个需要注意的地方:
- 第一行的路径已经变为简单的 /foo.php , 已经没了查询字符串。
- 新增了 Content-Type 和 Content-Lenght 头部,它提供了发送信息的相关信息.
- 所有数据都在headers之后,以查询字符串的形式被发送.
POST方式的请求也可用在AJAX,应用程序,cURL … 之上。并且所有的文件上传表单都被要求使用POST方式。
HEAD:接收头部信息HEAD和GET很相似,只不过HEAD不接受HTTP响应的内容部分。当你发送了一个HEAD请求,那就意味着你只对HTTP头部感兴趣,而不是文档本身。
这个方法可以让浏览器判断页面是否被修改过,从而控制缓存。也可判断所请求的文档是否存在。
例如,假如你的网站上有很多链接,那么你就可以简单的给他们分别发送HEAD请求来判断是否存在死链,这比使用GET要快很多。
http响应结构当浏览器发送了HTTP请求之后,服务器就会通过一个HTTP response来响应这个请求。如果不关心内容,那么这个请求看起来会是这样的:
map(String key, String value):
// key: document name
// value: document contents
for each word w in value:
EmitIntermediate(w, “1″);
reduce(String key, Iterator values):
// key: a word
// values: a list of counts
int result = 0;
for each v in values:
result += ParseInt(v);
Emit(AsString(result));