爬虫框架的基础理论部分"/>
搭建爬虫框架的基础理论部分
python本来就是一门敏捷、快速的开发语言。就爬虫而言,如果说每次登录一下知乎,或者说每次爬取一些小说都要完成从请求到保存的步骤的话,那么可能你不适合学习python,正所谓人生苦短,我用python。
分析整个请求到保存的过程:不管是自己写的微型框架还是非常受宠的scrapy框架,都需要这几个步骤。麻雀再小都是肉,哦!不对,是麻雀再小,五脏俱全~~~~
先looklook上边这张图自己研究研究。看看是不是这么个理?如果不是的话,欢迎下方吐槽,会及时更改。
步骤一:URL管理 小型爬虫用python自带的set(目的自动去重) 大型的爬虫或者分布式爬虫人家都用redis来管理队列了
所谓URL管理,就拿你去爬去某站妹子图来说吧,一个URL,也就包含那么十几张图,而你需要做的任务就是每次获取下一页的URL并且访问它去爬取对应下一页的图片和下下一页的URL。 这里最容易把人整晕。建议多练练,就能体会到了。
一般来说,这个管理器都是封装好的,自己写框架也就需要自己把结合写好,方便直接调用
步骤二:请求处理Requests
请求库就不说那么多了,像什么urllib,urllib2,urllib3,requests之类的,推荐使用requests,真的是好用。
这个模块可以封装成半成品,根据每次的需求来进行修改,例如需要登录和不需要登录等等
步骤三:页面解析模块,写这个模块之前请仔细掂量掂量自己到底需要的什么数据。
主要使用的解析库 也就re,xpath,beautifulsoup,css-selector 这就够用了。
这个模块是根据每次请求的需求来进行的。
但是强烈建议时刻提醒自己需要哪些数据,因为这样可以帮助你把后边的接口写好,方便schedule来调用
步骤四:数据储存了,这个完全可以高度封装,完全写死一个数据库或者一个数据表。或者就自行配置一下就行了
这个步骤完全是一劳永逸的。
步骤五:你又不是只在一个网页深度晃悠,你总得去子节点找数据吧。就相当于你在百度搜索妹子,你总不可能就在
它找出来的第一个页面晃悠吧,你总得点进去,才能发现新世界的大门。从数据里边分析的子URL那么就又得交给管理器
大哥了,真心累。
说完了以上五个步骤,那么就真刀真枪的干一下 当然还是老掉牙的豆瓣top250,但是是用这个简单的框架来做
1、url管理器
class UrlManager:def __init__(self):'''初始化连个序列 主要是用来去重'''self.new_url_queue = set() #待爬取的URL队列self.old_url_queue = set() #已经爬取的URL队列def has_new_url(self):'''判断self.new_url_queue中是否还有未爬取的url'''if self.new_url_size() != 0:print('队列中有未爬去的url')else:print('没有待爬取的url了')return self.new_url_size() != 0def get_new_url(self):'''从队列中拿出url去请求 那么就把这个url放入到old_queue中去在set中 pop是对栈首弹出 add是在栈尾插入'''new_url = self.new_url_queue.pop()self.old_url_queue.add(new_url)return new_urldef add_new_url(self, url):'''往队列中添加新的url'''print('收到了%s' % url)if url is None:returnif url not in self.new_url_queue and url not in self.old_url_queue:self.new_url_queue.add(url)print('已经添加到队列中,请等待>>>>>>')def add_new_urls(self, urls):'''往队列中添加新的url集合'''if urls is None or len(urls) == 0:returnfor url in urls:self.new_url_queue.add(url)def new_url_size(self):'''获取new_url队列的长度'''return len(self.new_url_queue)def old_url_size(self):'''获取old_url队列的长度'''return len(self.old_url_queue)
二、请求模块
import requests
from random import choice
from setting import user_agent # 一个自己搜集的User-Agent库资源class HTMLDownloader:def downloader(self, url):if url is None:return Noneheaders = {'User-Agent': choice(user_agent)}response = requests.get(url, headers=headers)if response.status_code == 200:#print('状态吗是200,请求成功》》')response.encoding = 'utf-8'return response.textreturn None
三、解析模块(篇幅问题只是解析了每一部电影的URL)
from lxml import etree
import re
from bs4 import BeautifulSoup
'''
三个主要使用的html解析库
'''
class HTMLParse:'''re在此不进行封装,具体在xpath 和 beautifulsoup中使用'''def parse_in_xpath(self, html_content):'''在此填写需要解析的内容'''html = etree.HTML(html_content)each_movie_url = html.xpath(r'//*[@id="wrapper"]/div[1]/div[1]/div[1]/ol/li/div[1]/div[2]/div[1]/a/@href') # 每一部电影的urlall_page_urls = html.xpath(r'//*[@id="content"]/div[1]/div[1]/div[2]/a/@href') # 下一页的urlreturn each_movie_url, all_page_urlsdef parse_in_bs4(self):'''在此填写需要解析的内容'''return
四、数据存储模块:(写入一个html文件中去)
import codecs
class DataOutput:def __init__(self):self.datas = []def store_data(self, data):if data is None:returnself.datas.append(data)def output_html(self, filename):fout = codecs.open(filename, 'a+', encoding='utf-8')fout.write("<html>")fout.write("<head><meta charset='utf-8'/><head>")fout.write("<body>")fout.write("<table>")for data in self.datas:fout.write("<tr>")fout.write("<td>%s</td>" % data)fout.write("</tr>")self.datas.remove(data)fout.write("</table>")fout.write("</body>")fout.write("</html>")fout.close()
效果截图:
咋说呢,一直在纠结URL队列问题,这次下了个狠心KO了它,做个小笔记,见证自己的成长。
欢迎各位批评指正。
更多推荐
搭建爬虫框架的基础理论部分
发布评论