PYTHON爬虫入门案例

逝者如斯夫,不舍昼夜!

原理:模拟浏览器访问网页的方式向HTTP发起请求,获取响应Response数据
案例:爬取豆瓣前250电影信息

相关库

re 正则表达式
bs4 对html,json等格式数据进行解析
urllib http请求库,获取数据
xlwt Excel相关操作
sqlite3 sqlite数据库操作

主流程

网页爬取
网页解析
数据保存

数据爬取

  1. 生成请求对象
Request(url, data=None, headers={ }, origin_req_host=None,unverifiable=False, method=None)
参数说明
url请求地址
data提交给网址的表单数据
headers通过修改User-Agent来伪装浏览器
origin_req_host请求方的host或者IP
unverifiable表示这个请求是无法验证的,默认是False。例如,我们请求一个HTML文档中的图片,但是我们没有自动抓取图像的权限,这时unverifiable的值就是True
method请求使用的方法,比如GET、POST

封装请求对象,包括url,头部信息等

def getHeaders(url):
       headers={
        "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.169 Safari/537.36"
        };
       dict={"hello":"word"}
       data=bytes(urllib.parse.urlencode(dict),encoding="utf-8")
       req=urllib.request.Request(url=url,data=data,headers=headers,method="GET")
       return req
  1. 获取数据
    通过urllib库中的urlopen打开一个url对象,在使用read()方法对源码解析
def GetData(url):
    req= getHeaders(url)#封装的request对象
    try:#异常捕获
    	#urlopen无法传参数,所以需要声明一个request对象,通过对象添加参数
        reponse=urllib.request.urlopen(req,timeout=10);#打开一个携带头部信息的url对象,也可以直接是一个url路径
        print(reponse.read().decode("utf-8"))#read对源码解析,decode:使用utf-8格式进行解析
        #print(reponse.status)#状态码
        #print(reponse.getheaders())#列表的形式展现出响应头
        #print(reponse.getheader("Date"))#获取指定的响应头
    except urllib.error.URLError as e:
        if isinstance(e.reason,socket.timeout):
            print(" timeout=1,now time out!")

数据解析

在这里使用BeautifulSoup4库,它默认支持Python的标准HTML解析库;它将复杂HTML文档转换成一个复杂的树形结构,通过下面的四大对象检索HTML树

BeautifulSoup4四大对象对象类型重要属性备注
Tagbs4.element.Tagname 、 attrs
NavigableStringbs4.element.NavigableStringstring
BeautifulSoupbs4.BeautifulSoupname、attrs大部分时间会当做一个Tag使用
Commentbs4.element.Commentstring特殊的NavigableString ,当标签内容含有注释时,会将注释符号替换掉

1.Tag、BeautifulSoup用法

bs.a#访问首个a标签的所有内容
bs.a.name#输出首个a标签的名称,即a
bs.a.attrs#输出首个a标签的属性,得到一个字典

2.NavigableString、Comment用法

bs.a.string#访问首个a标签内的文本内容

找到符合要求的所有的节点或节点内容

方法:find_all(name, attrs, recursive, text, **kwargs)

方法参数说明及使用

参数说明使用方法
name查找与字符串完全匹配的内容bs.find_all(“a”) ;正则方式:bs.find_all(re.compile(“a”)); 列表方式:bs.find_all([“meta”,“link”]); 方法匹配:bs.find_all(GetName)
attrs搜索特殊属性的tagbs.find_all(attrs={“data-foo”:“value”});若使用bs.find_all(data-foo=“value”)会报错
text搜索文档中的字符串内容,接受 字符串,正则表达式,列表bs.find_all(text=“hao123”); 正则:bs.find_all(text=re.compile("\d")) ;列表:bs.find_all(text=[“hao123”, “地图”, “贴吧”]) ; 方法:略
kwargsbs.find_all(id=“head”) ;find_all(href=re.compile(“http://news.baidu.com”)); class加_区分py中的关键字 bs.find_all(class_=True)

此外还有find()方法,将返回符合条件的第一个Tag,有时我们只需要或一个Tag时,我们就可以用到find()方法了。当然了,也可以使用find_all()方法,传入一个limit=1,然后再取出第一个值也是可以的,不过未免繁琐

bs.find("title")#返回只有一个结果的列表
bs.find("div").find("div")
#等价于
 bs.find("div").find("div")

3.CSS选择器
使用CSS选择器的语法找到Tag:

查找方式使用方法
标签名bs.select(‘a’)
类名bs.select(’.mnav’)
IDbs.select(’#u1’)
组合bs.select(‘div .bri’)
属性bs.select(‘a[class=“bri”]’)
子标签bs.select(‘a[class=“bri”]’)
兄弟标签bs.select(".mnav ~ .bri")
获取内容bs.select(‘title’)[0].get_text()

4.HTML树的遍历

bs.a.contents#将首个a标签下的所有子节点(不包括孙子节点,兄弟节点)以列表的形式呈现出来
bs.a.children#将首个a标签下的所有子节点(不包括孙子节点,兄弟节点)以迭代器的形式呈现出来

5.正则表达式(re库)

方法使用返回说明
re.search(pattern,string)}re.search( r"\d" , CB2A )<_sre.SRE_Match object; span=(2, 3), match=‘2’>从string的开始位置搜索,没有就继续搜索,
re.match(pattern,string)re.match(r’\d’,‘1CBA’)<_sre.SRE_Match object; span=(0, 1), match=‘1’>在字符串开始位置匹配,开始位置没有返回NONE
re.findall(pattern,string)re.findall(r’\d’,‘C3B2A1’)[‘3’, ‘2’, ‘1’]列表形式返回匹配项
re.split(pattern,string)m=re.split(r’\d’,‘C3BA’)[‘C’, ‘BA’]分割字符串,返回列表
re.sub(pattern,replace,string)re.sub(r’\d’,‘NN’,‘C3B2A1’)CNNBNNANN用repl替换 pat匹配项

声明全局变量

pictureLink=re.compile(r'<a\s+class=""\s+href="(.*?)">')#详情链接
ChinAndEngName=re.compile(r'<span\s+class="title"\s*>(.*?)</span>')#中英文名
Author=re.compile(r'<p\s+class=""\s*>(.*?)</p>',re.S)#详细信息
Score=re.compile(r'<span\s+class="rating_num"\s+property="v:average">(\d*.\d*)</span>')#分数
pj=re.compile(r'<span>(.*?)</span>')#简介

解析

def  parseData(url):
   reponse=GetData(url)#获取html
   bs=BeautifulSoup(reponse,"html.parser")#生成html树
   datalist=[]
   for item in bs.find_all("div",class_="info"):#获取class="info"的div及子元素
       data=[]
       data.append(re.findall(pictureLink,str(item))[0])#详情链接
       data.append(re.findall(ChinAndEngName,str(item))[0])#中文名
       if len(re.findall(ChinAndEngName,str(item)))==1:   #英文名
           data.append("")
       else:
            data.append(re.sub(r'\s*/\s*','',re.findall(ChinAndEngName,str(item))[1]))
       data.append(re.sub(r'[\s,<br/>]','',str(re.findall(Author,str(item))[0])))#电影详情
       data.append(re.findall(Score,str(item))[0])#分数
       data.append(re.findall(pj,str(item))[0])#评价
       datalist.append(data)
   return datalist

数据保存

def saveData(datalist):
    book=xlwt.Workbook(encoding="utf-8")#创建wookbook对象
    sheet=book.add_sheet('豆瓣电影',cell_overwrite_ok=True)//创建可覆盖得到工作表
    col=("详情链接","中文名称","英文名称","详情","评分","评价");
    for i in range(0,6): 
        sheet.write(0,i,col[i])#向第行i列写入数据col[i] 
    for i in range (0,250):
        data=datalist[i]
        for j in range(0,6):
           sheet.write(i+1,j,data[j])
    book.save("豆瓣电影.xls")

main调用

 url="https://movie.douban.com/top250?start="
    datalist=[];
    for i in range(0,10):
        data=parseData(url+str(25*i))
        for j in range(0,25):
           datalist.append(data[j])
    #print(len(datalist))
    saveData(datalist)

效果图

在这里插入图片描述

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值