爬虫再体验--爬取当当书籍--进阶篇
爬取当当书籍–进阶篇
在上一篇爬虫初体验中, 叙述了我的小爬虫的整体构架以及中心思想,并且在小伙伴的反馈下,进行了改良,加入了许多的注释,方便大家学习与交流。
在基础篇中,只是简单的爬取了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 拿去玩!
温情提示:
由于各个网站一直在维护与更新,爬取规则会有时效性,所以代码仅供参考!
拯救不开心!!!
爬虫再体验--爬取当当书籍--进阶篇相关推荐
- 爬虫初体验-- 爬取当当书籍
爬虫初体验-- 爬取当当书籍 这是我从学习Python 开始,第4天写的爬虫,所以有很多地方写的不太好,还希望各位多多包涵,欢迎指正,互相学习. 我学习python就是为了玩爬虫的.第一次听说爬虫这个 ...
- 在当当买了python怎么下载源代码-爬虫实战:爬取当当网所有 Python 书籍
来源:公众号-极客猴 出处: 本文主要讲解如何利用urllib.re.BeautifulSoup 这几个库去实战,爬取当当网所有 Python 书籍. 1 确定爬取目标 任何网站皆可爬取,就看你要不要 ...
- python爬虫什么书好_python爬虫入门06 | 爬取当当网 Top 500 本五星好评书籍
来啦,老弟 image 我们已经知道怎么使用 Requests 进行各种请求骚操作 也知道了对服务器返回的数据如何使用 正则表达式 来过滤我们想要的内容 - 那么接下来 我们就使用 requests ...
- 请用Python写一个爬虫程序,爬取当当网图书畅销榜数据
好的,下面是一个简单的 Python 爬虫代码,可以爬取当当网图书畅销榜数据: import requests from bs4 import BeautifulSoupurl = "htt ...
- 爬虫小案例-爬取当当网TOP500的图书并将数据存入数据库
在这里分享一个刚刚学习爬虫时自己做的一个小案例,爬取了当当网TOP500的图书信息,包括图书名称.作者名称和出版社的名称. 1.分析网页 url:http://bang.dangdang.com/bo ...
- python爬京东联盟_python爬虫框架scrapy实战之爬取京东商城进阶篇
前言 之前的一篇文章已经讲过怎样获取链接,怎样获得参数了,详情请看python爬取京东商城普通篇,本文将详细介绍利用python爬虫框架scrapy如何爬取京东商城,下面话不多说了,来看看详细的介绍吧 ...
- python爬虫06 | 你的第一个爬虫,爬取当当网 Top 500 本五星好评书籍
来啦,老弟 我们已经知道怎么使用 Requests 进行各种请求骚操作 也知道了对服务器返回的数据如何使用 正则表达式 来过滤我们想要的内容 ... 那么接下来 我们就使用 requests 和 re ...
- Python 爬虫第三步 -- 多线程爬虫爬取当当网书籍信息
XPath 的安装以及使用 1 . XPath 的介绍 刚学过正则表达式,用的正顺手,现在就把正则表达式替换掉,使用 XPath,有人表示这太坑爹了,早知道刚上来就学习 XPath 多省事 啊.其实我 ...
- 爬虫百战(一):爬取当当网Top500本五星好评书籍
爬取当当网Top500本五星好评书籍 ==实战前提:== 准备工作 撸代码 成果展示 实战前提: 掌握requests库的使用 熟悉re库,正则表达式的简单使用 可参考我的另外两篇博客进行学习 准备工 ...
最新文章
- Python2的Json反序列化工具
- Security issue about static code checking
- pandas 处理时间戳数据
- python下设置urllib连接超时
- python将json数据集转成voc xml文件
- MTK 10A APP,菜单,资源添加
- html ul li 的高度,ul与li高度不一致
- win10如何微信多开(无需工具)
- KB2999226-x64.msu 此更新不适合你的计算机VC++2015 redistributable安装出错
- Web开发之分页功能
- Codewars笔记
- 计算机主板与检测,主板知识详解:CPU自动检测和硬件错误的侦测
- ps神经网络滤镜用不了,ps神经网络滤镜安装包
- 注册公司的步骤及费用
- 逻辑函数的公式化减法
- [百家号]铁流:华为Hi1620发布 自研内核还是ARM改?
- 思维导图分享以及MindManager使用说明
- 底层进阶 | 移动端 GPU 架构 -- TBR 模型
- 软考中级 真题 2016年上半年 系统集成项目管理工程师 应用技术 下午试卷
- SOC设计之AMBA总线-AHB总线详解
热门文章
- 关于react判断是否安装app,没有则去appStore(适配android和ios)
- 足不出户24小时立案 广东法院全年网上立案超29万件
- android标题栏沉浸式,Android沉浸式状态栏方法总结
- 【Android -- 面试】HR 面试
- Oracle中模拟SQL中的isnull函数
- 皑皑白雪的反射光易致“雪盲”
- 上facebook安卓_如何在Facebook上保护您的隐私
- Using Celery With Django for Background Task Processing
- 天玑1100相当于骁龙多少处理器
- 莫冲动,捂口袋,练内功