spider-02
' href_list = self.re_func(one_regex,one_html) for href in href_list: # 加密指纹 s = md5() s.update(href.encode()) finger = s.hexdigest() # 如果指纹表中不存在 if self.r.sadd('car:urls',finger): # 每便利一个汽车信息,必须要把此辆汽车所有数据提取完成后再提取下一辆汽车信息 url = 'https://www.che168.com' + href # 获取一辆汽车的信息 self.get_data(url) time.sleep(random.randint(1,2)) else: sys.exit('抓取结束') # 获取一辆汽车信息 def get_data(self,url): two_html = self.get_html(url) two_regex = '
发布日期:2021-06-29 12:07:03
浏览次数:4
分类:技术文章
本文共 15867 字,大约阅读时间需要 52 分钟。
文章目录
spider-day02笔记
数据持久化 - MySQL
-
pymysql回顾
import pymysqldb = pymysql.connect('localhost','root','123456','maoyandb',charset='utf8')cursor = db.cursor()ins = 'insert into filmtab values(%s,%s,%s)'cursor.execute(ins,['霸王别姬','张国荣','1993'])db.commit()cursor.close()db.close()
数据持久化 - MongoDB
-
MongoDB特点
【1】非关系型数据库,数据以键值对方式存储,端口27017【2】MongoDB基于磁盘存储【3】MongoDB数据类型单一,值为JSON文档,而Redis基于内存, 3.1> MySQL数据类型:数值类型、字符类型、日期时间类型、枚举类型 3.2> Redis数据类型:字符串、列表、哈希、集合、有序集合 3.3> MongoDB数据类型:值为JSON文档【4】MongoDB: 库 -> 集合 -> 文档 MySQL : 库 -> 表 -> 表记录
-
MongoDB常用命令
Linux进入: mongo>show dbs - 查看所有库>use 库名 - 切换库>show collections - 查看当前库中所有集合>db.集合名.find().pretty() - 查看集合中文档>db.集合名.count() - 统计文档条数>db.集合名.drop() - 删除集合>db.dropDatabase() - 删除当前库
-
pymongo模块使用
import pymongo# 1.连接对象conn = pymongo.MongoClient(host = 'localhost',port = 27017)# 2.库对象db = conn['maoyandb']# 3.集合对象myset = db['maoyanset']# 4.插入数据库myset.insert_one({ 'name':'赵敏'})
-
练习 - 将电影信息存入MongoDB数据库
"""猫眼电影top100抓取(电影名称、主演、上映时间)存入mongodb数据库中"""import requestsimport reimport timeimport randomimport pymongoclass MaoyanSpider: def __init__(self): self.url = 'https://maoyan.com/board/4?offset={}' self.headers = { 'User-Agent':'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/81.0.4044.113 Safari/537.36'} # 三个对象:连接对象、库对象、集合对象 self.conn = pymongo.MongoClient('127.0.0.1', 27017) self.db = self.conn['maoyandb'] self.myset = self.db['maoyanset2'] def get_html(self, url): html = requests.get(url=url, headers=self.headers).text # 直接调用解析函数 self.parse_html(html) def parse_html(self, html): """解析提取数据""" regex = '
.*?title="(.*?)".*?(.*?)
.*?(.*?)
' pattern = re.compile(regex, re.S) r_list = pattern.findall(html) # r_list: [('活着','牛犇','2000-01-01'),(),(),...,()] self.save_html(r_list) def save_html(self, r_list): """数据处理函数""" for r in r_list: item = { } item['name'] = r[0].strip() item['star'] = r[1].strip() item['time'] = r[2].strip() print(item) # 存入到mongodb数据库 self.myset.insert_one(item) def run(self): """程序入口函数""" for offset in range(0, 91, 10): url = self.url.format(offset) self.get_html(url=url) # 控制数据抓取频率:uniform()生成指定范围内的浮点数 time.sleep(random.uniform(0,1))if __name__ == '__main__': spider = MaoyanSpider() spider.run()
数据持久化 - csv
-
csv描述
【1】作用 将爬取的数据存放到本地的csv文件中【2】使用流程 2.1> 打开csv文件 2.2> 初始化写入对象 2.3> 写入数据(参数为列表) 【3】示例代码 import csv with open('sky.csv','w') as f: writer = csv.writer(f) writer.writerow([])
-
示例
【1】题目描述 创建 test.csv 文件,在文件中写入数据【2】数据写入 - writerow([])方法 import csv with open('test.csv','w') as f: # with open('test.csv','w',newline='') as f:----->windows里面的写法,因为再wiondows中每条数据会有一个空行 writer = csv.writer(f) writer.writerow(['超哥哥','25'])
-
练习 - 使用 writerow() 方法将猫眼电影数据存入本地 maoyan.csv 文件
【1】在 __init__() 中打开csv文件,因为csv文件只需要打开和关闭1次即可【2】在 save_html() 中将所抓取的数据处理成列表,使用writerow()方法写入【3】在run() 中等数据抓取完成后关闭文件
-
代码实现
"""猫眼电影top100抓取(电影名称、主演、上映时间)存入csv文件,使用writerow()方法"""import requestsimport reimport timeimport randomimport csvclass MaoyanSpider: def __init__(self): self.url = 'https://maoyan.com/board/4?offset={}' self.headers = { 'User-Agent':'Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Win64; x64; Trident/5.0; .NET CLR 2.0.50727; SLCC2; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; InfoPath.3; .NET4.0C; Tablet PC 2.0; .NET4.0E)'} # 打开文件,初始化写入对象 self.f = open('maoyan.csv', 'w', newline='', encoding='utf-8') self.writer = csv.writer(self.f) def get_html(self, url): html = requests.get(url=url, headers=self.headers).text # 直接调用解析函数 self.parse_html(html) def parse_html(self, html): """解析提取数据""" regex = '
.*?title="(.*?)".*?(.*?)
.*?(.*?)
' pattern = re.compile(regex, re.S) r_list = pattern.findall(html) # r_list: [('活着','牛犇','2000-01-01'),(),(),...,()] self.save_html(r_list) def save_html(self, r_list): """数据处理函数""" for r in r_list: li = [ r[0].strip(), r[1].strip(), r[2].strip() ] self.writer.writerow(li) print(li) def run(self): """程序入口函数""" for offset in range(0, 91, 10): url = self.url.format(offset) self.get_html(url=url) # 控制数据抓取频率:uniform()生成指定范围内的浮点数 time.sleep(random.uniform(1,2)) # 所有数据抓取并写入完成后关闭文件 self.f.close()if __name__ == '__main__': spider = MaoyanSpider() spider.run()
useragent 池
sudo pip3 install fake_useragent # 爬虫生成useragent的插件,大概有250个UserAgentfrom fake_useragent import UserAgenthearders = { 'User-Agent': UserAgent().random}
汽车之家数据抓取 - 二级页面
-
领取任务
【1】爬取地址 汽车之家 - 二手车 - 价格从低到高 https://www.che168.com/beijing/a0_0msdgscncgpi1lto1csp1exx0/ 【2】爬取目标 所有汽车的 型号、行驶里程、上牌时间、档位、排量、车辆所在地、价格【3】爬取分析 *********一级页面需抓取*********** 1、车辆详情页的链接 *********二级页面需抓取*********** 1、名称 2、行驶里程 3、上牌时间 4、档位 5、排量 6、车辆所在地 7、价格
-
实现步骤
【1】确定响应内容中是否存在所需抓取数据 - 存在【2】找URL地址规律 第1页: https://www.che168.com/beijing/a0_0msdgscncgpi1lto1csp1exx0/ 第2页: https://www.che168.com/beijing/a0_0msdgscncgpi1lto1csp2exx0/ 第n页: https://www.che168.com/beijing/a0_0msdgscncgpi1lto1csp{ }exx0/ 【3】 写正则表达式 一级页面正则表达式:
- 二级页面正则表达式: .*?
(.*?)
.*?- .*?
- .*?
(.*?)
.*?(.*?)
.*?(.*?)
.*?(.*?)
.*?¥(.*?)【4】代码实现
- .*?
-
代码实现
"""汽车之家二手车信息抓取思路 1、一级页面:汽车的链接 2、二级页面:具体汽车信息建立User-Agent池:防止被网站检测到是爬虫 使用fake_useragent模块 安装:sudo pip3 install fake_useragent 使用: from fake_useragent import UserAgent UserAgent().random"""import requestsimport reimport timeimport randomfrom fake_useragent import UserAgentclass CarSpider: def __init__(self): self.url = 'https://www.che168.com/beijing/a0_0msdgscncgpi1lto1csp{}exx0/' def get_html(self, url): """功能函数1 - 获取html""" headers = { 'User-Agent':UserAgent().random } html = requests.get(url=url, headers=headers).text return html def re_func(self, regex, html): """功能函数2 - 正则解析函数""" pattern = re.compile(regex, re.S) r_list = pattern.findall(html) return r_list def parse_html(self, one_url): """爬虫逻辑函数""" one_html = self.get_html(url=one_url) one_regex = '
- ' href_list = self.re_func(regex=one_regex, html=one_html) for href in href_list: two_url = 'https://www.che168.com' + href # 获取1辆汽车的具体信息 self.get_car_info(two_url) # 控制爬取频率 time.sleep(random.randint(1,2)) def get_car_info(self, two_url): """获取1辆汽车的具体信息""" two_html = self.get_html(url=two_url) two_regex = ' .*?
(.*?)
.*?(.*?)
.*?(.*?)
.*?(.*?)
.*?(.*?)
.*? ¥(.*?)' # car_list: [('福睿斯','3万公里','2016年3月','手动 / 1.5L', '廊坊', '5.60'),] car_list = self.re_func(regex=two_regex, html=two_html) item = { } item['name'] = car_list[0][0].strip() item['km'] = car_list[0][1].strip() item['time'] = car_list[0][2].strip() item['type'] = car_list[0][3].split('/')[0].strip() item['displace'] = car_list[0][3].split('/')[1].strip() item['address'] = car_list[0][4].strip() item['price'] = car_list[0][5].strip() print(item) def run(self): for i in range(1,5): url = self.url.format(i) self.parse_html(url)if __name__ == '__main__': spider = CarSpider() spider.run() -
练习 - 将数据存入MySQL数据库
create database cardb charset utf8;use cardb;create table cartab(name varchar(100),km varchar(50),years varchar(50),type varchar(50),displacement varchar(50),city varchar(50),price varchar(50))charset=utf8;
使用redis实现增量爬虫
"""提示: 使用redis中的集合,sadd()方法,添加成功返回1,否则返回0请各位大佬忽略掉下面代码,自己独立实现"""import requestsimport reimport timeimport randomimport pymysqlfrom hashlib import md5import sysimport redisclass CarSpider(object): def __init__(self): self.url = 'https://www.che168.com/beijing/a0_0msdgscncgpi1lto1csp{}exx0/' self.headers = { 'User-Agent':'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/535.1 (KHTML, like Gecko) Chrome/14.0.835.163 Safari/535.1'} self.db = pymysql.connect('localhost','root','123456','cardb',charset='utf8') self.cursor = self.db.cursor() # 连接redis去重 self.r = redis.Redis(host='localhost',port=6379,db=0) # 功能函数1 - 获取响应内容 def get_html(self,url): html = requests.get(url=url,headers=self.headers).text return html # 功能函数2 - 正则解析 def re_func(self,regex,html): pattern = re.compile(regex,re.S) r_list = pattern.findall(html) return r_list # 爬虫函数开始 def parse_html(self,one_url): one_html = self.get_html(one_url) one_regex = '
.*?
(.*?)
.*?- .*?
- .*?
(.*?)
.*?(.*?)
.*?(.*?)
.*?(.*?)
.*?¥(.*?)
xpath解析
-
定义
XPath即为XML路径语言,它是一种用来确定XML文档中某部分位置的语言,同样适用于HTML文档的检索
-
匹配演示 - 猫眼电影top100
【1】查找所有的dd节点 //dd【2】获取所有电影的名称的a节点: 所有class属性值为name的a节点 //p[@class="name"]/a【3】获取dl节点下第2个dd节点的电影节点 //dl[@class="board-wrapper"]/dd[2] 【4】获取所有电影详情页链接: 获取每个电影的a节点的href的属性值 //p[@class="name"]/a/@href【注意】 1> 只要涉及到条件,加 [] : //dl[@class="xxx"] //dl/dd[2] 2> 只要获取属性值,加 @ : //dl[@class="xxx"] //p/a/@href
-
选取节点
【1】// : 从所有节点中查找(包括子节点和后代节点)【2】@ : 获取属性值 2.1> 使用场景1(属性值作为条件) //div[@class="movie-item-info"] 2.2> 使用场景2(直接获取属性值) //div[@class="movie-item-info"]/a/img/@src 【3】练习 - 猫眼电影top100 3.1> 匹配电影名称 //div[@class="movie-item-info"]/p[1]/a/@title 3.2> 匹配电影主演 //div[@class="movie-item-info"]/p[2]/text() 3.3> 匹配上映时间 //div[@class="movie-item-info"]/p[3]/text() 3.4> 匹配电影链接 //div[@class="movie-item-info"]/p[1]/a/@href
-
匹配多路径(或)
xpath表达式1 | xpath表达式2 | xpath表达式3
-
常用函数
【1】text() :获取节点的文本内容 xpath表达式末尾不加 /text() :则得到的结果为节点对象 xpath表达式末尾加 /text() 或者 /@href : 则得到结果为字符串 【2】contains() : 匹配属性值中包含某些字符串节点 匹配class属性值中包含 'movie-item' 这个字符串的 div 节点 //div[contains(@class,"movie-item")]
-
终极总结
【1】字符串: xpath表达式的末尾为: /text() 、/@href 得到的列表中为'字符串' 【2】节点对象: 其他剩余所有情况得到的列表中均为'节点对象' [
, , ] [ , ] [ , , ] -
课堂练习
【1】匹配汽车之家-二手车,所有汽车的链接 : //li[@class="cards-li list-photo-li"]/a[1]/@href //a[@class="carinfo"]/@href【2】匹配汽车之家-汽车详情页中,汽车的 2.1)名称: //div[@class="car-box"]/h3/text() 2.2)里程: //ul/li[1]/h4/text() 2.3)时间: //ul/li[2]/h4/text() 2.4)挡位+排量: //ul/li[3]/h4/text() 2.5)所在地: //ul/li[4]/h4/text() 2.6)价格: //div[@class="brand-price-item"]/span[@class="price"]/text()
lxml解析库
-
安装
【1】Ubuntu: sudo pip3 install lxml【2】Windows: python -m pip install lxml
-
使用流程
1、导模块 from lxml import etree2、创建解析对象 parse_html = etree.HTML(html)3、解析对象调用xpath r_list = parse_html.xpath('xpath表达式')
-
xpath最常用
【1】基准xpath: 匹配所有电影信息的节点对象列表 //dl[@class="board-wrapper"]/dd [
, ,...] 【2】遍历对象列表,依次获取每个电影信息 item = { } for dd in dd_list: item['name'] = dd.xpath('.//p[@class="name"]/a/text()').strip() item['star'] = dd.xpath('.//p[@class="star"]/text()').strip() item['time'] = dd.xpath('.//p[@class="releasetime"]/text()').strip() -
猫眼电影案例-xpath实现
"""猫眼电影top100抓取(电影名称、主演、上映时间)"""import requestsimport timeimport randomfrom lxml import etreeclass MaoyanSpider: def __init__(self): self.url = 'https://maoyan.com/board/4?offset={}' self.headers = { 'User-Agent':'Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Win64; x64; Trident/5.0; .NET CLR 2.0.50727; SLCC2; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; InfoPath.3; .NET4.0C; Tablet PC 2.0; .NET4.0E)'} def get_html(self, url): html = requests.get(url=url, headers=self.headers).text # 直接调用解析函数 self.parse_html(html) def parse_html(self, html): """解析提取数据 - xpath""" p = etree.HTML(html) # 基准xpath:每个电影信息的节点对象dd列表 [
, ,...] dd_list = p.xpath('//dl[@class="board-wrapper"]/dd') print(dd_list) item = { } for dd in dd_list: item['name'] = dd.xpath('.//p[@class="name"]/a/@title')[0].strip() item['star'] = dd.xpath('.//p[@class="star"]/text()')[0].strip() item['time'] = dd.xpath('.//p[@class="releasetime"]/text()')[0].strip() print(item) def run(self): """程序入口函数""" for offset in range(0, 91, 10): url = self.url.format(offset) self.get_html(url=url) # 控制数据抓取频率:uniform()生成指定范围内的浮点数 time.sleep(random.uniform(0,1))if __name__ == '__main__': spider = MaoyanSpider() spider.run() -
小作业
汽车之家案例使用lxml+xpath实现
Day02回顾
数据抓取
-
思路步骤
【1】先确定是否为动态加载网站【2】找URL规律【3】正则表达式 | xpath表达式【4】定义程序框架,补全并测试代码
-
多级页面数据抓取思路
【1】整体思路 1.1> 爬取一级页面,提取 所需数据+链接,继续跟进 1.2> 爬取二级页面,提取 所需数据+链接,继续跟进 1.3> ... ... 【2】代码实现思路 2.1> 避免重复代码 - 请求、解析需定义函数
-
增量爬虫实现思路
【1】原理 利用Redis集合特性,可将抓取过的指纹添加到redis集合中,根据返回值来判定是否需要抓取 返回值为1 : 代表之前未抓取过,需要进行抓取 返回值为0 : 代表已经抓取过,无须再次抓取 【2】代码实现模板import redisfrom hashlib import md5import sysclass XxxIncrSpider: def __init__(self): self.r = redis.Redis(host='localhost',port=6379,db=0) def url_md5(self,url): """对URL进行md5加密函数""" s = md5() s.update(url.encode()) return s.hexdigest() def run_spider(self): href_list = ['url1','url2','url3','url4'] for href in href_list: href_md5 = self.url_md5(href) if self.r.sadd('spider:urls',href_md5) == 1: 返回值为1表示添加成功,即之前未抓取过,则开始抓取 else: sys.exit()
-
目前反爬处理
【1】基于User-Agent反爬 1.1) 发送请求携带请求头: headers={ 'User-Agent' : 'Mozilla/5.0 xxxxxx'} 1.2) 多个请求时随机切换User-Agent a) 定义py文件存放大量User-Agent,导入后使用random.choice()每次随机选择 b) 使用fake_useragent模块每次访问随机生成User-Agent from fake_useragent import UserAgent agent = UserAgent().random 【2】响应内容存在特殊字符 解码时使用ignore参数 html = requests.get(url=url, headers=headers).content.decode('', 'ignore')
数据持久化
-
csv
import csv with open('xxx.csv','w',encoding='utf-8',newline='') as f: writer = csv.writer(f) writer.writerow([])
-
MySQL
import pymysql# __init__(self): self.db = pymysql.connect('IP',... ...) self.cursor = self.db.cursor() # save_html(self,r_list): self.cursor.execute('sql',[data1]) self.db.commit() # run(self): self.cursor.close() self.db.close()
-
MongoDB
import pymongo# __init__(self): self.conn = pymongo.MongoClient('IP',27017) self.db = self.conn['cardb'] self.myset = self.db['car_set'] # save_html(self,r_list): self.myset.insert_one(dict)# MongoDB - Commmand - 库->集合->文档mongo>show dbs>use db_name>show collections>db.集合名.find().pretty()>db.集合名.count()>db.集合名.drop()>db.dropDatabase()
xpath表达式
-
匹配规则
【1】结果: 节点对象列表 1.1) xpath示例: //div、//div[@class="student"]、//div/a[@title="stu"]/span【2】结果: 字符串列表 2.1) xpath表达式中末尾为: @src、@href、/text()
转载地址:https://blog.csdn.net/z_202041/article/details/117944849 如侵犯您的版权,请留言回复原文章的地址,我们会给您删除此文章,给您带来不便请您谅解!
发表评论
最新留言
路过按个爪印,很不错,赞一个!
[***.219.124.196]2024年04月26日 03时12分13秒
关于作者
喝酒易醉,品茶养心,人生如梦,品茶悟道,何以解忧?唯有杜康!
-- 愿君每日到此一游!
推荐文章
树莓派WIFI设置
2019-04-29
nanopi2 启动信息
2019-04-29
phpstudy https
2019-04-29
Linux下EasyPanel版本安装及升级
2019-04-29
raspberry pi(树莓派) + easycap d60 视频采集
2019-04-29
WebRTC
2019-04-29
rfc5766-turn-server NAT
2019-04-29
webrtc详细教程
2019-04-29
Android IOS WebRTC 音视频开发总结
2019-04-29
报表图表样式
2019-04-29
android模板图例
2019-04-29
树莓派网线直连
2019-04-29
复合材料培训(I第七期)
2019-04-29
复合材料生活中的应用
2019-04-29
ABAQUS复合材料(适合小白)
2019-04-29
ABAQUS高级案例解析
2019-04-29
人工智能药物研发
2019-04-29
【超级干货+福利】AIDD最全面的学习教程
2019-04-29
最新通知:AIDD与网络药理学资料大全
2019-04-29