python用requests和xpath爬取豆瓣电影

这篇文章我们将使用 requests 和 xpath 爬取豆瓣电影 Top250,下面先贴上最终的效果图:

image

1、网页分析

(1)分析 URL 规律

我们首先使用 Chrome 浏览器打开 豆瓣电影 Top250,很容易可以判断出网站是一个静态网页

然后我们分析网站的 URL 规律,以便于通过构造 URL 获取网站中所有网页的内容

首页:https://movie.douban.com/top250

第二页:https://movie.douban.com/top250?start=25&filter=

第三页:https://movie.douban.com/top250?start=50&filter=

不难发现,URL 可以泛化为 https://movie.douban.com/top250?start={page}&filter=,其中,page 代表页数

最后我们还需要验证一下首页的 URL 是否也满足规律,经过验证,很容易可以发现首页的 URL 也满足上面的规律

image

核心代码如下:

import requests
# 获取网页源代码
def get_page(url):
    # 构造请求头部
    headers = {
        'USER-AGENT':'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/67.0.3396.99 Safari/537.36'
    }
    # 发送请求,获得响应
    response = requests.get(url=url,headers=headers)
    # 获得网页源代码
    html = response.text
    # 返回网页源代码
    return html
(2)分析内容规律

接下来我们开始分析每一个网页的内容,并从中提取出需要的数据

使用快捷键 Ctrl+Shift+I 打开开发者工具,选中 Elements 选项栏分析网页的源代码

需要提取的数据包括(可以使用 xpath 进行匹配):

  • 详细链接:html.xpath('//div[@class="hd"]/a/@href')
  • 电影名称:html.xpath('//div[@class="hd"]/a/span[1]/text()')
  • 导演/主演、上映年份/国家/分类:html.xpath('//div[@class="bd"]/p[1]//text()')
  • 豆瓣评分:html.xpath('//div[@class="bd"]/div/span[2]/text()')
  • 评价人数:html.xpath('//div[@class="bd"]/div/span[4]/text()')

image
核心代码如下:

from lxml import etree
# 解析网页源代码
def parse_page(html):
    # 构造 _Element 对象
    html_elem = etree.HTML(html)
    # 详细链接
    links = html_elem.xpath('//div[@class="hd"]/a/@href')
    # 电影名称
    titles = html_elem.xpath('//div[@class="hd"]/a/span[1]/text()')
    # 电影信息(导演/主演、上映年份/国家/分类)
    infos = html_elem.xpath('//div[@class="bd"]/p[1]//text()')
    roles = [j for i,j in enumerate(infos) if i % 2 == 0]
    descritions = [j for i,j in enumerate(infos) if i % 2 != 0]
    # 豆瓣评分
    stars = html_elem.xpath('//div[@class="bd"]/div/span[2]/text()')
    # 评论人数
    comments = html_elem.xpath('//div[@class="bd"]/div/span[4]/text()')
    # 获得结果
    data = zip(links,titles,roles,descritions,stars,comments)
    # 返回结果
    return data

(3)保存数据
下面将数据分别保存为 txt 文件、json 文件和 csv 文件

import json
import csv
# 打开文件
def openfile(fm):
    fd = None
    if fm == 'txt':
        fd = open('douban.txt','w',encoding='utf-8')
    elif fm == 'json':
        fd = open('douban.json','w',encoding='utf-8')
    elif fm == 'csv':
        fd = open('douban.csv','w',encoding='utf-8',newline='')
    return fd

# 将数据保存到文件
def save2file(fm,fd,data):
    if fm == 'txt':
        for item in data:
            fd.write('----------------------------------------\n')
            fd.write('link:' + str(item[0]) + '\n')
            fd.write('title:' + str(item[1]) + '\n')
            fd.write('role:' + str(item[2]) + '\n')
            fd.write('descrition:' + str(item[3]) + '\n')
            fd.write('star:' + str(item[4]) + '\n')
            fd.write('comment:' + str(item[5]) + '\n')
    if fm == 'json':
        temp = ('link','title','role','descrition','star','comment')
        for item in data:
            json.dump(dict(zip(temp,item)),fd,ensure_ascii=False)
    if fm == 'csv':
        writer = csv.writer(fd)
        for item in data:
            writer.writerow(item)

2、编码实现
下面是完整代码,也是几十行可以写完

import requests
from lxml import etree
import json
import csv
import time
import random
'''
遇到不懂的问题?Python学习交流群:1136201545满足你的需求,资料都已经上传群文件,可以自行下载!
'''
# 获取网页源代码
def get_page(url):
    headers = {
        'USER-AGENT':'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/67.0.3396.99 Safari/537.36'
    }
    response = requests.get(url=url,headers=headers)
    html = response.text
    return html

# 解析网页源代码
def parse_page(html):
    html_elem = etree.HTML(html)
    links = html_elem.xpath('//div[@class="hd"]/a/@href')
    titles = html_elem.xpath('//div[@class="hd"]/a/span[1]/text()')
    infos = html_elem.xpath('//div[@class="bd"]/p[1]//text()')
    roles = [j.strip() for i,j in enumerate(infos) if i % 2 == 0]
    descritions = [j.strip() for i,j in enumerate(infos) if i % 2 != 0]
    stars = html_elem.xpath('//div[@class="bd"]/div/span[2]/text()')
    comments = html_elem.xpath('//div[@class="bd"]/div/span[4]/text()')
    data = zip(links,titles,roles,descritions,stars,comments)
    return data

# 打开文件
def openfile(fm):
    fd = None
    if fm == 'txt':
        fd = open('douban.txt','w',encoding='utf-8')
    elif fm == 'json':
        fd = open('douban.json','w',encoding='utf-8')
    elif fm == 'csv':
        fd = open('douban.csv','w',encoding='utf-8',newline='')
    return fd

# 将数据保存到文件
def save2file(fm,fd,data):
    if fm == 'txt':
        for item in data:
            fd.write('----------------------------------------\n')
            fd.write('link:' + str(item[0]) + '\n')
            fd.write('title:' + str(item[1]) + '\n')
            fd.write('role:' + str(item[2]) + '\n')
            fd.write('descrition:' + str(item[3]) + '\n')
            fd.write('star:' + str(item[4]) + '\n')
            fd.write('comment:' + str(item[5]) + '\n')
    if fm == 'json':
        temp = ('link','title','role','descrition','star','comment')
        for item in data:
            json.dump(dict(zip(temp,item)),fd,ensure_ascii=False)
    if fm == 'csv':
        writer = csv.writer(fd)
        for item in data:
            writer.writerow(item)

# 开始爬取网页
def crawl():
    url = 'https://movie.douban.com/top250?start={page}&filter='
    fm = input('请输入文件保存格式(txt、json、csv):')
    while fm!='txt' and fm!='json' and fm!='csv':
        fm = input('输入错误,请重新输入文件保存格式(txt、json、csv):')
    fd = openfile(fm)
    print('开始爬取')
    for page in range(0,250,25):
        print('正在爬取第 ' + str(page+1) + ' 页至第 ' + str(page+25) + ' 页......')
        html = get_page(url.format(page=str(page)))
        data = parse_page(html)
        save2file(fm,fd,data)
        time.sleep(random.random())
    fd.close()
    print('结束爬取')

if __name__ == '__main__':
    crawl()
以下是用Pythonrequestsxpath和正则表达式爬取豆瓣电影top250详情页的代码: ```python import requests from lxml import etree import re def get_movie_details(url): # 发送请求获取页面内容 response = requests.get(url) html = response.content.decode('utf-8') # 解析页面内容 selector = etree.HTML(html) # 获取电影名称 movie_name = selector.xpath('//h1/span/text()')[0] # 获取导演和主演信息 director_and_cast = selector.xpath('//div[@id="info"]/span[1]/span[@class="attrs"]/a/text()') director = director_and_cast[0] cast = director_and_cast[1:] # 获取上映年份、地区、类型 year_country_type = selector.xpath('//div[@id="info"]/text()') year = re.findall('\d{4}', year_country_type[1])[0] country = year_country_type[2].strip().split('/')[0] type = year_country_type[2].strip().split('/')[-1] # 获取评分和评价人数 rating = selector.xpath('//strong[@class="ll rating_num"]/text()')[0] rating_num = selector.xpath('//div[@class="rating_sum"]/a/span/text()')[0] # 获取电影简介 summary = selector.xpath('//div[@class="indent"]/span[@class="all hidden"]/text()')[0] # 构造电影信息字典 movie_info = { '名称': movie_name, '导演': director, '主演': cast, '年份': year, '地区': country, '类型': type, '评分': rating, '评价人数': rating_num, '简介': summary.strip(), } return movie_info if __name__ == '__main__': urls = ['https://movie.douban.com/top250?start={}'.format(i) for i in range(0, 250, 25)] for url in urls: response = requests.get(url) html = response.content.decode('utf-8') selector = etree.HTML(html) # 获取电影详情页链接 movie_links = selector.xpath('//div[@class="hd"]/a/@href') for link in movie_links: movie_info = get_movie_details(link) print(movie_info) ``` 这段代码会爬取豆瓣电影top250列表页面中每部电影的详情页,并从详情页中提取电影名称、导演和主演、上映年份、地区、类型、评分、评价人数、电影简介等信息,并打印出来。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值