刚开始学爬虫,找练手项目时遇到不少坑,一部分是因为大部分教程是基于python2的,一部分是因为各种教程里有各种坑,就是跑不通,挺影响进度的,还有一部分太高大上了,用了复杂的解析工具什么的,不利于清爽入门,好在找到了
http://www.cnblogs.com/TaylorBoy/p/6777864.html 这个教程还不错,结构清晰,内容丰富,对我帮助很大。不过在原作者的基础上做了一点改动。大家可以对比看~
import urllib.request
import re
import ssl
ssl._create_default_https_context=ssl._create_unverified_context # 我的代码里必须要加上这一句,来全局取消验证
class SQBK:
def __init__(self):
self.pageIndex=1
self.user_agent='Mozilla/4.0 (compatible; MSIE 5.5; Windows NT)'
self.headers={'User-Agent':self.user_agent}
self.storages=[]
self.enable=False
def getPage(self):
try:
url = 'http://www.qiushibaike.com/hot/page/' + str(self.pageIndex)
reqst=urllib.request.Request(url,headers=self.headers)
with urllib.request.urlopen(reqst) as response:
pageCode=response.read().decode('utf-8')
print('pageindex{}'.format(self.pageIndex))
#print('pageindex{}'.format(pageCode))
return pageCode
except urllib.request.URLError as e:
if hasattr(e,'reason'):
print('Failed',e.reason)
return None
def getPageItems(self): # 这里取消了原作者的传参,pageIndex因为它是类属性,对全部函数可见,为什么要来回传呢?
pageCode=self.getPage()
if not pageCode:
print('loading failure')
return None
pattern = re.compile('author.*?<h2>(.*?)</h2>.*?contentHerf.*?<span>(.*?)</span>' + '.*?<div class="stats">.*?class="number">(.*?)</i>.*?</div>', re.S) #这个正则提取非常不错,我之前一直苦于不知道如何提取不连续的若干段文字,这里括号内部的是要提取的内容。更多相关的内容,可以检索re模块的group相关内容。
items=re.findall(pattern,pageCode)
pageStorage=[]
for item in items:
br=re.compile('<br/>')
text=re.sub(br,'\n',item[1])
pageStorage.append([ item[2].strip(), item[0].strip(), text.strip() ])
return pageStorage
def loadPage(self):
if self.enable==True:
if len(self.storages) <2:
pageStorage=self.getPageItems()
print(pageStorage)
print(self.pageIndex)
if pageStorage:
self.storages.append(pageStorage)
self.pageIndex+=1
def getOneStory(self,pageStorage, page):
for story in pageStorage:
choose= input()
if 'Q'==choose:
self.enable=False
return
print('%d %s %s: \n%s *\n' % (page, story[1], story[0], story[2]))#这段就是打印页数、赞数、正文,博客貌似对中文不友好,所以我把里面的中文删了,应该不影响语法正确性。
def start(self):
print('start')
self.enable=True
self.loadPage()
nowPage=0
while self.enable:
if len(self.storages) >0:
pageStories=self.storages.pop(0)#这里跟原作者有一点调整,我发现作者是拿storages当queue用的,他先取出了第一个元素,之后又将其从列表里删除,那么为什么不直接用pop呢?
nowPage+=1
self.getOneStory(pageStories, nowPage)
self.loadPage()#原作者将这句话写在了getOneStory函数内部的循环内部,没有必要,并且违反逻辑,徒增调用次数,所以调到了这里。
if __name__=='__main__':
spider=SQBK()
spider.start()