Python开发简单爬虫速成教程
一、简介
按照一定的规则,自动抓取网络信息的程序或者脚本,搜索引擎的重要组成。
- 搜索引擎
- 数据分析
- 人工智能
- 薅羊毛、抢车票
爬虫产品:
神箭手、八爪鱼、造数、后羿采集器
数据储备:
- python编程基础
- http
- 数据库
怎么学:
- python语法知识
- python爬虫常用到的几个重要内置库Requests,用于请求网页
- 学习正则表达式re、Xpath(IxmI)等网页解析工具
- 开始一些简单的网站爬取,了解爬取数据的过程(当当网图书数据)
- 与数据库结合,将爬取数据进行存储
安装MongoDB数据库
- 介于关系型数据库和非关系型数据库之间的产品
- 本质是非关系型数据库,最像关系数据库
- 支持的数据结构非常松散,类似json的bson格式
- 可以存储比较复杂的数据
非关系模型:
- 列模型,一列为一个记录,分布式数据库,HBase
- 键值对,redis
- 文档类,类似键值对,Mongodb
效率非常高,存储在内存中,断电即失,现在也可存储到磁盘中
检查安装是否成功:
修改设置:
/bin/mongod.cfg
右击我的电脑,管理,服务和应用程序,服务,找到MongoDB,点击重新启动。同一个局域网的机器可以连接。
安装Navicat:支持多种数据库的连接
安装教程:Navicat安装教程
使用教程:在 Navicat for MongoDB 使用文档
使用Navicat,进行MongoDB数据库的连接:
注意主机和端口号的设置
二、request模块入门
requests库:
- Requests是一个简单优雅的python HTTP库
- Requests 中文文档
通过Requests库发送http请求:
Requests模块的安装:
cmd直接安装:pip install requests
Requests模块支持的http方法:
- Get方法:请求资源
- Post方法:向服务端发送信息和数据,表单提交
- Head方法:请求资源的一些信息而不是全部信息,用于确认URL的有效性以及资源更新的日期时间
- Put方法:上传文档
- Connection方法:客户端想要确定一个明确的连接到远程主机,便于通过Http代理服务器进行SSL加密通信时连接使用,在抓包时使用
【重点】通过requests模块发送get请求
import requests
r=requests.get('http://httpbin.org/ip') #会返回当前主机的一个外网地址
# r1=requests.get('https://www.imooc.com')
print(r.text) # 输出请求体
cmd查看内网ip:ipconfig
百度查看ip地址:ip地址
【重点】通过requests模块发送post请求
一般出现在html的form表单里面
import requests
r2=requests.post(url='http://httpbin.org/post',data={'name':'imooc'})
print(r2.text)
通过requests模块的get请求构造url
主要用在get请求里面
data={"key1":"value1","key2":"value2"}
response=requests.get("http://httpbin.org/get",params=data)
# 查看当前请求的url
print(response.url)
查看响应的返回头和返回体
# 查看响应的返回头
print(response.headers)
# 查看响应的返回体
print(response.text)
返回头:
【重点】请求图片
url='https://www.imooc.com/static/img/index/logo2020.png'
r1=requests.get(url)
# 访问图片返回的是二进制数据,需要用content查看输出
print(r1.content)
#写入图片数据
with open("imooc.png","wb") as f:
f.write(r1.content)
图片二进制数据:
写入图片:
查看响应的json数据
r1=requests.get(url="http://httpbin.org/ip")
print(r1.json()) # 整个json对象 {'origin': '124.160.215.146'}
print(r1.json()["origin"]) # json中某一项 124.160.215.146
查看响应状态码
print(r1.status_code)
查看request的请求头
print(r1.request.headers)
请求头可以修改,可以通过构造request请求头
headers={
"user-agent":"joseph/v1"
}
r1=requests.get(url="http://httpbin.org/ip",headers=headers)
print(r1.request.headers)
在反爬机制中可以使用,可以模拟win,ipad,手机
三、requests模块进阶
设置连接超时
当请求超时,放弃请求
# 0.0001秒之内返回网页数据
# 超时时间一般设置为2到3秒
start_time=time.time()
r1=requests.get(url="https://www.imooc.com",timeout=2)
end_time=time.time()
print(r1.text)
print(end_time-start_time)
查看响应设置的cookies
可以在headers中查看
也可以通过cookies查看
行为和字典非常的像
r1=requests.get(url="https://www.baidu.com")
print(r1.headers)
print(r1.cookies)
print(r1.cookies["BDORZ"])
在请求中携带cookies
cookies={
"username":"joseph"
}
r1=requests.get(url="http://httpbin.org/cookies",cookies=cookies)
print(r1.cookies) # 输出响应设置的cookies
print(r1.text) # 请求url在响应中返回请求的cookies
证书校验,SSLError问题
request可以为HTTPS请求验证SSL证书,就像web浏览器一样
SSL验证默认是开启的,如果证书验证失败,requests会抛出SSLError
# 关闭SSL校验
r1=requests.get(url="https://www.baina.org",verify=False)
# 方法二:指定网站的SSL证书,但是一般没有
print(r1.text)
异常
- 网络问题:如DNS查询失败,拒绝连接,会抛出ConnectionError异常
- Http请求返回了不成功的状态码:HTTPError异常
- 请求超时:Timeout异常
- 请求次数超过了设定的最大重定向次数,TooManyRedirects异常
- 所有request显式抛出的异常都继承自requests.exceptions.RequestException
【重点】保持登录凭据,requests.session(),爬取需登录的网站+定制请求头
http://account.chinaunix.net/login进行登录验证
1.通过get请求访问登录页面,这个时候还没有填写username和password
2.post请求访问登录
第二个使用的token信息就是第一个请求setCookies设置的
时间戳,删除后3位
3.index页面
cookies携带了很多数据,
可以通过定制请求头和设置请求的cookies 进入index页面,可行但太麻烦。
保持登录凭据,从而直接绕过登录,直接进入到index页面:
- get请求拿token信息
- post请求提交用户名密码
- 第三个请求直接访问登录后index页面
定制请求头header
请求头替换添加引号:
采用正则表达式
代码实现,利用requests.session()保存登录凭据
# request.session,创建一个保持登录凭据的session实例
login_session=requests.session()
# 1、get请求,获取token信息
token_url="http://account.chinaunix.net/login?"
headers={
"Accept":"text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9",
"Accept-Encoding":"gzip, deflate",
"Accept-Language":"zh-CN,zh;q=0.9,en;q=0.8,en-GB;q=0.7,en-US;q=0.6",
"Cache-Control":"no-cache",
"Host":"account.chinaunix.net",
"Pragma":"no-cache",
"Proxy-Connection":"keep-alive",
"Upgrade-Insecure-Requests":"1",
"User-Agent":"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.164 Safari/537.36 Edg/91.0.864.71"
}
# 发送第一个get请求
token_response=login_session.get(url=token_url,headers=headers)
# print(token_response.headers.get("Set-Cookie"))
# 通过正则表达式拿到token值,需要导入import re
token_search=re.compile(r"XSRF-TOKEN=(.*?);")
token_value=token_search.search(token_response.headers.get("Set-Cookie"))
print(token_value.group(1))
# 2.post请求
# 时间戳导入 import time模块生成
login_url="http://account.chinaunix.net/login/login"
data={
"username": "dazhuang_imooc",
"password": "abcd1234",
"_token": "QPABdRUD0iujCY7GCgv4RARvOlUBcQY39e3vSaxu",
"_t": int(time.time())
}
# 发送post请求,提交用户名和密码,注意不要忘记携带data
login_response=login_session.post(url=login_url,headers=headers,data=data)
print(login_response.text)
# 3.访问index页面
index_url="http://account.chinaunix.net/ucenter/user/index"
# 【重要】一定要使用login_session,否则登录凭据是不携带的
index_response=login_session.get(url=index_url)
print(index_response.text)
【重点】设置代理,隐藏请求
服务端可以看到客户端的请求地址,我们可以通过设置代理来隐藏我们自己
快代理:
- 可以提供隧道代理
- 本机连接代理的两种形式:每个请求携带用户名和密码,设置白名单类似ssh
# 查看本机的ip和城市
url="http://pv.sohu.com/cityjson"
response=requests.get(url=url)
print(response.text)
# 1.挑选代理厂商:阿布云,芝麻代理,快代理
# 2.把代理信息设置到代码中,两种格式:http和https
url="http://pv.sohu.com/cityjson"
# 免费代理,无需用户名和密码
proxies1={
"http":"http://117.157.197.18:3128",
"https":"https://117.157.197.18:3128",
}
# 付费代理:格式需要注意,定义一个字典http和https
# 用户名:密码@代理的接口:端口号
proxies={
"http":"http://t10422119804320:oynsb8dh@tps194.kdlapi.com:15818",
"https":"https://t10422119804320:oynsb8dh@tps194.kdlapi.com:15818",
}
# 发送请求携带代理信息
for i in range(5):
response=requests.get(url=url,proxies=proxies)
print(response.text)
四、Xpath基础和lxml模块
XPath知识点
html节点与节点间的关系,Xpath和lxml获取想要的数据字段
节点有哪些?
先辈节点不唯一,后辈节点也不唯一
学习XPath需要安装插件:XPath helper
xpath路径表达式:
汪曾祺《黄油烙饼》
/div
单斜杆定位根节点下div节点
//div
双斜杠定位文档中所有div节点
//div[@class='pic_art']
获取特定元素 网页元素
//div[@class='pic_art']/text()
获取特定元素 整个文本信息
//div[@class='pic_art']/.
一个点表示当前节点
//div[@class='pic_art']/..
两个点表示获取当前节点的父节点
/div/a
从根节点开始选取div节点下的a节点
//div[@class='info']/span[@class='time']
/div/a[2]/img
从根节点开始选取div节点下的第二个a节点下的img节点
//div[@class=‘header-wrapper’]
选取所有属性class的值为header-wrapper的div节点
- 在节点后加上带有数字的方括号,兄弟节点索引
/div/a[2]/img
- 在节点后加上属性名-值对的方括号,可以筛选出需要的节点
//div[@class='info']/span[@class='time']
//*
选取所有元素//@*
选取所有带属性的元素
xpath函数:
div/p/text()
选取文本内容
模糊查询:
//div[contains(@class,”post”)]
选取带有class属性且包含“post”的所有div节点。取反//div[ not(contains(@class,”post”))]
/div/p[last()-1]
选取div下倒数第二个p节点
div/p[position()>1]
选取div下第二个p节点后的所有兄弟节点
/div/a|div/p
选取div下的a节点和div下的p节点,竖线分隔or
Python lxml模块
可以灵活处理xml
支持xpath
利用XPath语法,快速定位特定元素以及节点信息,以提取出html或xml目标数据
安装lxml库:
在cmd中输入pip install lxml
实操:通过xpath获取想要的数据字段
from lxml import etree
# 不包含html标签和body标签
data="""
<div>
<ul>
<li class="item-0"><a href="link1.html">first item</a></li>
<li class="item-1"><a href="link2.html">second item</a></li>
<li class="item-inactive"><a href="link3.html"><span class="bold">third item</span></a></li>
<li class="item-1"><a href="link4.html">fourth item</a></li>
<li class="item-0"><a href="link5.html">fifth item</a></li>
</ul>
</div>
"""
#html实例化,添加了html和body标签
html=etree.HTML(data)
print(etree.tostring(html).decode())
print(html.xpath("//li"))
print(html.xpath("//li/@class"))
print(html.xpath("//li/a[@href='link1.html']"))
print(html.xpath("//li[1]/a[1]"))
print(html.xpath("//li[last()]/a[1]"))
print(html.xpath("//li/a/span"))
print(html.xpath("//li//span"))
# 输出的所有结果都是列表的形式
五、实战:当当网5星图书排行榜数据抓取
目标站点
当当5星图书排行榜
抓取5星好评图书数据:
items=//ul[@class='bang_list clearfix bang_list_mode']/li #所有图书条目,返回列表
for item in items:
item.xpath(".//div[@class='name']/a/text()") #图书的标题
item.xpath(".//div[@class='star']/a/text()") #图书的评论
item.xpath(".//span[@class='tuijian']/text()") #图书的推荐信息
item.xpath(".//div[@class='publisher_info'][1]/a/@title") #图书的作者
item.xpath(".//div[@class='publisher_info'][2]/span/text()") #图书的出版时间
item.xpath(".//div[@class='publisher_info'][2]/a/text()") #出版社信息
item.xpath(".//div[@class='biaosheng']/span/text()") #评分信息
item.xpath(".//div[@class='price']/p[1]/span[1]/text()") #图书价格
item.xpath(".//div[@class='price']/p/span[@class='price_s']/text()") #折扣信息
item.xpath(".//div[@class='price']/p[@class='price_e']/span/text()") #电子书价格
构造请求头headers:浏览器复制请求头,利用notepad++正则表达式格式化,加引号
【易错】需要去除复制的header里面的空格
爬取图书数据,存储为列表形式
import requests
from lxml import etree
class Dangdang(object):
def __init__(self):
"""构造方法"""
self.header={
"Host":"bang.dangdang.com",
"Proxy-Connection":"keep-alive",
"Pragma":"no-cache",
"Cache-Control":"no-cache",
"Upgrade-Insecure-Requests":"1",
"User-Agent":"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.164 Safari/537.36 Edg/91.0.864.71",
"Accept":"text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9",
"Accept-Encoding":"gzip, deflate",
"Accept-Language":"zh-CN,zh;q=0.9,en;q=0.8,en-GB;q=0.7,en-US;q=0.6"
}
def get_dangdang(self,page):
"""发送请求到当当网获取数据"""
url="http://bang.dangdang.com/books/fivestars/01.00.00.00.00.00-recent30-0-0-1-%s" % page
# 发送请求
response=requests.get(url=url,headers=self.header) # 1.response获取一个页面的网页内容
if response:
# 2.HTML数据的实例化。通过xpath表达式抽取网页数据,获取各个图书的网页数据,以列表形式返回
html=etree.HTML(response.text)
items=html.xpath("//ul[@class='bang_list clearfix bang_list_mode']/li")
return items
# xpath获取的数据是一个列表,转换为字符串
def join_list(self,item):
"""处理列表到字符串"""
return "".join(item)
def parse_item(self,items):
"""解析具体的图书条目"""
# 定义一个列表,用于存放存储到MongoDB之前的数据
result_list=[]
# 1.对抽取的每一个图书网页数据,进行进一步数据抽取,获得每本图书的各项具体信息节点
for item in items:
title=item.xpath(".//div[@class='name']/a/text()") #图书的标题
comment=item.xpath(".//div[@class='star']/a/text()") #图书的评论
recommend=item.xpath(".//span[@class='tuijian']/text()") #图书的推荐信息
author=item.xpath(".//div[@class='publisher_info'][1]/a/@title") #图书的作者
publication_time=item.xpath(".//div[@class='publisher_info'][2]/span/text()") #图书的出版时间
press=item.xpath(".//div[@class='publisher_info'][2]/a/text()") #出版社信息
score=item.xpath(".//div[@class='biaosheng']/span/text()") #评分信息
price=item.xpath(".//div[@class='price']/p[1]/span[1]/text()") #图书价格
discount=item.xpath(".//div[@class='price']/p/span[@class='price_s']/text()") #折扣信息
e_book=item.xpath(".//div[@class='price']/p[@class='price_e']/span/text()") #电子书价格
# 2.每本图书的各项具体信息都是以列表存储节点的形式展现,将列表变为字符串。再将每个节点信息封装成一个JSON对象,存储到结果列表result_list中
result_list.append(
{
"title":self.join_list(title),
"comment":self.join_list(comment),
"recommend":self.join_list(recommend),
"author":self.join_list(author),
"publication_time":self.join_list(publication_time),
"press":self.join_list(press),
"score":self.join_list(score),
"price":self.join_list(price),
"discount":self.join_list(discount),
"e_book":self.join_list(e_book)
}
)
return result_list
def main():
import json
d=Dangdang()
for page in range(1,26):
items=d.get_dangdang(page=page)
result=d.parse_item(items=items)
print(json.dumps(result)) #复制一条,浏览器打开json.cn可以看到json形式
if __name__ == '__main__':
main()
python操作MongoDB
安装pymongo:
pip install pymongo
python中连接mongodb数据库+插入数据
import pymongo
# 指定一个客户端连接Mongodb
pymongo_client=pymongo.MongoClient("mongodb://127.0.0.1:27017")
# 指定数据库的名称imooc
# 只有库里面由内容插入的时候,才会创建数据库
pymongbo_db=pymongo_client["imooc"]
# 创建集合(数据库表)
pymongo_collection=pymongbo_db["pymongo_test"]
data={
"name":"imooc",
"flag":1,
"url":"https://www.baidu.com"
}
# 插入一条数据
pymongo_collection.insert_one(data)
# 插入多条数据,列表
mylist=[
{"name":"taobao","flag":"100","url":"https://www.taobao.com"},
{"name":"QQ","flag":"101","url":"https://www.qq.com"},
{"name":"facebook","flag":"102","url":"https://www.facebook.com"},
{"name":"zhihu","flag":"103","url":"https://www.zhihu.com"},
{"name":"github","flag":"104","url":"https://www.github.com"},
]
pymongo_collection.insert_many(mylist)
数据查询:
# 查询
# 第一个{}表示进行数据的查询,第二个{}进行过滤,find是查询所有数据
result=pymongo_collection.find({},{"_id":0,"name":1,"flag":1}) #结果是一个游标<pymongo.cursor.Cursor object at 0x00000201BE84EEB0>,可以通过for循环进行遍历
for item in result:
print(item)
# 查询一条数据
result2=pymongo_collection.find_one()
print(result2)
# 高级查询
# result3=pymongo_collection.find({"flag":{"$gt":"100"}}) # 查询结果flag都大于100,大小输出
result3=pymongo_collection.find({"name":{"$regex":"^g"}}) # 正则表达式,限定输出
for item in result3:
print(item)
数据更新:
# 数据更新
# 更新一条(第一个参数是查询条件,第二个参数是要修改成为什么样子)
pymongo_collection.update_one({"name":{"$regex":"^g"}},{"$set":{"name":"gitee"}})
result=pymongo_collection.find({},{"_id":0,"name":1,"flag":1})
for item in result:
print(item)
# 更新多条
pymongo_collection.update_many({},{"$set":{"name":"gitee"}})
result=pymongo_collection.find({},{"_id":0,"name":1,"flag":1})
for item in result:
print(item)
数据删除:
# 数据删除
# 删除一条
pymongo_collection.delete_one({"url":"https://www.baidu.com"})
# 删除所有数据
pymongo_collection.delete_many({})
将爬取的当当网图书数据存储到mongdb中
from typing import Collection
from pymongo import collection, mongo_client
import requests
from lxml import etree
import pymongo
from pymongo.collection import Collection # Collection不要写错
class Dangdang(object):
# ******************************************************************************************
# 连接数据库
mongo_client=pymongo.MongoClient(host="127.0.0.1",port=27017)
# 指定数据库为dangdang_db
dangdang_db=mongo_client["dangdang_db"]
# ******************************************************************************************
def __init__(self):
self.header={
"Host":"bang.dangdang.com",
"Proxy-Connection":"keep-alive",
"Pragma":"no-cache",
"Cache-Control":"no-cache",
"Upgrade-Insecure-Requests":"1",
"User-Agent":"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.164 Safari/537.36 Edg/91.0.864.71",
"Accept":"text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9",
"Accept-Encoding":"gzip, deflate",
"Accept-Language":"zh-CN,zh;q=0.9,en;q=0.8,en-GB;q=0.7,en-US;q=0.6"
}
# ******************************************************************************************
# 构造方法创建Collection
self.dangdang=Collection(Dangdang.dangdang_db,"dangdang") # 表名为dangdang
# ******************************************************************************************
def get_dangdang(self,page):
"""发送请求到当当网获取数据"""
url="http://bang.dangdang.com/books/fivestars/01.00.00.00.00.00-recent30-0-0-1-%s" % page
print(url)
# 发送请求
response=requests.get(url=url,headers=self.header)
if response:
# HTML数据的实例化
html=etree.HTML(response.text)
items=html.xpath("//ul[@class='bang_list clearfix bang_list_mode']/li")
return items
# xpath获取的数据是一个列表,转换为字符串
def join_list(self,item):
"""处理列表到字符串"""
return "".join(item)
def parse_item(self,items):
"""解析具体的图书条目"""
# 定义一个列表,用于存放存储到MongoDB之前的数据的
result_list=[]
for item in items: # 一个items包括25条数目,即最终一个result_list包含25条数据每次
title=item.xpath(".//div[@class='name']/a/text()") #图书的标题
comment=item.xpath(".//div[@class='star']/a/text()") #图书的评论
recommend=item.xpath(".//span[@class='tuijian']/text()") #图书的推荐信息
author=item.xpath(".//div[@class='publisher_info'][1]/a/@title") #图书的作者
publication_time=item.xpath(".//div[@class='publisher_info'][2]/span/text()") #图书的出版时间
press=item.xpath(".//div[@class='publisher_info'][2]/a/text()") #出版社信息
score=item.xpath(".//div[@class='biaosheng']/span/text()") #评分信息
price=item.xpath(".//div[@class='price']/p[1]/span[1]/text()") #图书价格
discount=item.xpath(".//div[@class='price']/p/span[@class='price_s']/text()") #折扣信息
e_book=item.xpath(".//div[@class='price']/p[@class='price_e']/span/text()") #电子书价格
result_list.append(
{
"title":self.join_list(title),
"comment":self.join_list(comment),
"recommend":self.join_list(recommend),
"author":self.join_list(author),
"publication_time":self.join_list(publication_time),
"press":self.join_list(press),
"score":self.join_list(score),
"price":self.join_list(price),
"discount":self.join_list(discount),
"e_book":self.join_list(e_book)
}
)
return result_list
# ******************************************************************************************
def insert_data(self,result_list):
"""插入数据到mongodb"""
self.dangdang.insert_many(result_list) #一次20条数目
# ******************************************************************************************
def main():
import json
d=Dangdang()
for page in range(1,26):
items=d.get_dangdang(page=page)
result=d.parse_item(items=items)
# print(len(result)) # 浏览器每个页面输出记录条数
# print(json.dumps(result)) #复制一条,浏览器打开json.cn可以看到json形式
d.insert_data(result_list=result)
if __name__ == '__main__':
main()
爬虫的伪装:使用代理
from typing import Collection
from pymongo import collection, mongo_client
import requests
from lxml import etree
import pymongo
from pymongo.collection import Collection
class Dangdang(object):
# 连接数据库
mongo_client=pymongo.MongoClient(host="127.0.0.1",port=27017)
# 指定数据库为dangdang_db
dangdang_db=mongo_client["dangdang_db"]
def __init__(self):
self.header={
"Host":"bang.dangdang.com",
"Proxy-Connection":"keep-alive",
"Pragma":"no-cache",
"Cache-Control":"no-cache",
"Upgrade-Insecure-Requests":"1",
"User-Agent":"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.164 Safari/537.36 Edg/91.0.864.71",
"Accept":"text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9",
"Accept-Encoding":"gzip, deflate",
"Accept-Language":"zh-CN,zh;q=0.9,en;q=0.8,en-GB;q=0.7,en-US;q=0.6"
}
# 构造方法创建Collection
self.dangdang=Collection(Dangdang.dangdang_db,"dangdang") # 表名为dangdang
# ******************************************************************************************
#使用代理,在request方法中加上代理信息
self.proxies={
"http":"http://t10422119804320:oynsb8dh@tps194.kdlapi.com:15818",
"https":"https://t10422119804320:oynsb8dh@tps194.kdlapi.com:15818",
}
# ******************************************************************************************
def get_dangdang(self,page):
"""发送请求到当当网获取数据"""
url="http://bang.dangdang.com/books/fivestars/01.00.00.00.00.00-recent30-0-0-1-%s" % page
print(url)
# ******************************************************************************************
# 发送请求,此时爬虫项目使用了代理,进行爬取数据的
response=requests.get(url=url,headers=self.header,proxies=self.proxies)
# ******************************************************************************************
if response:
# HTML数据的实例化
html=etree.HTML(response.text)
items=html.xpath("//ul[@class='bang_list clearfix bang_list_mode']/li")
return items
# xpath获取的数据是一个列表,转换为字符串
def join_list(self,item):
"""处理列表到字符串"""
return "".join(item)
def parse_item(self,items):
"""解析具体的图书条目"""
# 定义一个列表,用于存放存储到MongoDB之前的数据的
result_list=[]
for item in items: # 一个items包括25条数目,即最终一个result_list包含25条数据每次
title=item.xpath(".//div[@class='name']/a/text()") #图书的标题
comment=item.xpath(".//div[@class='star']/a/text()") #图书的评论
recommend=item.xpath(".//span[@class='tuijian']/text()") #图书的推荐信息
author=item.xpath(".//div[@class='publisher_info'][1]/a/@title") #图书的作者
publication_time=item.xpath(".//div[@class='publisher_info'][2]/span/text()") #图书的出版时间
press=item.xpath(".//div[@class='publisher_info'][2]/a/text()") #出版社信息
score=item.xpath(".//div[@class='biaosheng']/span/text()") #评分信息
price=item.xpath(".//div[@class='price']/p[1]/span[1]/text()") #图书价格
discount=item.xpath(".//div[@class='price']/p/span[@class='price_s']/text()") #折扣信息
e_book=item.xpath(".//div[@class='price']/p[@class='price_e']/span/text()") #电子书价格
result_list.append(
{
"title":self.join_list(title),
"comment":self.join_list(comment),
"recommend":self.join_list(recommend),
"author":self.join_list(author),
"publication_time":self.join_list(publication_time),
"press":self.join_list(press),
"score":self.join_list(score),
"price":self.join_list(price),
"discount":self.join_list(discount),
"e_book":self.join_list(e_book)
}
)
return result_list
def insert_data(self,result_list):
"""插入数据到mongodb"""
self.dangdang.insert_many(result_list) #一次25条数目
def main():
import json
d=Dangdang()
for page in range(1,26):
items=d.get_dangdang(page=page)
result=d.parse_item(items=items)
# print(len(result)) # 浏览器每个页面输出记录条数
# print(json.dumps(result)) #复制一条,浏览器打开json.cn可以看到json形式
d.insert_data(result_list=result)
if __name__ == '__main__':
main()
使用了代理以后,抓取的数据会变慢很多
小结
- 开发环境的配置
- 了解了关系型数据库和非关系型数据库
- 安装了MongoDB
- 安装使用navicat可视化工具,连接了MongoDB数据库
- 爬虫基础
- 学习了http和https相关知识
- 浏览器中观察到了http请求头,以及返回数据,状态码,get请求,post请求
- request模块——获取网页内容,通过request模块可以请求到网页数据了
- requests基础模块学习了发送get请求、post请求
- requests进阶模块中,学习了如何定制请求头、如何获取获取cookie值,如何加载证书,如何保存登录凭据、如何携带代理
- XPath语句和lxml模块——抽取网页数据,实例化html数据,通过xpath语句获取想要的网页数据
- 通过XPath语句,在浏览器中使用
xpath helper
工具来获取网页数据 - 通过lxml模块,去实例化html数据,并且通过xpath语句,在代码中或许想要的网页数据
- 爬虫实战——当当网5星排行榜图书数据爬取+将数据保存到mongodb数据库中
- python操作mongodb数据库
- 项目实战爬取