所以整理一下python爬虫最基础的一些东西出来
1.读取页面,说简单其实可以很简单,一句话就够了,而且在大部语言都能实现
这样就能把页面的内容读出来,但是,做为一个比较强大的爬虫,还要知道除了正常的情况还有其它情况,比如301 404 或者链接无法读取,这时候就要去处理中断了,所以就加入了异常
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
|
def
get
(
self
,
url
)
:
returnObj
=
{
"code"
:
None
,
"string"
:
None
}
failedTimes
=
self
.
TryTimes
while
failedTimes
>
0
:
try
:
#f=self._urllib2.urlopen(url)
f
=
self
.
_urllib2
.
Request
(
url
,
headers
=
{
"Referer"
:
"http://www.google.com"
,
"User-Agent"
:
"Mozilla/5.0 (Windows NT 5.1) AppleWebKit/534.24 (KHTML, like Gecko) Chrome/11.0.696.68 Safari/534.24"
}
)
f
=
self
.
_urllib2
.
urlopen
(
url
=
f
,
timeout
=
10
)
#print f.code
if
f
.
code
==
200
:
#2XX
self
.
html
=
f
.
read
(
)
#转换为Unicode
charset
=
self
.
_chardet
.
detect
(
self
.
html
)
self
.
html
=
self
.
html
.
decode
(
charset
[
'encoding'
]
,
'ignore'
)
#print charset
self
.
code
=
f
.
code
break
elif
f
.
code
==
201
:
self
.
html
=
None
self
.
code
=
f
.
code
except
Exception
,
e
:
if
isinstance
(
e
,
self
.
_urllib2
.
HTTPError
)
:
self
.
code
=
e
.
code
if
e
.
code
==
404
:
break
print
'http error: {0}'
.
format
(
e
.
code
)
elif
isinstance
(
e
,
self
.
_urllib2
.
URLError
)
and
isinstance
(
e
.
reason
,
socket
.
timeout
)
:
print
'url error: socket timeout {0}'
.
format
(
e
.
__str__
(
)
)
else
:
print
'misc error: '
+
e
.
__str__
(
)
failedTimes
=
failedTimes
-
1
if
self
.
DelayConnectTime
>
0
:
self
.
_time
.
sleep
(
self
.
DelayConnectTime
)
|
这是我写的一个类里的一个方法,不能直接运行,如果看不懂可以直接关掉浏览器:)还有一个post的方法,包括post数据和保存cookie,这里就不贴出来了,有兴趣可以随时和我交流
2.看上面代码就出现了第二个问题。
还有很多编码,如果是英文可能不会有什么问题,如果出现中文这样编码不一样就会出现乱码,我上面的解决方法是使用chardet来识别编码。因为编码问题,开始本来是读取charset来识别编码,但是大家都知道什么程序猿都有,有的也没有很规范就遗漏了charset,所以没办法识别出来!后来想用一些中文来判别,查阅了大部份资料,比如可以用“的”来做为识别码,还有人给我提示去看firefox的源代码看浏览器是怎么识别编码的;我还真的去看,可惜google不给力,经常被墙,只好作罢。后来找到了charset这个第三方库,比较强大,出错非常少,至少可以保证其稳定性。但是确实挺慢,觉得加了以后加上html读过来比较大,识别的时间要花去很多,个人感觉有500毫秒左右。
这样一句就能识别出来,当然写之前要确定你是否已经装了这个库
3.链接的提取
开始使用正则去匹配链接(这也是我以前常做的方法),其实也挺好的,效率也不算太差,后来因为要解析其它的html方法,尝试了几种方法比如SGMLParser库,SGMLParser还是比较强大,刚接触,好像难度有点大一些。开始用来提取链接也算简单,后来想用来做更多的工作就有点复杂了,听说效率也不高。
1
2
3
4
5
6
7
8
|
class
URLLister
(
SGMLParser
)
:
def
reset
(
self
)
:
SGMLParser
.
reset
(
self
)
self
.
urls
=
[
]
def
start_a
(
self
,
attrs
)
:
href
=
[
v
for
k
,
v
in
attrs
if
k
==
'href'
]
if
href
:
self
.
urls
.
extend
(
href
)
|
很简单就可以提取出链接出来,后来看文章推荐,最后使用了BeautifulSoup,这个库比较大,功能也多,对于初学者来说是比较容易学习使用。用BeautifulSoup就简单多了,一句话就能提出来出
安装可以参照我前一篇文章BeautifulSoup的安装
4.问题4,url过滤
要过滤掉一些没有用的链接,比如javascript,#等还有站内和站外的链接直接看代码吧。这是我原创的:)也没有什么好参考的
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
|
def
getHref
(
self
)
:
newlist
=
[
]
links
=
self
.
soup
.
findAll
(
'a'
)
for
i
in
links
:
##判断tag是a的里面,href是否存在。
if
'href'
in
str
(
i
)
:
linkname
=
i
.
string
linkaddr
=
i
[
'href'
]
if
'NoneType'
in
str
(
type
(
linkname
)
)
:
#当i无内容是linkname为Nonetype类型。
None
#print linkaddr
else
:
#print linkname+':'+linkaddr
#排除链接为 # javascript 和#top
if
re
.
search
(
"^(javascript\:|#.*)"
,
linkaddr
)
:
#None
print
linkaddr
else
:
#合并相对链接
url
=
html_urljoin
(
self
.
url
,
linkaddr
)
#只允许收集本域的链接
urls
=
html_urlparse
(
url
)
if
html_urlparse
(
self
.
url
)
.
netloc
==
urls
.
netloc
:
#过滤长尾 如#top
url
=
urls
.
scheme
+
'://'
if
urls
.
netloc
:
url
+
=
urls
.
netloc
if
urls
.
path
:
url
+
=
urls
.
path
if
urls
.
query
:
url
+
=
'?'
+
urls
.
query
newlist
.
append
(
[
linkname
,
url
]
)
else
:
None
#用于后期收集外域
return
newlist
|
接下来就是html解析啦。具体就要看你要抓取什么东西了:)