一、CSV模块
1.作用
将爬取的数据存到本地的CSV文件中
2.使用流程
1.导入模块
2.打开csv文件
3.初始化写入对象
4.写入数据(参数为列表)
import csv with open('test.csv','w') as f: writer=csv.writer(f) #写一行 writer.writerow(['小明',25]) #写多行 writer.writerow([(),(),(),()])
windows中使用csv模块默认添加一个空行,使用newline=''可解决这个问题
3.示例代码
创建test.csv文件,在文件中写入2条数据(01_csv_example.py)
import csv
with open('test.csv','w',newline='') as f:
# 初始化写入对象
writer=csv.writer(f)
writer.writerow(['易烊千玺',20])
writer.writerow(['步惊云',22])
#追加数据
with open('test.csv','a',newline='') as f:
writer=csv.writer(f)
data_list=[('聂风',23),('秦霜',30)]
writer.writerows(data_list)
二、猫眼电影top100抓取案例
1.确定url网址
2.目标
电影名称、主演、上映时间
3.操作步骤
(1)查看是否为动态加载
右键 ——查看网页源代码——搜索爬取关键字(查看在源代码中是否存在)
(2)找url规律
第1页:https://www.maoyan.com/board/4?offset=0
第2页:https://www.maoyan.com/board/4?offset=10
第n页:offset=(n-1)*10
(3)正则表达式
源代码:
<div class="board-item-main">
<div class="board-item-content">
<div class="movie-item-info">
<p class="name"><a href="/films/78341" title="星际穿越" data-act="boarditem-click" data-val="{movieId:78341}">星际穿越</a></p>
<p class="star">
主演:马修·麦康纳,安妮•海瑟薇,杰西卡·查斯坦
</p>
<p class="releasetime">上映时间:2014-11-12</p> </div>
正则表达式
<div class="movie-item-info">.*?title="(.*?)".*?class="star">(.*?)</p>.*?releasetime">(.*?)</p>
猫眼之前的版本,不需要滑块验证
import random
import urllib
from urllib import request
import time
import re
import csv
class MaoyanSpider(object):
def __init__(self):
self.url='https://maoyan.com/board/4?offset={}'
self.user_agent_list=[
'Mozilla/5.0 (Windows NT 6.1; WOW64; rv:34.0) Gecko/20100101 Firefox/34.0 ',
'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/30.0.1599.101 Safari/537.36 ',
'Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; QQDownload 732; .NET4.0C; .NET4.0E)',
'Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; en) Opera 9.50']
#获取数据
def get_page(self,url):
# 每次使用随机的user - agent
headers = {'User-Agent':random.choice(self.user_agent_list)}
request=urllib.request.Request(
url=url,
headers=headers
)
response=urllib.request.urlopen(request)
html=response.read().decode('utf-8')
#调用解析函数
self.parse_page(html)
#解析数据
def parse_page(self,html):
pattern=re.compile('<div class="movie-item-info">.*?title="(.*?)".*?class="star">(.*?)</p>.*?releasetime">(.*?)</p>',re.S)
r_list=pattern.findall(html)
self.write_page(r_list)
#保存数据
def write_page(self,r_list):
one_film_dict={}
for rt in r_list:
one_film_dict['name']=rt[0].strip()
one_film_dict['star']=rt[1].strip()
one_film_dict['time']=rt[2].strip()
print(one_film_dict)
#主函数
def main(self):
for offset in range(0,91,10):
url=self.url.format(offset)
self.get_page(url)
time.sleep(random.randint(1,3))
if __name__=='__main__':
start=time.time()
spider=MaoyanSpider()
spider.main()
end=time.time()
print('执行时间:%.2f' % (end-start))
结果展示
现在的版本,需要验证
# encoding=utf-8
import random
import urllib
from urllib import request
import time
import re
import csv
import requests
class MaoyanSpider(object):
def __init__(self):
self.url = 'https://maoyan.com/board/4?offset={}'
self.user_agent_list = [
'Mozilla/5.0 (Windows NT 6.1; WOW64; rv:34.0) Gecko/20100101 Firefox/34.0 ',
'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/30.0.1599.101 Safari/537.36 ',
'Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; QQDownload 732; .NET4.0C; .NET4.0E)',
'Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; en) Opera 9.50'
]
# 获取数据
def get_page(self, url):
# 每次使用随机的user - agent
headers = {
'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9',
'Accept-Language': 'zh-CN,zh;q=0.9',
'Connection': 'keep-alive',
# 'Referer': 'https://www.maoyan.com/',
'Sec-Fetch-Dest': 'document',
'Sec-Fetch-Mode': 'navigate',
'Sec-Fetch-Site': 'same-origin',
'Sec-Fetch-User': '?1',
'Upgrade-Insecure-Requests': '1',
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.67 Safari/537.36',
'sec-ch-ua': '" Not A;Brand";v="99", "Chromium";v="101", "Google Chrome";v="101"',
'sec-ch-ua-mobile': '?0',
'sec-ch-ua-platform': '"Windows"',
}
response = requests.get(url=url, headers=headers)
# 调用解析函数
self.parse_page(response.text)
# 解析数据
def parse_page(self, html):
pattern = re.compile(
'<div class="movie-item-info">.*?title="(.*?)".*?class="star">(.*?)</p>.*?releasetime">(.*?)</p>', re.S)
r_list = pattern.findall(html)
self.write_page(r_list)
# 保存数据
def write_page(self, r_list):
one_film_dict = {}
for rt in r_list:
one_film_dict['name'] = rt[0].strip()
one_film_dict['star'] = rt[1].strip()
one_film_dict['time'] = rt[2].strip()
print(one_film_dict)
#保存数据,存入csv
# def write_page(self, r_list):
# 打开文件要在for循环之前
# with open('maoyan.csv', 'a') as f:
# for rt in r_list:
# writer = csv.writer(f)
# writer.writerow(
# [rt[0], rt[1].strip(), rt[2].strip()[5, 15]]
# )
# 主函数
def main(self):
for offset in range(0, 91, 10):
# url = self.url.format(offset)
url = 'https://www.maoyan.com/board/4?timeStamp=1652929876901&channelId=40011&index=6&signKey=3a37c66f9ad17859383d8d4f02708497&sVersion=1&webdriver=false&offset={}'.format(
offset)
self.get_page(url)
time.sleep(random.randint(1, 3))
print('第%页爬取完成'%self.page)
self.page += 1
if __name__ == '__main__':
start = time.time()
spider = MaoyanSpider()
spider.main()
end = time.time()
print('执行时间:%.2f' % (end - start))
结果展示
三、数据持久化(mysql数据库)
1.pymysql模块
(1)execute()
import pymysql
#数据库连接对象
db=pymysql.connect(
host='127.0.0.1',#连接名称
user='root',#用户名
password='0000', # 密码
db='spider',#数据库名称
charset='utf8'
)
#游标对象
cursor=db.cursor()
#execute()方法第二个参数为列表传参补位
cursor.execute('insert into film values(%s,%s,%s)',
['霸王别姬','张国荣','1993'])
#提交到数据库执行
db.commit()
#关闭
cursor.close()
db.close()
(2)executemany
import pymysql
#数据库连接对象
db=pymysql.connect(
host='127.0.0.1',#连接名称
user='root',#用户名
password='0000', # 密码
db='spider',#数据库名称
charset='utf8'
)
#游标对象
cursor=db.cursor()
#存放所有数据的大列表
ins_list=[]
for i in range(2):
name=input('请输入第%d个学生姓名:'%(i+1))
age=input('请输入第%d个学生年龄:'%(i+1))
ins_list.append([name,age])
#定义插入语句
ins='insert into t3 values(%s,%s)'
#一次数据库的IQ操作可插入多条语句,提升功能
cursor.executemany(ins,ins_list[[],[],[]])
#提交到数据库执行
db.commit()
#关闭
cursor.close()
db.close()
(3)存入到mysql数据库
import random
import urllib
from urllib import request
import time
import re
import csv
import pymysql
class MaoyanSpider(object):
def __init__(self):
self.url='https://maoyan.com/board/4?offset={}'
self.user_agent_list=[
'Mozilla/5.0 (Windows NT 6.1; WOW64; rv:34.0) Gecko/20100101 Firefox/34.0 ',
'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/30.0.1599.101 Safari/537.36 ',
'Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; QQDownload 732; .NET4.0C; .NET4.0E)',
'Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; en) Opera 9.50']
#用于记录页数
self.page=1
#创建数据库连接对象和游标对象
# 数据库连接对象
self.db = pymysql.connect(
host='127.0.0.1', # 连接名称
user='root', # 用户名
password='0000', # 密码
db='spider', # 数据库名称
charset='utf8'
)
# 游标对象
cursor = self.db.cursor()
#获取数据
def get_page(self,url):
# 每次使用随机的user - agent
headers = {'User-Agent':random.choice(self.user_agent_list)}
request=urllib.request.Request(
url=url,
headers=headers
)
response=urllib.request.urlopen(request)
html=response.read().decode('utf-8')
#调用解析函数
self.parse_page(html)
#解析数据
def parse_page(self,html):
pattern=re.compile('<div class="movie-item-info">.*?title="(.*?)".*?class="star">(.*?)</p>.*?releasetime">(.*?)</p>',re.S)
r_list=pattern.findall(html)
self.write_page(r_list)
#保存数据,打印输出
# def write_page(self,r_list):
# one_film_dict={}
# for rt in r_list:
# one_film_dict['name']=rt[0].strip()
# one_film_dict['star']=rt[1].strip()
# one_film_dict['time']=rt[2].strip()
# print(one_film_dict)
#存入mysql数据库(executemany()[[],[],[],[]])
def write_page(self, r_list):
#定义空列表v
film_list={}
ins='insert into film values(%s,%s,%s)'
#处理数据,放到大列表film_list中
for rt in r_list:
one_film=[
rt[0],rt[1].strip(),rt[2].strip()[5:15 ]
]
#添加到大列表中
film_list.append(one_film)
#一次数据库的IO把1页数据存入
self.cursor.executemany(ins,film_list)
#提交列表数据库执行
self.db.commit()
#主函数
def main(self):
for offset in range(0,31,10):
url=self.url.format(offset)
self.get_page(url)
time.sleep(random.randint(1,3))
print('第%页爬取完成'%self.page)
self.page += 1
#所有页爬完之后再断开
self.cursor.close()
self.db.close()
if __name__=='__main__':
start=time.time()
spider=MaoyanSpider()
spider.main()
end=time.time()
print('执行时间:%.2f' % (end-start))
三、电影天堂案例(二级页面抓取)
1.查看是否为静态页面
右键---查看网页源代码
2. 确定url地址
百度搜索:电影天堂-2022最新电影-更多
3. 目标
一级页面
- 电影名称
- 电影链接
二级页面
- 下载链接
4.步骤
(1)找URL规律
第一页 https://www.ygdy8.net/html/gndy/dyzz/list_23_1.html第二页
https://www.ygdy8.net/html/gndy/dyzz/list_23_2.html第n页
https://www.ygdy8.net/html/gndy/dyzz/list_23_n.html
(2)写正则表达式
一级页面正则表达式(电影名称、电影详情链接)
<table width="100%".*?<td height="26">.*?<a href="(.*?)">.*?>(.*?)</a>
二级页面正则表达式
<td style="WORD-WRAP.*?>.*?>(.*?)</a>
代码演示
import urllib
from urllib import request
import re
import time
import random
import pymysql
from pymysql import connect
class FilmSky(object):
def __init__(self):
self.url='https://www.ygdy8.net/html/gndy/dyzz/list_23_{}.html'
self.user_agent_list = [
'Mozilla/5.0 (Windows NT 6.1; WOW64; rv:34.0) Gecko/20100101 Firefox/34.0 ',
'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/30.0.1599.101 Safari/537.36 ',
'Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; QQDownload 732; .NET4.0C; .NET4.0E)',
'Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; en) Opera 9.50']
#定义两个对象
self.db = pymysql.connect(
host='127.0.0.1', # 连接名称
user='root', # 用户名
password='0000', # 密码
db='spider', # 数据库名称
charset='utf8'
)
# 游标对象
self.cursor = self.db.cursor()
#获取html函数(因为两个页面都需要发请求)
def get_page(self,url):
headers = {'User-Agent': random.choice(self.user_agent_list)}
request = urllib.request.Request(
url=url,
headers=headers
)
response=urllib.request.urlopen(request)
#ignore参数,实在处理不了的编码错误忽略
#查看网页源码,发现网页编码为gb2312,不是utf-8
html=response.read().decode('gbk','ignore')
return html
#解析提取数据(把名称和下载链接一次性拿到)
#html为一级响应页面的内容
def parse_page(self,html):
#先解析一级页面(电影名称和详情链接)
pattern=re.compile('<table width="100%".*?<td height="26">.*?<a href="(.*?)".*?>(.*?)</a>',re.S)
#film_list:[('详情链接',‘名称’),()]
film_list=pattern.findall(html)
ins='insert into sky_film values(%s,%s)'
#print(film_list)
for film in film_list:
film_name=film[1]
film_link='https://www.ygdy8.net'+film[0]
#拿到详情链接后,再获取详情链接html,提取下载链接
download_link=self.parse_two_html(film_link)
self.cursor.execute(ins,[film_name,film_link])
# 提交列表数据库执行
self.db.commit()
#打印测试
d={
'电影名称':film_name,
'下载链接':download_link
}
print(d)
#解析二级页面,获取下载链接
def parse_two_html(self,film_link):
two_html=self.get_page(film_link)
pattern=re.compile('<td colspan="2".*?<a target="_blank" href="(.*?)">',re.S)
download_link=pattern.findall(two_html)[0]
return download_link
#主函数
def main(self):
for page in range(1,3):
url=self.url.format(page)
html=self.get_page(url)
self.parse_page(html)
time.sleep(random.randint(1,3))
print('第%d页完成'%page)
# 所有页爬完之后再断开
self.cursor.close()
self.db.close()
if __name__=='__main__':
start=time.time()
spider=FilmSky()
spider.main()
end=time.time()
print('执行时间:%.2f'%(end-start))