Python爬虫入门—分析Ajax爬取今日头条美图
本篇“玩python”来源答主链接:
相似参考博文链接:
python 分析Ajax来抓取今日头条街拍美图
python爬虫—— 抓取今日头条的街拍的妹子图
环境配置:
1.系统环境:Ubuntu 14.04 LTS
2.编译环境:Python3.4.3
3.依赖库: requests pymongo BeautifulSoup re json multiprocessing
4.其他工具:Chrome浏览器
网页分析
首先使用Chrome浏览器打开要爬取的网页
1.搜索框内查找网页
2.进入目的网页点击右键–检查
3.找到所用信息
鼠标选定的那个就是其中一页索引页,一共加载了四页。
我们可以看到 四个索引页之间的区别只有 offset参数有区别,其他都是一模一样的。
如此来说我们就可以通过修改offset参数来获取任意索引页了。
第一页索引页 offset = 0
第二页索引页 offset = 20
第三页索引页 offset = 40
第四页索引页 offset = 60
由此可以看出 offset的规律是 跨步20递增。
代码浅析
流程图
配置文件config
首先得把config.py文件了解清楚,该文件的目的有两个:
- 其一:配置mongoDB数据库相关的内容
- 其二:配置下载页数及关键词KEYWORD
MONGO_URL ='localhost'
MONGO_DB = 'toutiao'
MONGO_TABLE = 'toutiao'
GROUP_START = 1
GROUP_END = 2
KEYWORD = '模特'
注意:
记得导入该文件:from config import *
第一次导入时,会自动生成一个名为__pycache__文件夹,该文件里含有config.cpython-34.pyc,是一个二进制文件,百度可知其作用是:下次再导入时速度会很快。暂时理解为缓冲器,未作深究。
抓取首页
def get_page_first(offest,keyword):#抓取首页
data={
'offset':offest, #offest可变
'format':'json',
'keyword':keyword,#keyword是可以从config,py文件中定义
'autoload':'true',
'count':'20',
'cur_tab':3
}
url='http://www.toutiao.com/search_content/?'+urlencode(data)
try:
response=requests.get(url) #请求url
if response.status_code==200:
return response.text
return None
except RequestException:
print('请求异常')
return None
调用requests的get方法得到网页,状态码200代表请求正常请求成功。
分析首页
def parse_page_first(html):
data=json.loads(html)#转换成json对象
if data and 'data' in data.keys():
for item in data.get('data'):#data这个对象非空 并且存在key为'data'数据
yield item.get('article_url')
这里要说明一下,可能data多次出现会导致混乱,注释里已经注明。‘data’即这个单引号括起来的data,是Json对象data里的一个Key值为‘data’的数据,这里面放着什么呢?在Chrome浏览器“检查”分析的时候会看到,这里面存在着我们想要的数据,title(标题)、image_list(存放图片链接的列表)等等。yield生成器不再赘述,可参看上一篇里的菜鸟教程的链接。
抓取详情页
def get_page_detai(url):#详情页url
try:
response=requests.get(url) #请求url
if response.status_code==200:
return response.text
return None
except RequestException:
print('请求异常')
return None
分析详情页
def parse_page_chirld(htmlchirld,url):
soup=BeautifulSoup(htmlchirld,'lxml')
title=soup.select('title')[0].get_text()
print(title)
# print(htmlchirld)
images_pattern=re.compile('gallery: (.*?),\n',re.S)
result = re.search(images_pattern, htmlchirld)
if result:
result = result.group(1)
# print(result) #log1
result = result[12:]
result = result[:-2]
result = re.sub(r'\\','',result)
# print(result) #log2
data = json.loads(result)
print(data)
if data and 'sub_images' in data.keys(): sub_images = data.get('sub_images')
images_url=[item.get('url') for item in sub_images]
for image in images_url:
download_image(image)
return {
'title': title,
'url': url,
'images_url': images_url
}
log1与log2调试时添加,其中的几行代码也是添加的,关于代码中re正常匹配请参考菜鸟教程python3正则部分。为什么去匹配”gallery”?匹配返回的是:
<_sre.SRE_Match object; span=(4521, 8184), match='gallery: JSON.parse("{\\"count\\":5,\\"sub_images>
而再调用group(1)会得到一个不标准无法直接JSON解析的<class str>
,于是就有手动切片处理字符串,去除字符“\”的一系列操作。
下载图片
def download_image(url):
print('正在下载',url)
try:
response=requests.get(url)
if response.status_code==200:
save_image(response.content)#content二进制
return None
except RequestException:
print('请求图片出错',url)
return None
def save_image(content):
file_path='{0}/{1}.{2}'.format('./',md5(content).hexdigest(),'jpg')
if not os.path.exists(file_path):
with open(file_path,'wb') as f:
f.write(content)
f.close()
这部分很简单,陌生的hashlib的md5加密算法。
md5(content).hexdigest()
上面这个调用返回的是一个真正的哈希码,即这种形式:9d5e54f12f3f4a8b6dd02439b1a3da144ce20e89
存入数据库
def save_to_mongo(result):
if db[MONGO_TABLE].insert(result):
print('储存mongodb成功',result)
return True
return False
单单上面几行代码还无法完成将result这个dict存入数据库的操作,还需要:
1.config配置正确无误
2.在代码执行到的地方加入
client=pymongo.MongoClient(MONGO_URL)
db=client[MONGO_DB]
效果
查看数据库择需要命令:
mongo
use toutiao
db.toutiao.find().pretty()
回顾与思考
- 多线程的优势慢慢显露,下载更快。
- MongoDB 旨在为WEB应用提供可扩展的高性能数据存储解决方案。
- MongoDB将数据存储为一个文档,数据结构由键值(key=>value)对组成。
- MongoDB文档类似于JSON对象。字段值可以包含其他文档,数组及文档数组。
- Ajax是一种动态更新网页界面的技术。即:AJAX 是一种在无需重新加载整个网页的情况下,能够更新部分网页的技术。
- 可以尝试导入argv将代码写成带参数的脚本形式,配置文件内容写进脚本,参数是关键词等等。