爬取当当书籍–进阶篇

在上一篇爬虫初体验中, 叙述了我的小爬虫的整体构架以及中心思想,并且在小伙伴的反馈下,进行了改良,加入了许多的注释,方便大家学习与交流。

在基础篇中,只是简单的爬取了3个字段,小伪装了一下浏览器,并写入到了文件当中,是不是感觉有些low档次呢?

那么今天,咱们就来搞一些高大上的东西,


  • 咱们会把爬虫伪装的更像一个浏览器,并不断随机更换User-Agent,正所谓爬虫伪装术+影分身,迷惑网管(网站管理员)。

  • 利用Chrome自带的抓包工具捕捉AJAX异步请求的JSON数据(网页源代码中不存在或者说找不到的数据)

  • 最后咱们把提取到的数据存到MySql数据库里


温馨提示
   本篇重点讲解以上三点,若有对细节和别的地方产生困惑的话,请阅读博主上一篇爬虫初体验--爬取当当书籍

爬虫的基本结构与上一篇文章一样,咱们再来回顾一下

分为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输出器,用于把提取的信息存储到文件或者数据库

咱们今天的重点,是分别在html下载器、html解析器、html输出器上做文章。

主函数以及url管理器基本没变化,源码我会在文章末尾打包给各位

好了,开始进入正题

一、爬虫伪装术+影分身

有时候,我们的小爬虫爬着爬着就被网管拒之门外(403状态码拒绝访问),甚至刚开始就已经结束了。
那可怎么办呢,别着急,咱们来学两招

咱们在html下载器(html_downloader.py)里做文章
上一次咱们简单的加入了User-Agent,这次呢,咱们多加入几个字段

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','Accept':'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8','Accept-Encoding':'gzip, deflate, sdch, br','Accept-Language':'zh-CN,zh;q=0.8','Connection':'keep-alive','Host':'product.dangdang.com','Cookie':'',}

话说是这样,但是这些字段去哪里找呢?
来,咱们一起来找找,
首先打开浏览器,我用的Chrome,找到一个书籍网页,打开后按F12,出现调试窗口,点击菜单栏中的Network,然后点击下方的All

却发现什么也没有,不要紧,点击F5刷新网页,之后出来一大堆东西,随便点击一个(尽量选择含有较多Headers的),右方的Headers栏中会出来一大堆东西,Ruquests Headers中的东西,就是我们想要的

这些都是浏览器的标识,就相当于浏览器的身份证一样
想要了解每个字段的含义的话,推荐去看Requests Headers

到这里,咱们的伪装术完成了。

------------------------------------------这是一个搞事的分割线-----------------------------------------

单伪装成一个浏览器,可能对某些网站还是不太好使,那咱们就来个影分身

咱们随机换取User-Agent字段,让网管误以为每次访问都是不同的浏览器
首先用一个list列表来存放多个User-Agent,然后再利用random模块的 choice方法,随机抽取一个User-Agent,放进headers里去,代码如下:

# coding: utf-8
import requests,random
class HtmlDownloader(object):"""docstring for HtmlDownloader"""def __init__(self):#用来存放User-Agent的listself.user_agent_list = ["Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.1 (KHTML, like Gecko) Chrome/22.0.1207.1 Safari/537.1","Mozilla/5.0 (X11; CrOS i686 2268.111.0) AppleWebKit/536.11 (KHTML, like Gecko) Chrome/20.0.1132.57 Safari/536.11","Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/536.6 (KHTML, like Gecko) Chrome/20.0.1092.0 Safari/536.6","Mozilla/5.0 (Windows NT 6.2) AppleWebKit/536.6 (KHTML, like Gecko) Chrome/20.0.1090.0 Safari/536.6","Mozilla/5.0 (Windows NT 6.2; WOW64) AppleWebKit/537.1 (KHTML, like Gecko) Chrome/19.77.34.5 Safari/537.1","Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/536.5 (KHTML, like Gecko) Chrome/19.0.1084.9 Safari/536.5","Mozilla/5.0 (Windows NT 6.0) AppleWebKit/536.5 (KHTML, like Gecko) Chrome/19.0.1084.36 Safari/536.5",]def download(self,url):UA = random.choice(self.user_agent_list)if url == None:return 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','Accept':'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8','Accept-Encoding':'gzip, deflate, sdch, br','Accept-Language':'zh-CN,zh;q=0.8','Connection':'keep-alive','Host':'product.dangdang.com','Cookie':'',}# print "headers:%s"%(headers)res = requests.get(url,headers=headers,timeout=20)html = res.textreturn html

以上只是放入了几个User-Agent而已,我个人又整理了300多个,需要的话,拿去玩!
300多个User-Agent

好了,影分身+伪装术到此结束,是不是有点意思呢!

二、捕捉AJAX异步请求的JSON数据

有时候我们虽然拿到了整个页面的html源代码,但是怎么也找不到咱们想要拿的数据,是不是好奇怪。
这是因为那些数据是用AJAX加载出来的,如果不懂什么是AJAX,推荐看百度百科AJAX

这次咱们依然用到调试者模式,不过这次咱们的目的更加明确,就是拿通过AJAX异步请求才拿到的数据(源代码里找不到的),这次咱们拿的是总评论数,好评论数,中评,差评以及好评率(之前的做法是拿不到的,不信你试试)

还是Network,点击下方的 XHR,点击F5,然后一个一个找,右边的Preview会显示data内容,最终咱们找到了咱们想要的那个AJAX请求

之后咱们找到他所对应的url,还是在Headers里边

这个就是获取这个数据的url,你可以复制到地址栏里访问一下,返回的数据是json格式,不懂json的同学,可以百度一下。
url拿到了,咱们也就离成功不远了,
为了方便使用,我在url_parser.py里边又定义了一个方法,用来进行AJAX请求并放回的下载json数据。
http://product.dangdang.com/index.php?r=comment%2Flist&productId=25120084&categoryPath=01.01.02.00.00.00&mainProductId=25120084&mediumId=0&pageIndex=1&sortType=1&filterType=1&isSystem=1&tagId=0&tagFilterCount=0
只拿回来这个url还不够,咱们还需要对它进行分析,因为有些参数是随着不同的书籍是变的,我把多个同类的url做对比,发现其中的“productId”、“categoryPath”、“mainProductId”是变化的。
于是我们在书籍的源码中拿到这三个字段然后进行拼接。形成每本书籍特有的AJAX请求
代码如下:

# coding: utf-8
from bs4 import BeautifulSoup
import re,json,requests
class HtmlParser(object):"""docstring for HtmlParser"""def get_new_urls(self,page_url,soup):new_urls = set()links = soup.find_all('a',href=re.compile(r"http://category.dangdang.com/[.\w]+html|http://product.dangdang.com/[.\w]+html"))for link in links:new_url = link['href']new_urls.add(new_url)return new_urlsdef get_new_data(self,page_url,html,soup):data = {}link_node = soup.find('div',class_='name_info')if link_node != None:data['url'] = page_urlh1_node = link_node.find('h1')    data['title'] = h1_node.get_text().strip()               #书名price_node = soup.find('p',id='dd-price')  data['price'] = price_node.get_text().strip()[1:]        #价钱#用正则表达式拿取ma = re.search(r'"productId":"[\d]+"',html)productId =  eval(ma.group().split(':')[-1])ma = re.search(r'"categoryPath":"[\d.]+"',html)categoryPath =  eval(ma.group().split(':')[-1])# print page_urlma = re.search(r'"mainProductId":"[\d.]+"',html)mainProductId =  eval(ma.group().split(':')[-1])#对Ajax的url进行拼接json_url = 'http://product.dangdang.com/index.php?r=comment%2Flist&productId={productId}&categoryPath={categoryPath}&mainProductId={mainProductId}&mediumId=0&pageIndex=1&sortType=1&filterType=1&isSystem=1&tagId=0&tagFilterCount=0'.format(productId=productId,categoryPath=categoryPath,mainProductId=mainProductId)#调用方法,下载下来json数据json_html = json.loads(self.getJsonText(json_url))summary = json_html['data']['summary']  data['all_comment_num'] = summary['total_comment_num']             #总评论数data['good_comment_num'] = summary['total_crazy_count']               #好评数data['middle_comment_num'] = summary['total_indifferent_count']        #中评数data['bad_comment_num'] = summary['total_detest_count']                #差评数data['good_rate'] = summary['goodRate']                                #好评率return data#用于加载请求AJAX并获取json数据的方法def getJsonText(self,url):try:r = requests.get(url, timeout = 30)r.raise_for_status()r.encoding = r.apparent_encodingreturn r.textexcept:print '获取失败'return ''def parse(self,page_url,html):if page_url == None:returnsoup = BeautifulSoup(html,'html.parser')new_urls = self.get_new_urls(page_url,soup)new_data = self.get_new_data(page_url,html,soup)return new_urls,new_data

以上用到了正则表达式(Python正则教程)
还有Python内置json库(Python的json教程)
这一部分就算完成了,有什么不懂的,欢迎骚扰博主

三、存储到数据库

Python连接到数据库比java等其他语言简单多了,只需要简单的几句话
推荐教程Python对数据库操作教程
(偷个懒,写了这么多,太累了,大家去看我给你们推荐的教程吧,嘿嘿)
下面附上代码,其中有文件写入部分,和提交到数据库部分:

# coding: utf-8
import sys,MySQLdb
reload(sys)
sys.setdefaultencoding('utf-8')
class HtmlOutputer(object):"""docstring for Outputer"""def __init__(self):self.datas = []def collect(self,data):if data == None or len(data) == 0:return self.datas.append(data)#这个依然是输出到html文件里def output_html(self):f = open('out.html','w')try:f.write('<html>')f.write('<body>')f.write('<table>')for data in self.datas:f.write('<tr>')f.write('<td>%s</td><td>%s</td><td>%s</td>'%(data['url'],data['title'].encode('utf-8'),data['price'].encode('utf-8')))f.write('<td>%s</td>'%(data['all_comment_num']))f.write('<td>%s</td>'%(data['good_comment_num']))f.write('<td>%s</td>'%(data['middle_comment_num']))f.write('<td>%s</td>'%(data['bad_comment_num']))f.write('<td>%s</td>'%(data['good_rate']))f.write('</tr>')f.write('</table>')f.write('</body>')f.write('</html>')except:print '输出失败!'finally:f.close()#这个才是今天的重点,存储到数据库里def output_mysql(self):# print 'mysql'conn = MySQLdb.Connect(host = '127.0.0.1',port = 3306,user = 'root',passwd = '123',db = 'python_1',charset = 'utf8')cursor = conn.cursor()print 'datas:%d'%(len(self.datas))for data in self.datas:try:# print data# print len(data)sql = "INSERT INTO book(url,title,price,all_comment_num,good_comment_num,middle_comment_num,bad_comment_num,good_rate) VALUES('%s','%s','%s','%s','%s','%s','%s','%s')"%(data['url'],data['title'].encode('utf-8'),data['price'].encode('utf-8'),data['all_comment_num'],data['good_comment_num'],data['middle_comment_num'],data['bad_comment_num'],data['good_rate'])cursor.execute(sql)# print 'inserting'conn.commit()print 'insert success'except:print '插入失败!'continueprint 'insert end!'cursor.close()conn.close()

代码调试ok,有图有真相

以上就是所有的内容,篇幅有限,有些地方说的不够详细还请各位谅解,有什么不明白的,或者什么我写的不好的,需要改良的话,可以和博主交流交流嘛,邮箱:1131726190@qq.com

源码奉上:http://pan.baidu.com/s/1qYymLlU 拿去玩!
温情提示:
由于各个网站一直在维护与更新,爬取规则会有时效性,所以代码仅供参考!

拯救不开心!!!

爬虫再体验--爬取当当书籍--进阶篇相关推荐

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

    爬虫初体验-- 爬取当当书籍 这是我从学习Python 开始,第4天写的爬虫,所以有很多地方写的不太好,还希望各位多多包涵,欢迎指正,互相学习. 我学习python就是为了玩爬虫的.第一次听说爬虫这个 ...

  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爬京东联盟_python爬虫框架scrapy实战之爬取京东商城进阶篇

    前言 之前的一篇文章已经讲过怎样获取链接,怎样获得参数了,详情请看python爬取京东商城普通篇,本文将详细介绍利用python爬虫框架scrapy如何爬取京东商城,下面话不多说了,来看看详细的介绍吧 ...

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

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

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

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

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

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

最新文章

  1. Python2的Json反序列化工具
  2. Security issue about static code checking
  3. pandas 处理时间戳数据
  4. python下设置urllib连接超时
  5. python将json数据集转成voc xml文件
  6. MTK 10A APP,菜单,资源添加
  7. html ul li 的高度,ul与li高度不一致
  8. win10如何微信多开(无需工具)
  9. KB2999226-x64.msu 此更新不适合你的计算机VC++2015 redistributable安装出错
  10. Web开发之分页功能
  11. Codewars笔记
  12. 计算机主板与检测,主板知识详解:CPU自动检测和硬件错误的侦测
  13. ps神经网络滤镜用不了,ps神经网络滤镜安装包
  14. 注册公司的步骤及费用
  15. 逻辑函数的公式化减法
  16. [百家号]铁流:华为Hi1620发布 自研内核还是ARM改?
  17. 思维导图分享以及MindManager使用说明
  18. 底层进阶 | 移动端 GPU 架构 -- TBR 模型
  19. 软考中级 真题 2016年上半年 系统集成项目管理工程师 应用技术 下午试卷
  20. SOC设计之AMBA总线-AHB总线详解

热门文章

  1. 关于react判断是否安装app,没有则去appStore(适配android和ios)
  2. 足不出户24小时立案 广东法院全年网上立案超29万件
  3. android标题栏沉浸式,Android沉浸式状态栏方法总结
  4. 【Android -- 面试】HR 面试
  5. Oracle中模拟SQL中的isnull函数
  6. 皑皑白雪的反射光易致“雪盲”
  7. 上facebook安卓_如何在Facebook上保护您的隐私
  8. Using Celery With Django for Background Task Processing
  9. 天玑1100相当于骁龙多少处理器
  10. 莫冲动,捂口袋,练内功