Python爬虫开发与项目实战——基础爬虫分析

最近在看《Python爬虫开发与项目实战》,看到第六章基础爬虫时,发现把实现爬虫各个功能分别封装为一个类能增强爬虫的可读性,不过理解代码时碰到了许多坑,因此分享一下读书笔记。

书籍第六章的代码

代码中的注释给的已经足够了,但是只是针对单个文件,对于整体爬虫项目,理解起来难免还会有点模糊
这一章爬取的是百度百科,给出一个url通过该页面的链接爬取其它的url,看起来就像这样:

这里写图片描述
给出一个Root_Url,看看它都经历了什么
Root_url作为整个程序的第一个Url,即为一个新的Url,要加入到Url管理器中

self.manager.add_new_url(root_url)

Root_Url对应的页面肯定含有其它知识的百科链接,因此要提取,在提取之前要从Url管理器中获得Root_Url,然后获取Root_Url对应的页面的页面信息:

new_url = self.manager.get_new_url()
html = self.downloader.download(new_url)
如何从Url管理器中获取Url?

通过pop()方法每次从Url集合中取一个出来,并把取出的Url标记为已爬取的Url

URLManager.py

class UrlManager(object):
    ...
    def get_new_url(self):
        new_url = self.new_urls.pop()
        self.old_urls.add(new_url)
        return new_url
    ...
如何获取页面信息?

通过requests

HtmlDownloader.py

class HtmlDownloader(object):
    def download(self,url):
        ...
        return r.text
        ...

有了页面信息,就可以把其它知识的百科链接提取出来,以及保存当前页面知识的信息:

new_urls,data = self.parser.parser(new_url,html)
怎么获取?

通过BeautifulSoup解析HTML文档:

HtmlParser.py

class HtmlParser(object):
    def parser(self,page_url,html_cont):
        ...
        soup = BeautifulSoup(html_cont,'html.parser',from_encoding='utf-8')
        new_urls = self._get_new_urls(page_url,soup)
        new_data = self._get_new_data(page_url,soup)
        ...

    def _get_new_urls(self,page_url,soup):
        links = soup.find_all('a', href=re.compile(r'/item/.*'))
        for link in links:
            new_url = link['href']
            new_full_url = urlparse.urljoin(page_url,new_url)
            new_urls.add(new_full_url)

    def _get_new_data(self,page_url,soup):
        ...
        return data      

如果把Root-Url看作父节点,那么第一次获取的Url集合为:
这里写图片描述
获取到Url集合之后把它保存到Url管理器中

self.manager.add_new_urls(new_urls)

对于Url管理器来说实际上就是把得到Url集合添加new_urls集合的后面

URLManager.py

class UrlManager(object):
    def __init__(self):
        self.new_urls = set()
    ...

    def add_new_url(self,url):
        if url is None:
            return
        if url not in self.new_urls and url not in self.old_urls:
            self.new_urls.add(url)

    def add_new_urls(self,urls):
        if urls is None or len(urls)==0:
            return
        for url in urls:
            self.add_new_url(url)
    ...

通过BeautifulSoup库解析后的参数有两个,new_urls已经处理过了,即加入到Url管理器中了,data还没处理,需要把它存到文件中:

self.output.store_data(data)

还要打印当前处理了多少Url,即获取处理过的Url:

print "已经抓取%s个链接"%self.manager.old_url_size()

相应地,Url管理器是这么做的:

URLManager.py

class UrlManager(object):
    def __init__(self):
        self.old_urls = set()
    ...

    def old_url_size(self):
        return len(self.old_urls)

这样一次循环就完事了,第二次循环呢?
会从第一次由Root_Url产生的子Url中选择一个进行处理,如此循环,有时可能在处理子Url时,还没处理当前子Url产生的子子Url,就去处理另一个子Url,等等情况。
如果Url所构造的树为下面这样该怎么做呢?
这里写图片描述
很简单,因为Url-X不会生成子Url,因此在处理Url-x时不获取该页面所包含的其它Url即可。
可以参考一下我基于一个下小说的简易爬虫改造成多文件的代码,而不在是一个文件完成所有的功能。
自己写的代码在这

  • 8
    点赞
  • 63
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值