7 }$ X: T4 n4 S7 o$ G J7 [, Wimport urllib2, re, string, n( Z/ j" C+ B6 ]0 l9 P2 j* m- x
import threading, Queue, time! m `5 R( y& o: v3 \8 k2 y
import sys- |2 c' ~7 [- {% Y: @
import os 5 w# v; y0 u! |" T6 W- Tfrom bs4 import BeautifulSoup: w7 T$ T w7 b0 n7 k5 M) e
#from pprint import pprint8 p5 _6 }6 Q+ w# f
# T& ~% S3 f2 ?6 Breload(sys): o. n O2 [7 N z* w# S
sys.setdefaultencoding('utf8'), L% ?8 t. `$ @6 I9 I: S
_DATA = [] : x3 j) \# @) Y3 u* ~- J; sFILE_LOCK = threading.Lock() * |4 \& D! r( ~1 G3 q8 M7 rSHARE_Q = Queue.Queue() #构造一个不限制大小的的队列 & ?' D( X/ B8 ~- J0 ?_WORKER_THREAD_NUM = 3 #设置线程的个数+ \% j2 W. E! P8 h& X
0 `- {$ U8 ?6 a9 m7 M_Num = 0 #总条数3 \0 u2 `, x7 ^
class MyThread(threading.Thread) :; Z, W% O9 M/ F; M
' e' a4 L2 m, ?0 m6 G4 E
def __init__(self, func,num) :2 M5 y2 h' J1 D
super(MyThread, self).__init__() #调用父类的构造函数, ]' o; ]- {8 u0 S+ U% |. i5 f
self.func = func #传入线程函数逻辑 ; _/ H6 ]# \. }6 x' `( ? self.thread_num = num q/ y0 [0 A4 N9 r$ I6 }' S
def run(self) : 0 l0 X# R( t+ l) w) C- b' t self.func() : c3 W) h2 S, y% l0 _! c/ ~$ f #print u'线程ID:',self.thread_num5 ]7 J! u2 b3 O8 s3 A
8 @% z2 d; \' `# c+ d; fdef worker() : + b% c7 @( e5 Z" B4 E5 }; m, I global SHARE_Q , L: g" H' T0 |* l. m* D while not SHARE_Q.empty():7 k5 _1 J+ H4 q$ a. }( V$ |* J
url = SHARE_Q.get() #获得任务 ( ]7 [6 o! k! v7 v. s, j my_page = get_page(url)3 ] t# W) c& k+ N1 P# U3 M
find_data(my_page) #获得当前页面的数据* ]8 W7 h8 ?3 v6 j' t1 R9 Q
#write_into_file(temp_data) v8 p- T* C# c9 p4 l4 `* n time.sleep(1) & T, b& U/ D+ x6 e/ F SHARE_Q.task_done()1 v0 [+ M, B: ^, ?+ M
0 @+ B8 i+ @+ N" d7 X( h
def get_page(url) :' M: o+ z1 K7 m6 B3 d' N
"""1 J$ ~; j; G% r+ ~/ [5 \' f+ u
根据所给的url爬取网页HTML! z" ?: L2 J/ h& i6 h2 P
Args: & U: G" D3 I8 ?+ [! e1 z4 M2 n
url: 表示当前要爬取页面的url) [3 U$ q5 C2 ], q( j7 P/ S
Returns: 2 D* }) J" n. {* _3 n/ } 返回抓取到整个页面的HTML(unicode编码) : B! O2 G/ ]- t/ W# N Raises:1 T1 ?: D2 o' z( `+ `3 o- P
URLError:url引发的异常4 p5 U/ E! \& x7 r" t k$ [& l6 l1 o. i+ f
""". S/ ]' r2 n P0 U, D. j/ ~# O, g
try : * b) Z o5 a2 l8 L html = urllib2.urlopen(url).read()5 q0 k7 v( P1 H2 }1 V5 A2 N* Q) C
my_page = html.decode("gbk",'ignore')% [' o7 U- t: s6 W+ U, L- B
#my_page = unicode(html,'utf-8','ignore').encode('utf-8','ignore') s% O# `- [' l' O #my_page = urllib2.urlopen(url).read().decode("utf8")9 M& Y! o1 y! _# i
except urllib2.URLError, e : : @! o' @# o: e: T+ r& P5 m if hasattr(e, "code"):0 ~, K6 b8 m P8 y, ]
print "The server couldn't fulfill the request."# i$ v: K+ e4 P# v8 F
print "Error code: %s" % e.code ! x' L6 \, ]' [, [- G# } elif hasattr(e, "reason"):- {' @6 [) Y' }3 S, R7 b
print "We failed to reach a server. Please check your url and read the Reason" * ~) w. p3 y2 ?! h print "Reason: %s" % e.reason8 |1 Q2 t% q& D8 G4 G+ a6 m
return my_page! X; b, Y ^" v9 @& A4 ~
7 r& W/ s6 j) F! x
def find_data(my_page) :; J0 y; K) y' y3 Z( t
""" : M. @4 j4 ~) a6 ^0 _ 通过返回的整个网页HTML, 正则匹配名称. a7 C: z# a+ @" Q' \" F
e" ?" Q5 C! C' w) {* e9 o Args:1 Y! ?) t, u* T; i7 x
my_page: 传入页面的HTML文本用于正则匹配# [' c$ |* L0 F: P7 d* A& o+ D
""" 0 R" ?3 q) [3 x- d& f0 K0 f global _Num; o# M0 u4 Y/ ]4 U' I: m
temp_data = [] 0 f2 A! J: d& U% K- q items = BeautifulSoup(my_page).find_all("div", style="width:96%;margin:10px;border-bottom:1px #CCC dashed;padding-bottom:10px;")5 z( S/ ?, F6 T
for index, item in enumerate(items) :6 x( g! u$ [) _
#print item # [0 A% `1 a8 N8 D* N) T) K+ i$ m { #print item.h1; h1 ^0 }! g" F2 |7 B2 j4 y# E+ m
#print h.group() 8 i! b+ M2 p. f #temp_data.append(item) ! I* v5 t4 S. |* H) F" v0 P #print item.find(re.compile("^a")). M F% M+ ~8 f) M% F
href = item.find(re.compile("^a")) 0 T1 @# ]/ a1 u7 r" g6 S3 v: A& g #soup = BeautifulSoup(item) 5 n( h" P& Y4 P& }" t3 o #公司名称 - S, F0 \( P9 x if item.a: * q/ ?) T* P% j# q data = item.a.string.encode("gbk","ignore") & h% k" z3 M* C7 G# A print data * G- ^; E$ k* Q. `% Y temp_data.append(data) % Y+ ?3 _: Y0 j0 v$ s) I) Y1 t+ k! W( n& k7 m2 q
goods = item.find_all("div", style="font-size:12px;")8 R5 x* I: v. \
7 }* f7 b1 A) {% C# n9 b% T! T( H #经营产品与联系方式 ( p0 Z) q9 v% L" T for i in goods: " i4 Y4 m: w. \ data = i.get_text().encode("gbk","ignore")0 j0 f9 v, O( n' a. U" @
temp_data.append(data)% o8 N1 h! e- x7 [
print data I5 e9 i$ d1 I0 Z9 W& I
#b = item.find_all("b")9 S. ^' M# R6 p
#print b 5 J- W; g; k' z #链接地址2 [8 y( C+ d5 i9 Z$ c" w3 X
pat = re.compile(r'href="([^"]*)"') 5 y, u0 W- R% u7 p2 Z3 k h = pat.search(str(item)) 7 M: D# V. W& u( ^ if h:4 w0 J9 y x6 {& q1 }- ~) M4 J Y3 J, s
#print h.group(0) , n+ d0 ~' E4 q href = h.group(1) ( Q# a* ~% M% b' j9 k2 l, G print href$ ^# _, Q- s- l! |" ?% A; C" {
temp_data.append(h.group(1)) # k/ e) |. W. u' @/ e1 r" Y, } ( v) k& C4 a8 g" ^5 e" R3 D. L3 `2 G _Num += 1 6 p6 Z* X2 A: ?- ]0 R, c #b = item.find_all(text=re.compile("Dormouse")) & p6 d# T* Y& |+ u! J+ W S( W #pprint(goods)( e& `* M) ]+ h, L# L
#print href % D( b) e( s) T) g' i+ e$ _ #pat = re.compile(r'title="([^"]*)"') b# Q! E7 E: v# w# `% Y #h = pat.search(str(href))6 c' d/ h5 |% S1 L: U; U
#if h:; M' o* |3 R/ U# W
#print h.group(1) ; C$ z6 r" H: v1 O #temp_data.append(h.group(1))' V/ {5 z' r! Z) K; \( y9 x
_DATA.append(temp_data)2 u2 W+ ], `! n& @+ ^
9 z/ f8 [& M% {1 i& ^* O. [#headers = {'User-Agent':"Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.1 (KHTML, like Gecko) Chrome/22.0.1207.1 Safari/537.1"}##浏览器请求头(大部分网站没有这个请求头会报错、请务必加上哦) , Y: C; K* W6 f2 f# u" I#all_url = 'http://www.mzitu.com/all' ##开始的URL地址2 @+ \7 A1 V4 a; f7 K, z" }" s
#start_html = requests.get(all_url, headers=headers) ##使用requests中的get方法来获取all_url(就是:http://www.mzitu.com/all这个地址)的内容 headers为上面设置的请求头、请务必参考requests官方文档解释 $ H7 c Z1 k6 r* @. \1 ^! m% w#print(start_html.text) ##打印出start_html (请注意,concent是二进制的数据,一般用于下载图片、视频、音频、等多媒体内容是才使用concent, 对于打印网页内容请使用text). ^& x P( n' R. g N" @) N
5 s6 |2 |" [& `/ X7 T* {( idef main() : % x1 K4 E+ w# p* ]& F global SHARE_Q K( q# a" l. U' d threads = []+ K; R( [8 M! @( @" N
start = time.clock() 8 l6 h9 j* L( ? Z( F% k douban_url = "http://company.yktworld.com/comapny_search.asp?page={page}"- ], O4 ]! Z! E9 g+ W; S9 R0 p
#向队列中放入任务, 真正使用时, 应该设置为可持续的放入任务1 K* _6 t) m7 S: A$ N
for index in xrange(20) : - V6 {) h. u2 ?/ M; Z7 o6 N SHARE_Q.put(douban_url.format(page = index * 1))& C& X+ o' y. @, ]8 e r
for i in xrange(_WORKER_THREAD_NUM) : 8 b2 ^# Y1 E1 o: Z' O2 W8 C thread = MyThread(worker,i) % ]( M; Y8 C6 ?$ `# t' W& I thread.start() #线程开始处理任务; q: d7 a# H+ y) B& e1 e& B
" ]- s3 K: Q+ [2 h: b& F threads.append(thread) p0 O3 c! Q6 d9 u4 {, U f for thread in threads : 5 ^) J4 ~( e+ x2 e: ~ thread.join()/ c7 ~% M7 q4 T' v% z
SHARE_Q.join() , V# m8 w+ F, k i = 05 F9 R2 _9 E; C2 Z5 t. L
with open("down.txt", "w+") as my_file : 2 B- ~: Z/ \% T3 N2 O" {$ g for page in _DATA :$ l3 y1 R5 a7 O$ {) G
i += 10 G. d, ]8 X' f, P
for name in page: `; Z4 N$ F2 a& E my_file.write(name + "\n")1 x! t/ c. j! y
) }/ K' m0 k& O+ r9 A print "Spider Successful!!!") Q* y5 w0 [1 Y/ A8 Z- X4 E
end = time.clock()8 R8 R- \) k, g! A! J1 ?
print u'抓取完成!' / P( k1 v! X0 N0 c print u'总页数:',i / {% E9 {; s0 }6 i7 ?% U3 B' a. I" b0 [ print u'总条数:',_Num& f& Q& M8 d& B8 l. V0 e
print u'一共用时:',end-start,u'秒'0 Y* o, k) @% E) J, w/ G" b
+ U. ~ L. F/ ?* W% Cif __name__ == '__main__':9 {# l7 f2 j+ ?: o( ?) Y, x
main() N! L: x' i/ ~6 {; W j+ |; @# y8 j r( E) `' x7 A8 Z0 |
( k6 A: q/ M% K$ H% O; t