python3爬虫——爬取糗事百科
萌新在爬取糗事百科时遇到了许多麻烦,幸好看到了hailofwu:https://blog.csdn.net/xixi880928/article/details/78346728 大佬的文章。
不过大佬写了思路和源码,没写详细基础类容,所以我作些补充,并写上思路,这样看起来更易理解。
请先看大佬的文章后再来,希望这篇文章能帮到你。
def getPage(self, pageIndex):
try:
url = 'https://www.qiushibaike.com/hot/page/'+str(pageIndex)
req = urllib.request.Request(url, headers = self.headers)
res = urllib.request.urlopen(req)
content = res.read().decode('utf-8')
return content
except urllib.error.URLError as e:
if hasattr(e, "reason"):
print ('连接糗事百科失败,错误原因:',e.reason)
res = urllib.requests.urlopen(rep)可以将rep的内容作为一个类对象文件保存在res中,这样才能够用read()读取。
hasattr用来找错误信息中的reason,直接返回原因。
def getPageItems(self, pageIndex):
content = self.getPage(pageIndex)
pattern = re.compile('<div.*?author.*?<a.*?<img.*?alt="(.*?)">.*?<div class="content.*?'+
'<span>(.*?)</span>.*?<span class="stats-vote".*?<i class="number">(.*?)</i>',re.S)
items = re.findall(pattern,content)
pageStories = []
for item in items:
replaceBR = re.compile('<br/>')
text = re.sub(replaceBR, "\n", item[1])
pageStories.append([item[0].strip(),text.strip(),item[2].strip()])
return pageStories
re.compile可以理解为用这个函数处理过后才能用re.findall之类的。
.?是匹配任意数量的任意字符。
(.?)是要获取的信息。
re.sub将获取的文本信息中的’
‘换成’/n’。
源代码:
#!/usr/bin/env/python
#encoding: UTF-8
import re
import requests
import http.cookiejar
import time
import json
import urllib
#糗事百科爬虫类
class QSBK:
def __init__(self):
self.pageIndex = 1
self.headers = {
'User-Agent': r'Mozilla/4.0 (compatible; MSIE 5.5; Windows NT) '
r'Chrome/45.0.2454.85 Safari/537.36 115Browser/6.0.3',
'Referer': r'https://www.qiushibaike.com/',
'Connection': 'keep-alive'
}
self.stories = []
#存放程序是否继续运行的变量
self.enable = False
#传入某一页的索引获取页面代码的函数
def getPage(self, pageIndex):
try:
url = 'https://www.qiushibaike.com/hot/page/'+str(pageIndex)
req = urllib.request.Request(url, headers = self.headers)
res = urllib.request.urlopen(req)
content = res.read().decode('utf-8')
return content
except urllib.error.URLError as e:
if hasattr(e, "reason"):
print ('连接糗事百科失败,错误原因:',e.reason)
return None
#传入页面代码,返回段子列表
def getPageItems(self, pageIndex):
content = self.getPage(pageIndex)
pattern = re.compile('<div.*?author.*?<a.*?<img.*?alt="(.*?)">.*?<div class="content.*?'+
'<span>(.*?)</span>.*?<span class="stats-vote".*?<i class="number">(.*?)</i>',re.S)
items = re.findall(pattern,content) #找到content中全部符合pattern的内容
pageStories = []
for item in items:
replaceBR = re.compile('<br/>')
text = re.sub(replaceBR, "\n", item[1])
pageStories.append([item[0].strip(),text.strip(),item[2].strip()])
return pageStories
#加载并提取页面内容,加入列表中
def loadPage(self):
if self.enable == True:
if len(self.stories)<2:
pageStories = self.getPageItems(self.pageIndex)
if pageStories:
self.stories.append(pageStories)
self.pageIndex +=1
#一次回车一个段子
def getOneStory(self, pageStories, page):
for story in pageStories:
hc = input()
self.loadPage()
if hc == "quit":
self.enable = False
return
print ("第%d页\t发布人:%s\t赞:%s\n%s"%(page,story[0],story[2],story[1]))
def start(self):
print('正在读取糗事百科段子,按回车查看新段子,quit退出')
self.enable = True
self.loadPage()
nowPage = 0 # 计算总共打印的段子数,确认是一页中第几个段子
while self.enable:
if len(self.stories)>0:
pageStories = self.stories[0]
nowPage +=1
del self.stories[0]
self.getOneStory(pageStories,nowPage)
spider = QSBK()
spider.start()
思路是每次读取一页数据存储在pageStories中,在段子数量小于2时再读取下一页。之后把pageStories的内容保存到self.stories。然后将pageStories作为变量存储第一个段子。之后将self.stories中第一个段子删除。最后返回pageStories中的信息。