python学习-利用xpath爬取豆瓣top250电影保存至本地excel

  1. requests库
  2. lxml
  3. csv
库的安装

1.pip install ****
2.pycharm中file->setting在这里插入图片描述
+号添加库

爬取网页数据

1. requests库

可以说, Requests是用Python语言编写的简单易⽤的HTTP库

1.1基本操作
    r=requests.get("http://www.baidu.com/") # 请求网页
    print(r.status_code) # HTTP请求的返回状态,200表示连接成功,404表示失败
    print(type(r))
    print(r.headers) # 头部信息
    print(r.encoding) # 头部可能编码形式
    print(r.apparent_encoding) # 内容可能编码形式
    r.encoding=r.apparent_encoding
    print(r.text) # HTTP响应内容的字符串形式,即,url对应的页面内容

在这里插入图片描述

requests
获取urlrequest = requests.get(“http://www…com”)
获取状态码request.states_code
返回htmlrequest.text
获得头部信息request.headers
返回请求的urlrequest.url
requests.get(‘url’) #GET请求,获取url位置上的资源
requests.post(“url”) #POST请求,在url位置的资源后附加新的数据
requests.put(“url”) #PUT请求,向url位置存储资源,覆盖原有的资源
requests.delete(“url”) #DELETE请求,删除url位置存储的资源
#PATCH请求,局部更新url位置的资源,改变该处资源的部分内容,优点是节省网络带宽
requests.head(“url”) #HEAD请求
requests.options(“url”) #OPTIONS请求

在这里插入图片描述

1.2 网页爬取通用框架
def getHTMLText(url):
    try:
        # kv={'user_agent':'Mozilla/5.0'} #更改头部信息,对于要求较高的网站
        # r = requests.get(url, headers=kv)
        r = requests.get(url, timeout=30)
        r.raise_for_status()  # 如果状态不是200, 引发HTTPError异常
        r.encoding = r.apparent_encoding
        return r.text
    except:
        return "产生异常"
        
if __name__ == "__main__":
    url = "http://www.baidu.com"
    print(getHTMLText(url))
2.XPath

XPath 是一门在 XML 文档中查找信息的语言
XML文档是被作为节点树来对待的,树的根被称为根节点或者文档节点
节点之间的关系有:父(parent)、子(children)、同胞(sibling)、先辈(ancestor,该节点的父,父的父等)、后代(decentant,该节点的子,子的子)

2.1 语法

a.选取节点

方式描述
/绝对路径提取
//相对路径提取
@指定属性提取

b.谓语

谓语用来查找某个特定的节点或者包含某个指定的值的节点。谓语被嵌在方括号中。

方式描述
/bookstore/book[1]选取属于 bookstore 子元素的第一个 book 元素。
/bookstore/book[last()]选取属于 bookstore 子元素的最后一个 book 元素。
/bookstore/book[last()-1]选取属于 bookstore 子元素的倒数第二个 book 元素。
/bookstore/book[position()< 3]选取最前面的两个属于 bookstore 元素的子元素的 book 元素。
//title[@lang]选取所有拥有名为 lang 的属性的 title 元素。
//title[@lang=‘eng’]选取所有 title 元素,且这些元素拥有值为 eng 的 lang 属性。
/bookstore/book[price>35.00]选取 bookstore 元素的所有 book 元素,且其中的 price 元素的值须大于 35.00。
/bookstore/book[price>35.00]/title选取 bookstore 元素中的 book 元素的所有 title 元素,且其中的 price 元素的值须大于 35.00。

c.选取未知节点

XPath 通配符可用来选取未知的 XML 元素

方法描述
*匹配任何元素节点。
@*匹配任何属性节点。
node()匹配任何类型的节点。

d.选取若干路径

通过在路径表达式中使用"|"运算符,您可以选取若干个路径。
如:/bookstore/book/title | //price: 选取属于 bookstore 元素的 book 元素的所有 title 元素,以及文档中所有的 price 元素。

2.2 查看网页

右击检查/(F12)
在这里插入图片描述

3. csv

csv文件格式是一种通用的电子表格和数据库导入导出格式。

# 读取csv文件
    import csv
    with open('some.csv', 'rb') as f:        # 采用二进制的方式处理可以省去很多问题
        reader = csv.reader(f)
        for row in reader:
            # do something with row, such as row[0],row[1]
            # 如 print(row)

 # 写入csv文件
    import csv
    with open('some.csv', 'wb') as f:      # 采用二进制的方式处理可以省去很多问题
    # 注意:如果打开csv文件出现空行的情况,那么需要添加一个参数 newline=” with open('some.csv','w',newline='')as f:
        # 实例化csv.writer对象
        writer = csv.writer(f)
        # 用writerows方法将数据以指定形式保存
        writer.writerows(someiterable)
        # writerow(写入一行)writerows(写入多行)


# 在写入字典序列类型数据的时候,需要传入文件对象——f,字段名称——fieldnames    
import csv
headers = ['class','name','sex','height','year']
rows = [
        {'class':1,'name':'xiaoming','sex':'male','height':168,'year':23},
        {'class':1,'name':'xiaohong','sex':'female','height':162,'year':22},
        {'class':2,'name':'xiaozhang','sex':'female','height':163,'year':21},
        {'class':2,'name':'xiaoli','sex':'male','height':158,'year':21},
    ]

with open('test2.csv','w',newline='')as f:
    f_csv = csv.DictWriter(f,headers)
    f_csv.writeheader() # 写表头
    f_csv.writerows(rows) # 写入多行

获取豆瓣top250电影数据

每翻一页start+25
在这里插入图片描述
在这里插入图片描述
每部电影信息在 < li > 中
在这里插入图片描述
在这里插入图片描述
电影排名://div[@class=“item”]/div[1]/em/text()
在这里插入图片描述
同样在div[@class=“item”]下电影名字取第一个:div.xpath(‘div[2]/div[1]/a/span/text()’)[0]
在这里插入图片描述

导演主演信息:director = div.xpath(‘div[2]/div[2]/p/text()’)[0]
上映时间及国家和类型:
year_country =div.xpath(‘div[2]/div[2]/p/text()’)[1]
评分:grade = div.xpath(‘div[2]/div[2]/div/span[2]/text()’)[0]
评分人数:
div.xpath(‘div[2]/div[2]/div/span[4]/text()’)[0].replace(“人评价”,"")
短评:
div.xpath(‘div[2]/div[2]/p[2]/span/text()’)[0]

在这里插入图片描述

# split("/") 以“/”分割,得到年份、国家和分类
            movie_year_string=str(year_country.replace('\n',"").replace("\xa0","").split("/")[0]) # split() 分割
            movie_country_string=str(year_country.replace('\n',"").replace("\xa0","").split("/")[1])
            movie_category_string=str(year_country.replace('\n',"").replace("\xa0","").split("/")[2])
#strip()方法从字符串中去掉在其左侧和右侧的空格时,括号内单引号里应保留空格,导演信息前有大量空格
 			movie_director_string=str(director.replace('\n',"").split('\xa0\xa0\xa0')[0]).strip(' ') 

代码

import requests
from lxml import etree
import csv

with open("movie.csv","w",encoding="GB18030",newline="") as f:
    writer = csv.DictWriter(f,fieldnames=["电影排名","电影名称","年份","国家","类型","导演","主演","电影评分","电影评论数","电影短评"])
    writer.writeheader()
    #拼接网址,发起请求
    for x in range(0,226,25):
        #拼接出来每一页的地址
        url = "https://movie.douban.com/top250?start={}&filter=".format(x)
        print("正在爬取--{}--网址的数据".format(url))
        kv = {'User-Agent':'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.88 Safari/537.36'}  # 更改头部信息,对于要求较高的网站
        response = requests.get(url=url, headers=kv)
        # print(response.headers)
        html_obj = etree.HTML(response.text)
        div_list = html_obj.xpath('//div[@class="item"]')
        for div in div_list:
            rank = div.xpath('div[1]/em/text()')[0]
            movie_name = div.xpath('div[2]/div[1]/a/span/text()')[0]
            director = div.xpath('div[2]/div[2]/p/text()')[0]
            year_country = div.xpath('div[2]/div[2]/p/text()')[1]
            # country=div.xpath('div[2]/div[2]/p/text()')[1].split("/")[0]
            grade = div.xpath('div[2]/div[2]/div/span[2]/text()')[0]
            #replace():把**字符替换成**
            comment_num = div.xpath('div[2]/div[2]/div/span[4]/text()')[0].replace("人评价","")
            #因为有的电影没有短评,强行匹配短评会报错!
            try:
                short_comment = div.xpath('div[2]/div[2]/p[2]/span/text()')[0]
            except Exception as e:
                short_comment="没有短评"
                
            #定义一个字符串,存储清理过后的电影名称
            movie_name_string = ''
            for movie in movie_name:
                #把电影名称中的\xa0替换成空,然后把处理过后的电影名称拼接起来
                movie_name_string+=movie.replace("\xa0","") # \xa0 是不间断空白符 &nbsp

            # 定义字符串,存储清理过后的年份及国家
            movie_year_string=str(year_country.replace('\n',"").replace("\xa0","").split("/")[0])
            movie_country_string=str(year_country.replace('\n',"").replace("\xa0","").split("/")[1])
            movie_category_string=str(year_country.replace('\n',"").replace("\xa0","").split("/")[2])
        
            # 演员表中会遇到不完整情况
            try:
                movie_director_string=str(director.replace('\n',"").replace("导演:","").split('\xa0\xa0\xa0')[0]).strip(' ') #strip()方法从字符串中去掉在其左侧和右侧的空格时,括号内单引号里应保留空格
                movie_actor_string = str(director.replace('\n', "").replace("主演:","").split('\xa0\xa0\xa0')[1])
            except Exception as e:
                movie_actor_string="..."

            movie_dict = {"电影排名":rank,"电影名称":movie_name_string,"年份":movie_year_string,"国家":movie_country_string,"类型":movie_category_string,"导演":movie_director_string,"主演":movie_actor_string,"电影评分":grade,"电影评论数":comment_num,"电影短评":short_comment}
            #一次写入一行数据
            writer.writerow(movie_dict)

在这里插入图片描述

异常处理:

我们把可能发生错误的语句放在try模块里,用except来处理异常。每一个try,都必须至少有一个except

# except可以处理一个专门的异常,也可以处理一组圆括号中的异常,如果except后没有指定异常,则默认处理所有的异常
try:
    c = b/ a
    print c
except (IOError ,ZeroDivisionError),x:
    print x
else:
    print "no error"
print "done"

# 无论异常是否发生,在程序结束前,finally中的语句都会被执行
a=10
b=0
try:
    print a/b
except:
    print "error"
finally:
    print "always excute"
  • 4
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值