【python】爬虫

所用示例

1.任务:爬取豆瓣top250
2.网址:https://movie.douban.com/top250
3.爬取内容:电影名称、豆瓣评分、评价数、电影概况、电影链接
在这里插入图片描述

一、准备工作

(一)找网址

https://movie.douban.com/top250

每一页的链接:url = ‘https://movie.douban.com/top250?start=’+ str(page*25)+’&filter=’(page是页数-1)

(二)找数据的位置:

方法一:元素(element)

1.Fn+F12
2.点击element
3.点击网页内容:
在这里插入图片描述
4.我们根据层级结构确定数据位置:
在这里插入图片描述

方法二:网络(network)+刷新

headers:我们发送的请求
response:返回的请求
可以看到请求头等信息
在这里插入图片描述

(三)编码规范

1.一般python程序第一行要加入(这样可以在代码中包含中文)

#-*-coding:utf-8-*-
或者
#coding=utf-8

2.用于测试程序:(定义程序入口)

def main():
	print("hello")
if __name__=="__main__":#下划线有两根,当程序执行时调用函数
	main()

(四)引入模块

1.引入自己写的模块:
在这里插入图片描述
2.引入系统的模块
(1)安装库:
方法1:点击Terminal——输入pip install 库名
方法2:File->settings->Project douban->Project Intrpreter->±>搜索要安装的包->Install Package
(2)引入库:

from bs4 import BeautifulSoup #网页解析,获取数据beautifulsoup4
import re #正则表达式,文字匹配
import urllib.request,urllib.error #指定URL,获取网页数据
import xlwt #进行excel操作
import sqlite3 #进行SQLite数据库操作

二、构建流程

step1 爬取网页

baseurl = 'https://movie.douban.com/top250?start='
datalist = getData(baseurl)
def getData(baseurl):
    datalist = 网页中获取的数据
    return datalist

step2 解析数据
边爬边解析,逐一解析

step3 保存数据

savepath = '.\\豆瓣电影Top'
def saveData(savepath):
	……

三、urllib

(一)把网页中的源代码封装到一个对象中

import urllib.request

#获取一个get请求
response = urllib.request.urlopen("http://www.baidu.com") #封装在response中
print(response.read().decode('utf-8')) #decode('utf-8')对获取到的网页代码解码,防止出现中文乱码,打出网页源码


#获取一个post请求(用于模拟登录(密码,用户))
用httpbin.org

import urllib.parse #解析器,解析键值对

data = bytes(urllib.parse.urlencode({"hello":"world"}),encoding = "utf-8")#表单,将键值对信息封装为二进制的包,encoding = "utf-8"封装方式

response = urllib.request.urlopen("http://httpbin.org/post",data = data)

print(response.read().decode('utf-8'))

(二)超时问题

try:
	response = urllib.request.urlopen("http://httpbin.org/post",timeout=0.01)#时间超过0.01秒
	print(response.read().decode('utf-8'))
except urllib.error.URLError as e:
    print("time out!")

(三)响应头的问题(伪装成浏览器)

url = "https://httpbin.org/post"

headers = {"User-Agent":"……"}

data = bytes(urllib.parse.urlencode({"hello":"world"}),encoding = "utf-8")

req = urllib.request.Request(url=url,data=data,headers=headers,method='post')#封装,模拟成真的浏览器

response = urllib.request.urlopen(req)#封装

print(response.read().decode("utf-8"))

在这里插入图片描述

(四)获取数据

#爬取网页
def getData(baseurl):
	dataist = []
    for i in range(0,10):#调用获取页面信息的函数,10次
    	url = baseurl + str(i*25)
        html = askURL(url)#保存获取到的网页源码
	return datalist

#得到指定的一个URL的网页内容
def askURL(url):
	head = {
	"User-Agent":"……"
	}#用来伪装,模拟浏览器头部信息
    request = urllib.request.Request(url,headers=head)#携带headers去访问url
    try:
        	response = urllib.request.urlopen(request)#获取整个网页的信息
            html = response.read().decode("utf-8")#读取信息(网页源码)
    except urllib.error.URLError as e:#捕获错误
        if hasattr(e,"code"):
            print(e.code)#打印code,看编码有什么问题
        if hasattr(e,"reason"):
            print(e.reason)#打印出没有成功的原因
    return html

四、BeautifulSoup(获取网页指定内容)

(一)概述

1.作用:获取网页指定内容
2.引用

from bs4 import BeautifulSoup

(二)操作

1.

from bs4 import BeautifulSoup
file = open("./baidu.html","rb")#baidu.html是存有已经爬取并存下来的网页源代码的文件
html = file.read()#网页源代码
bs = BeautifulSoup(html,"html.parser")#解析html,解析器为html.parser,解析为树形结构

print(bs.a)
print(bs.title)#tag打印出标签tag及其内容:只能拿出找到的第一条

print(bs.title.string)
print(type(bs.title.string))#NavigableString 打印出标签里的内容(字符串)

print(bs.a.attrs)#拿到标签里的所有属性

print(bs)#整个文档的内容

print(bs.a.string)#Comment 是一个特殊的NavigableString,输出的内容不包含注释符号

2.文档的遍历:

print(bs.head.contents)#将tag(此处的tag是head)的子节点以列表的方式输出
print(bs.head.contents[1])#用列表所用来获取它的第1个元素

注:详情可搜索:遍历文件树

3.文档的搜索:

#字符串遍历
t_list = bs.find_all("a")#查找所有a标签的超链接
print(t_list)

#正则表达式
t_list=bs.find_all(re.compile("a"))#找出含有a字母的标签下的所有链接
print(t_list)

#传入一个函数,根据函数要求来搜索
def name_is_exists(tag)
	return tag.has_attr("name")
t_list = bs.find_all(name_is_exists)
print(t_list)

#指定参数经行搜索kwargs
t_list=bs.find_all(id="head")
t_list=bs.find_all(class_=True)
t_list=bs.find_all(href="http://……")

#找出含有响应内容的文本
t_list=bs.find_all(text = "地图")#找出含有“地图”的文本
t_list=bs.find_all(text = ["地图","贴吧"])
t_list=bs.find_all(text=re.compile("\d"))#用正则表达式查出所有含数字的文本内容(标签里的字符串

#limit参数
t_list = bs.find_all("a",limit=3)#获取三条标签为a的文档

#css选择器
t_list = bs.select("title")#通过标签查找
t_list = bs.select(".mnav")#通过类名查找(class="mnav")
t_list = bs.select("#u1")#按照id来查找(id="u1")
t_list = bs.select("a[class='bri']")#通过属性来查找(<a class="bri" href="……"……)
t_list = bs.select("head>title")#通过子标签查找(<head>……<title>……)

t_list = bs.select(".mnav ~ .bri")#兄弟节点
print(t_list[0].get.text())#拿第一个文本元素

五、正则表达式(字符串的格式要求)

(一)正则表达式的常用操作符

在这里插入图片描述
注意:可以网上搜索“史上最全正则表达式大全”

(二)re库(解决正则表达式匹配问题)

1.作用

在这里插入图片描述

2.模式限制

在这里插入图片描述
①re.l 忽略大小写

②re.S 扩大字符的判断范围

3.代码

import re

#创建模式对象
pat = re.compile("AA")#此处的AA是正则表达式,用来验证其他的字符串

#校验
#写法1
m1 = pat.search("CBA")#""中放被校验的内容
print(m1)
m2 = pat.search("CBAA")
print(m2)
m3 = pat.search("AACBAA")
print(m3)
#写法2
m = re.search("asd","Aasd")
print(m)

#找到所有匹配的内容
print(re.findall("a","ASDaBDDa"))#第一个""中放规则,后面的""放字符串
print(re.findall("[A-Z]+","ASDaBDDa"))

#风格替换
print(re.sub("a","A","abcdef")#找到a用A替换,在第三个字符串中查找
     

注意:建议在被比较的字符串前面加上一个r,防止转义字符问题,eg:

a = "\aabs-\'"
print(a)

(三)应用

找要爬取的内容的源代码:

①影片内容信息
在这里插入图片描述
②影片链接
在这里插入图片描述
③影片图片
在这里插入图片描述
④影片名字
在这里插入图片描述
⑤评分
在这里插入图片描述
⑥评价人数
在这里插入图片描述
⑦一句话的评价
在这里插入图片描述
⑧电影信息
在这里插入图片描述
注意:复制源代码:右键->edit as HTML

代码:

def main():
    baseurl = "http://movie.douban.com/top250?start="
    datalist = getData(baseurl)

#影片详情信息的规则    
findLink = re.compile(r'<a href="(.*?)">')#创建正则表达式对象,表示规则(字符串模式)②   
findImgSrc = re.compile(r'<img.*src="(.*?)"',re.S)#找图片的内容,re.S让换行符包含在字符中,忽略换行符号③
findTitle = re.compile(r'<span class="title">(.*)</span>')#影片片名
findRating = re.compile(r'<span class="rating_num" property="v:average">(.*)</span>')#影片评分
findJudge = re.compile(r'<span>(\d*)人评价</span>')#评价人数
findInq = re.compile(r'<span class="inq">(.*)</span>')#一句话的评价
findBd = re.compile(r'<p class="">(.*?)</p>',re.S)#电影信息

#爬取网页
def getData(baseurl):
    datalist = []
    for i in range(0,10):  #调用获取页面信息10次
        url = baseurl = str(i*25)
        html = askURL(url)  #保存获取到的网页源码
        
#逐一解析数据
        soup = BeautifulSoup(html,"html.parser")
        for item in soup.findall('div',class_="item"):  #查找符合要求(<div class="item">……)的字符串,形成列表(内容含有源代码)①
            data = []#保存一部电影的所有信息
            item = str(item)
            
            link = re.findall(findLink,item)[0] #re库用来通过正则表达式查找指定的字符串,[0]表示只要符合条件的第一个,link=一页中所有电影的超链接
            data.append(link)#把找到的链接加进去
            ImgSrc = re.findall(findImgSrc,item)[0] #图片信息
            data.append(ImgSrc)#把找到的图片加进去
            titles = re.findall(findTitle,item) #片名可能只有一个中文名没有外文名,也可能都有
            if(len(titles)==2):
            	ctitle = titles[0]
                data.append(ctitle)#添加中国名
                otitle = titles[1].replace("/","")#去掉无关的符号
                data.append(ctitle)#添加外文名
            else:
                data.append(titles[0])
                data.append(' ')#外国名留空
            
            rating = re.findall(findRating,item)[0] #打分
            data.append(rating)#把找到的分数加进去
            judgeNum = re.findall(findJudge,item)[0] #评价人数
            data.append(judgeNum)#添加评价人数
            inq = re.findall(findInq,item) #添加概述
            if len(inq)!=0:
                inq = inq[0].replace("。","")#去掉句号
                data.append(inq)#概述
            else
            	data.append(" ")#留空
                
            bd = re.findall(findBd,item)[0]
            bd = re.sub('<br(\s+)?/>(\s+)?'," ",bd)#去掉<br/>
            bd = re.sub('/'," ",bd)#替换\
            data.append(bd.strip())#bd.strip()去掉前后的空格
            
            datalist.append(data)#处理好一部电影的信息就存入datalist
            
    return datalist

六、保存数据

1.txt保存

(1)打开

打开方式:open(文件名,访问模式)

访问模式:在这里插入图片描述
例:

f = open('text.txt','w')#w模式(写模式),文件不存在就打开

注意:不存在text的open后新建在当前工程下

(2)关闭

关闭方式:close()

f.close()

(3)写入

写入方式:write

f.write("hello,world!")

(4)读取

操作1:按字符读(read())
f.read(5)#读取5个字符

注:read并不是每次都从开头读取,执行一次就往后移

例子:

f = open("text.txt",'r')

content = f.read(5)
print(content)#打出hello

content = f.read(5)
print(content)#打出,worl

f.close()
操作2:读取整个文档(列表)(readlines())
f = open("text.txt",'r')

content = f.readlines()
print(content)#打出整个文档

i=1
for temp in content:
    print("%d:%s"%(i,temp))
    i+=1
#一行一行读取

f.close()
操作3:按行读取(readline())
f = open("text.txt",'r')

content = f.readline()
print(content,end='')#打出第一行,end=''相当于不换行

content = f.readline()
print(content)#打出第二行

f.close()

注意:其他操作import os可以自行查找补充

2.Excel保存

(1)库

xlwt

(2)基本思路

以utf-8编码创建一个Excel对象

创建一个sheet表

往单元格写入内容

保存表格

(3)代码

表格的坐标位置
在这里插入图片描述

import xlwt

workbook = xlwt.Workbook(encoding="utf-8") #创建workbook对象
worksheet = workbook.add_sheet("sheet1")#创建名为sheet1的工作表

worksheet.write(0,0,'hello') #写入数据.write(行,列,参数内容)
workbook.save("student.xls") #保存数据表

九九乘法表写入
在这里插入图片描述

(4)应用

savepath = "豆瓣电影Top250.xls"
def saveData(datalist,savepath):
	book = xlwt.Workbook(encoding="utf-8",style_compression=0) #创建workbook对象
	sheet = book.add_sheet("豆瓣电影Top250",cell_overwrite_ok=True)#创建名工作表
    col = ("电影详情链接","图片链接","影片中文名","影片外文名","评分","评价书","概况","相关信息")
	for i in range(0,8):
        sheet.write(0,i,col[i])#列名
    for i in range(0,250):
        data = datalist[i]
        for j in range(0,8)
        	sheet.write(i+1,j,data[j])
           
	workbook.save(savepath) #保存数据表

3.Pymysql保存

在这里插入图片描述

(1)下载

pip install pymysql

(2)链接数据库

import pymysql
 
conn = pymysql.connect( # 创建数据库连接
    host='10.10.11.131', # 要连接的数据库所在主机ip
    user='chb', # 数据库登录用户名
    password='123456!', # 登录用户密码
    database='base1' # 数据库的名称
)

(3)创建游标

cursor = conn.cursor()#游标
cursor.execute(操作)#可以用游标进行各种操作

(4)创建数据库、表

①创建数据库
# -*- coding: utf-8 -*-
import pymysql
 
conn = pymysql.connect( # 创建数据库连接
    host='10.10.11.131', # 要连接的数据库所在主机ip
    user='chb', # 数据库登录用户名
    password='123456!', # 登录用户密码
    charset='utf8' # 编码,注意不能写成utf-8
)
cursor = conn.cursor()
cursor .execute("create database test_db character set utf8;")
# 执行完之后别忘了关闭游标和数据库连接
cursor.close()
conn.close()
②创建数据表
# -*- coding: utf-8 -*-
import pymysql
 
conn = pymysql.connect( # 创建数据库连接
    host='10.10.11.131', # 要连接的数据库所在主机ip
    user='chb', # 数据库登录用户名
    password='123456!', # 登录用户密码
    database='test_db', # 连接的数据库名,也可以后续通过cursor.execture('user test_db')指定
    charset='utf8' # 编码,注意不能写成utf-8
)
 
cursor = conn.cursor() # 创建一个游标
 
# 需要执行的创建表的sql语句
sql = """
create table book(
bookid int auto_increment primary key ,
bookname VARCHAR(255) not null ,
authors VARCHAR(255) not null ,
year_publication YEAR not null
);
"""
 
cursor.execute(sql) # 使用游标执行sql
 
# 执行完之后别忘了关闭游标和数据库连接
cursor.close()
conn.close()

(5)增、删、改、查

①插入
(1.一次插入一条记录execute()
cursor.execute('insert into 数据表名(键值对) values(数据类型);',(插入的数据内容))
cursor.execute('insert into book(bookname, authors, year_publication) values("%s", "%s", %s);' % ('Python从入门到放弃', '乔布斯', 2019))
conn.commit()
import pymysql

user = '小黑'
pwd  = '06161086'
sql = "insert into userinfo(user,password) values(%s,%s)"#增
cursor.execute(sql,user,pwd)#返回值r为受影响的行数
conn.commit()
(2.一次插入多条记录executemany()
data = [
    ('21天完全入门Java', '扎克伯格', 2018),
    ('Linux学习手册', '李纳斯', 2017),
    ('MySQL从删库到跑路', '比尔盖茨', 2018),
]
cursor.executemany('insert into book(bookname, authors, year_publication) values("%s", "%s", %s);', data)
conn.commit()
②更新
cursor.execute('update book set authors=%s where bookname=%s;', ["马云", "Python从入门到放弃"])
conn.commit()
③查询
(1.fetch操作

Ⅰ查询所有记录:fetchall()

cursor.execute('select * from 表名;')
books = cursor.fetchall()
cursor.execute('select * from book where bookid < %s;', [4])
books = cursor.fetchall()
print(books)#输出结果以元组形式保存,每条记录也是一个元素输出内容为(1, 'Python从入门到放弃', '马云', 2019), (2, 'Python从入门到放弃', '马云', 2019), (3, '21天完全入门Java', '扎克伯格', 2018))

Ⅱ查询指定数量的记录:fetchmany(要记录的条数)

cursor.execute('select * from book where bookid < %s;', [4])
books = cursor.fetchmany(2)
print(books)#输出结果为((1, 'Python从入门到放弃', '马云', 2019), (2, 'Python从入门到放弃', '马云', 2019))

Ⅲ取第一条记录:fetchone()

cursor.execute('select * from book where bookid < %s;', [4])
books = cursor.fetchone()
print(books)#输出结果(1, 'Python从入门到放弃', '马云', 2019)
(2.游标(pymysql还提供了DictCursor、SSCursor、SSDictCursor这几类游标。)

ⅠDicCursor(返回的数据以字典形式保存)

cursor = conn.cursor(pymysql.cursors.DictCursor) # 创建一个字典游标
cursor.execute('select * from book where bookid < %s;', [3])
books = cursor.fetchall()
print(books)
cursor.execute('select * from book where bookid < %s;', [3])
book_one = cursor.fetchone()
print(book_one)

输出结果:

[{‘bookid’: 1, ‘bookname’: ‘Python从入门到放弃’, ‘authors’: ‘马云’, ‘year_publication’: 2019},

{‘bookid’: 2, ‘bookname’: ‘Python从入门到放弃’, ‘authors’: ‘马云’, ‘year_publication’: 2019}]

{‘bookid’: 1, ‘bookname’: ‘Python从入门到放弃’, ‘authors’: ‘马云’, ‘year_publication’: 2019}

ⅡSSCursor和SSDictCursor(流式游标,陆陆续续一条一条得返回查询数据,用于内存低、网络带宽小、数据量大的应用场景中。)

cursor = conn.cursor(pymysql.cursors.SSCursor) # 创建一个流式游标
cursor.execute('select * from book;')
book = cursor.fetchone()
while book:
print(book)
book = cursor.fetchone()

输出结果:

(1, ‘Python从入门到放弃’, ‘马云’, 2019)

(2, ‘Python从入门到放弃’, ‘马云’, 2019)

(3, ‘21天完全入门Java’, ‘扎克伯格’, 2018)

(4, ‘Linux学习手册’, ‘李纳斯’, 2017)

(5, ‘MySQL从删库到跑路’, ‘比尔盖茨’, 2018)

④删除
(1.删除一条记录
cursor.execute('delete from book where bookid=%s;', [1])
(2.删除多条记录
cursor.executemany('delete from book where bookid=%s;', [[2], [4]])
conn.commit()#bookid为2和4的记录已经被删除
  • 20
    点赞
  • 26
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值