爬虫初体验-- 爬取当当书籍

这是我从学习Python 开始,第4天写的爬虫,所以有很多地方写的不太好,还希望各位多多包涵,欢迎指正,互相学习。

我学习python就是为了玩爬虫的。第一次听说爬虫这个名字,就觉得很有趣(事实证明确实很有趣),趁着暑假没事,赶紧搞了搞,确实很好玩。

这篇文章我更希望可以让和我一样的初学爬虫小伙伴看到,我觉得很不错,至少这个爬虫可以爬取大部分的网站(虽然性能一般),个人玩耍,足够了。

注意:本人用的python2.7版本的 以下用到各种第三方库 windows的同学都可以通过cmd小黑框,输入“pip install
第三方库”进行安装(别忘了配置环境变量) 例如安装requests库 就可以输入 pip install requests
回车,提示Successful就说明安装成功


废话少说,开始进入正题----

首先,我先讲解一下我整个项目的大题结构:

分为5个文件,即5个类:
分别是1、spider_main.py     即主函数,用于启动爬虫2、url_manager.py     这个是url管理器,用于管理url3、html_downloader.py 这个是html下载器,用于下载给定url 的源码4、html_parser.py     这个是html解析器,用于提取你想要的信息5、html_outputer.py   这个是html输出器,用于把提取的信息存储到文件或者数据库

下面我来一一讲解这几个类的作用:

一、主类:

用于启动爬虫,让爬虫动起来
其中重要的函数crawl 主要思想是:启动爬虫
先把根url(即初始的url)添加到管理器中
然后进入while循环,判断是否有新的url
如果有,则从url管理器中拿出来一个新的url
然后开始下载url对应的HTML页面
再对得到的页面进行解析,得到新的url和数据
把得到的新的url添加到url管理器中
把解析过后的数据利用输出器,放入文件当中

以上是大体思路,请仔细思考,然后就能以不变应万变喽。
附上代码spider_main.py:

# coding: utf-8
import url_manager,html_downloader,html_parser,html_outputer
class SpiderMain(object):"""docstring for SpiderMain"""#实例化各个部件def __init__(self):self.urls = url_manager.UrlManager()self.downloader = html_downloader.HtmlDownloader()self.parser = html_parser.HtmlParser()self.outputer = html_outputer.HtmlOutputer()#启动爬虫def crawl(self,root_url):count = 1self.urls.add_new_url(root_url) #先把根url(即初始的url)添加到管理器中while self.urls.has_new_url():  #然后进入while循环,判断是否有新的urltry:#如果有,则从url管理器中拿出来一个新的urlnew_url = self.urls.get_new_url() #然后开始下载url对应的HTML页面html_cont = self.downloader.download(new_url)#再对得到的页面进行解析,得到新的url和数据new_urls,new_data = self.parser.parse(new_url,html_cont)#把得到的新的url添加到url管理器中self.urls.add_new_urls(new_urls)#收集数据self.outputer.collect(new_data)if new_data != None:print 'crawl %d : %s' %(count,new_url)count = count + 1#这个判断用来控制爬取多少本书籍if count > 50:breakexcept:print 'crawl failed'#把解析过后的数据利用输出器,放入文件当中self.outputer.output_html()if __name__ == '__main__':root_url = "http://book.dangdang.com/"obj_spider = SpiderMain()obj_spider.crawl(root_url)  #启动爬虫

如果细节有什么不懂的地方,联系我呦,可以互相交流一下

二、url管理器

初始化了两个set集合,分别用来存放,未爬取的url和已爬取的url。
set集合有元素不重复的特点,用set集合存放url,用于驱虫,再合适不过了。
有四个方法:
1、add_new_url() 用于添加新的单个url
2、add_new_urls() 用于批量添加新的url,
3、get_new_url() 用于从未爬取set集合中拿url
4、has_new_url() 用于判断是否还有未爬取的url
附上url_manager.py代码:

# coding: utf-8
class UrlManager(object):def __init__(self):#这个set集合用来存放待抓取的urlself.new_urls = set()#这个set集合用来存放已经抓取过的urlself.old_urls = set()#用于添加新的单个urldef add_new_url(self,url):if url is None:return#如果抓取的的url不在这两个集合当中,则认定是新的urlif url not in self.new_urls and url not in self.old_urls:self.new_urls.add(url)  #用于批量添加新的urldef add_new_urls(self,urls):if urls is None or len(urls) == 0:return for url in urls:self.add_new_url(url)#用于判断是否还有未爬取的urldef has_new_url(self):return len(self.new_urls) != 0#用于从未爬取set集合中拿urldef get_new_url(self):#pop()的作用就是从set()集合中取出带爬取的urlnew_url = self.new_urls.pop()#取出后,放入已爬取的set()集合中self.old_urls.add(new_url)return new_url

三、html下载器:

这个就比较简单了,就是把页面的所有内容下载下来
这里可以使用requests库,或者urllib2库,

这个是用urllib2写的:

# coding: utf-8
import MySQLdb#下面这三行是用来解决编码问题的
import sys
reload(sys)
sys.setdefaultencoding('utf-8')import urllib2
class HtmlDownloader(object):def download(self,url):if url is None:return None#加入头部,伪装成浏览器headers = {'User-Agent':'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.36'}req = urllib2.Request(url,headers=headers)response = urllib2.urlopen(req,timeout=20)#判断返回的状态码是不是200(用来判定是否请求成功)if response.getcode() != 200:return None#返回html的内容return response.read()

这里我伪装了浏览器,在头字段里加入了浏览器的user-agent ,这是最基础的对抗反爬策略
注意:特别强调,凡是遇到过编码问题的小伙伴,加上这三句话,简直就是万能钥匙:

import sys,MySQLdb
reload(sys)
sys.setdefaultencoding('utf-8')

后来我取了随机的user-agent,我会在以后的文章中提到,为了节约篇幅和便于理解与消化,这里不再讲述

html_downloader.py到此结束

接下来是爬虫最核心的部分–

四、html解析器:

这个是爬虫的精髓,它有两个作用:

(1) 是提取到你想要的信息
(2) 是提取新的url

这里用了BuautifulSoup4库(非常优秀的html解析库),re库(正则表达式),urlparse库(用于拼装完整的url)

如果不太会用正则的小伙伴,推荐去看慕课Python正则表达式

共有三个方法:
parse()        用于创建BuautifulSoup对象,交给另外两个方法进行解析
get_new_data()     用于提取新的数据
get_new_urls()    用于提取页面中的url

下面附上代码:
html_parser.py:

# coding: utf-8
from bs4 import BeautifulSoup
import re,urlparse,json,requests
class HtmlParser(object):#这里用来抓取新的urldef get_new_urls(self,page_url,soup):new_urls = set()#用正则表达式来提取新的url#http://category.dangdang.com/[.\w]+\.html 是分类的url#http://product.dangdang.com/*\d+\.html* 是书籍的urllinks = soup.find_all('a',href=re.compile(r"http://product.dangdang.com/*\d+\.html*|http://category.dangdang.com/[.\w]+\.html"))for link in links:new_url = link['href']#这个是用来拼装url的,因为new_url并不完整,需要与page_url的一部分拼装,这里urljoin方法可以智能拼装new_full_url = urlparse.urljoin(page_url,new_url)# print new_full_urlnew_urls.add(new_full_url)return new_urls#这里是这提取数据的部分def get_new_data(self,page_url,html_cont,soup):#这里用一个字典来存储数据res_data = {}title_no = soup.find('div',class_='name_info')if title_no != None:#这里只提取了页面的title和价格res_data['url'] = page_urltitle_node = title_no.find('h1')res_data['title'] = title_node.get_text()price_node = soup.find('p',id='dd-price')res_data['price'] = price_node.get_text()return res_datareturn None   #这个方法主要用来创建BeautifulSoup对象,并收集所需的数据返回给下一个部件def parse(self,page_url,html_cont):if page_url is None or html_cont is None:returnsoup = 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,html_cont,soup)return new_urls,new_data

数据解析完了
接下来来保存和输出了吧
鉴于这是最初级的爬虫,我在这里只保存到html文件,打开即可查看你爬取的数据

五、html输出器

这个我就不多做解释了, 有一定前端基础的同学,都能看懂
实在看不懂的同学,先去稍微了解一下web前端基础吧!
这里还用到了写入文件,如果对这一块陌生的同学,推荐去看Python文件操作

# coding: utf-8
import sys
reload(sys)
sys.setdefaultencoding('utf8')
# print dir(sys)
# x = 0
class HtmlOutputer(object):"""docstring for HtmlOutputer"""#这里创建了一个空列表,用来存数据datas = []#这个方法用来收集数据存到datas列表里边def collect(self,data):if data is None:return self.datas.append(data)#这个就是把datas写入到文件里def output_html(self):fout = open('output.html','w')fout.write('<html>')fout.write('<body>')fout.write('<table>')for data in self.datas:fout.write('<tr>')fout.write('<td>%s</td>' %data['url'])fout.write('<td>%s</td>' %data['title'].encode('utf-8'))fout.write('<td>%s</td>' %data['price'].encode('utf-8'))fout.write('</tr>')fout.write('</table>')fout.write('</body>')fout.write('</html>')

以上就是我人生的第一个爬虫,再此做记录,供大家学习与交流,若有错误,欢迎指正,相互交流,共同进步!!
博主是在慕课网上get到该技能的,有兴趣的同学可以去看看

源码打包带走,拿去玩:
http://pan.baidu.com/s/1eSAIu5s

在下一篇 爬取当当书籍“进阶篇”中,我会进行抓取Ajax异步请求的数据,以及存储到MySql数据库中,以及高伪装成浏览器。

拯救不开心!!!

爬虫初体验-- 爬取当当书籍相关推荐

  1. 爬虫再体验--爬取当当书籍--进阶篇

    爬取当当书籍–进阶篇 在上一篇爬虫初体验中, 叙述了我的小爬虫的整体构架以及中心思想,并且在小伙伴的反馈下,进行了改良,加入了许多的注释,方便大家学习与交流. 在基础篇中,只是简单的爬取了3个字段,小 ...

  2. 在当当买了python怎么下载源代码-爬虫实战:爬取当当网所有 Python 书籍

    来源:公众号-极客猴 出处: 本文主要讲解如何利用urllib.re.BeautifulSoup 这几个库去实战,爬取当当网所有 Python 书籍. 1 确定爬取目标 任何网站皆可爬取,就看你要不要 ...

  3. python爬虫什么书好_python爬虫入门06 | 爬取当当网 Top 500 本五星好评书籍

    来啦,老弟 image 我们已经知道怎么使用 Requests 进行各种请求骚操作 也知道了对服务器返回的数据如何使用 正则表达式 来过滤我们想要的内容 - 那么接下来 我们就使用 requests ...

  4. 请用Python写一个爬虫程序,爬取当当网图书畅销榜数据

    好的,下面是一个简单的 Python 爬虫代码,可以爬取当当网图书畅销榜数据: import requests from bs4 import BeautifulSoupurl = "htt ...

  5. 爬虫小案例-爬取当当网TOP500的图书并将数据存入数据库

    在这里分享一个刚刚学习爬虫时自己做的一个小案例,爬取了当当网TOP500的图书信息,包括图书名称.作者名称和出版社的名称. 1.分析网页 url:http://bang.dangdang.com/bo ...

  6. python爬虫06 | 你的第一个爬虫,爬取当当网 Top 500 本五星好评书籍

    来啦,老弟 我们已经知道怎么使用 Requests 进行各种请求骚操作 也知道了对服务器返回的数据如何使用 正则表达式 来过滤我们想要的内容 ... 那么接下来 我们就使用 requests 和 re ...

  7. Python 爬虫第三步 -- 多线程爬虫爬取当当网书籍信息

    XPath 的安装以及使用 1 . XPath 的介绍 刚学过正则表达式,用的正顺手,现在就把正则表达式替换掉,使用 XPath,有人表示这太坑爹了,早知道刚上来就学习 XPath 多省事 啊.其实我 ...

  8. bs4爬取的时候有两个标签相同_python爬虫初体验,爬取中国最好大学网大学名次...

    程序员天天只顾写生活琐事的文章可就太对不起其他的程序员们了,某大佬给我在线寄了一张刀片的图片,催更技术分享,不得不动手了.从今年刚开始学习python,美妙的语法令人陶醉,好用的第三方库令人爱不释手. ...

  9. 爬虫百战(一):爬取当当网Top500本五星好评书籍

    爬取当当网Top500本五星好评书籍 ==实战前提:== 准备工作 撸代码 成果展示 实战前提: 掌握requests库的使用 熟悉re库,正则表达式的简单使用 可参考我的另外两篇博客进行学习 准备工 ...

最新文章

  1. 如何定位cpu占用率高的java线程
  2. 终聚.net平台开发
  3. 5、Hive的自定义UDF函数
  4. 获取当地天气_Mac 天气预报动态壁纸工具Living Weather HD 4.4.4
  5. SQL2000数据库中删除“坏表”的方法
  6. 动态代理之: com.sun.proxy.$Proxy0 cannot be cast to 问题
  7. C++ 长指针与指针的区别
  8. 人工智能在fpga的具体应用_“基于FPGA的人工智能应用技术师资培训”圆满落幕!...
  9. ASP 無組件上傳類
  10. [oracle] 设置PL/SQL Developer 字符集
  11. 测试用例设计方法-场景法详解
  12. mysql 单精度和双经度_***mysql中经度纬度字段用什么存储(关于mysql的float和decimal区别)...
  13. PCB板上走100A电流的方法
  14. 2015,了不起的邮件创意!
  15. Centos 查看 CPU 核数 和 型号 和 主频
  16. 国外问卷调查这个项目可以做吗?
  17. C++解一元二次方程
  18. 软考科目那么多,该报哪个?
  19. 仿热血江湖帮战客方血帮战 开始对战记时器结束事件
  20. 通用验证系统commons-validator

热门文章

  1. linux查看端口状态防火墙开放端口
  2. Druid监控统计数据源
  3. 虽然杀伤力极强 但勒索病毒尚难引发网络战争
  4. native 真机测试react_React Native iOS 真机调试
  5. JSP和js(JavaScript )区别
  6. 普通护照出国免签及落地签国家和地区
  7. PHP之 常见问题拾记
  8. sql server 数据库向java接口推送数据
  9. linux如何挂载硬盘linux服务器上挂载磁盘(图文详解)
  10. Learning the Best Pooling Strategy for Visual Semantic Embedding