admin 管理员组

文章数量: 887504

首先给出自己编写的源代码以及对应的运行结果(翻页抓取两页),最后对代码以及网页结构逐次分析。

一、爬虫代码以及运行结果

'''
https://www.douban/doulist/3936288/?start=0&sort=time&playable=0&sub_type=
https://www.douban/doulist/3936288/?start=25&sort=time&playable=0&sub_type=
(1)确定抓取的URL,观察参数的变化规律(目的是进行翻页抓取)
(2)发送请求并获取响应
(3)解析响应
'''
import requests
from lxml import etree
import time

# 单页抓取
# 发送请求
for i in range(2):
    url_base = 'https://www.douban/doulist/3936288/?start={}&sort=time&playable=0&sub_type='.format(i*25)
    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.7',
        'User-Agent':'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/128.0.0.0 Safari/537.36',
        'Referer':'https://www.douban/doulist/3936288/'
    }
    res = requests.get(url=url_base,headers=headers)
    html = etree.HTML(res.content)
    urlSet = html.xpath('//div[@class="title"]/a/@href')#需要跳转才能取到电影的名字
    time.sleep(2)
    for item in urlSet:
        response = requests.get(url=item,headers=headers)
        html = etree.HTML(response.content)
        title = html.xpath('//div/h1/span[1]/text()')[0]
        releaseTime = html.xpath('//div/span[@property="v:initialReleaseDate"][1]/text()')[0]
        runtime = html.xpath('//div/span[@property="v:runtime"]/text()')[0]
        print('电影名称为:',title,',上映时间:',releaseTime,',电影时常',runtime)
        time.sleep(2)
# with open('douban.html','w') as file:
#     file.write(res.content.decode())

二、网页结构分析

我们首先在网页源代码中搜索我们想要爬取的内容,判断是不是异步加载的。如果在网页源码中查找不到对应的内容,需要利用开发者工具中的network抓包,找到真正获取数据的请求,这部分内容后期再讲解。

在源码中存在我们需要的数据,直接利用requests请求该网址链接即可。

接下来,我们要确定请求方法,参数等内容。

该请求是get请求,请求参数为start:25,sort:time,playable:0,sub_type: 实际上也是Payload中的内容

对应的请求

URL = https://www.douban/doulist/3936288/?start=25&sort=time&playable=0&sub_type=

对应的请求可以改写为

URL = https://www.douban/doulist/3936288/
params = {
    "start": 25
    "sort": "time"
    "playable": 0
    "sub_type": 
}

通过对网页的分析我们可以实现该网页内容的抓取,代码如下:

import requests

url = "https://www.douban/doulist/3936288/?start=25&sort=time&playable=0&sub_type="
response = requests.get(url)
print(response.status_code)

此时会返回请求状态码418,因为我们被服务器检测为爬虫程序,也就是被反爬了。这是因为豆瓣的网站对请求头有着严格的检测措施。接下来,我们在程序中增加headers字段,

import requests

url = "https://www.douban/doulist/3936288/?start=25&sort=time&playable=0&sub_type="
headers = {
    'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/128.0.0.0 Safari/537.36'
}
response = requests.get(url=url,headers=headers)
print(response.status_code)

此时请求状态码是200,表明我们已经请求成功。接下来我们说明一下请求参数的作用。在上述的程序中,我们发现url的长度很长,代码显得不够美观,对程序我们可以做如下的改写。运行该程序同样可以得到200的状态码

import requests

url = "https://www.douban/doulist/3936288/"
params = {
    'start':25,
    'sort':'time',
    'playable':0,
    'sub_type':''
}
headers = {
    'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/128.0.0.0 Safari/537.36'
}
response = requests.get(url=url,headers=headers,params=params)
print(response.status_code)

接下来就是实现页面内容的输出和解析。获取页面内容有三种方法:

response.txt该种获取页面内容的方式会自动寻找页面解码的方式,容易出现乱码
response.content.docode()默认采用utf-8解码
response.json()json数据的格式

接下来我们通过指定采用utf-8的解码方式,分别采用response.txt与response.content.decode()获取页面内容。

# 获取页面内容的第一种方式
response.encoding = "utf-8"
print(response.text)

# 获取页面内容的第二种方式
print(response.content.decode('utf-8')) # 指定解码的方式
print(response.content.decode()) 

三、页面内容解析

获取页面内容之后,接下来就是提取我们需要的内容。解析页面的方法有多种,比如通过xpath、css等。我们这里演示通过xpath提取页面内容。正如一开始给的代码中一样,利用第三方库lxml中的etree方法将response.txt的结果转换为html格式,然后利用xpath提取内容。第三方库的安装方法可以参考我之前的笔记爬虫学习02:如何在pycharm上正确安装第三方package-CSDN博客

我更喜欢用parsel这个第三方库实现网页内容提取。

import parsel

# 构建Selector对象
selector = parsel.Selector(response.text)
# 提取自页面的链接地址
urls = selector.xpath('//div[@class="title"]/a/@href').getall()
for u in urls:
    print(u)

'''
子页面的url
https://movie.douban/subject/1292224/
https://movie.douban/subject/1929463/
https://movie.douban/subject/1291552/
https://movie.douban/subject/3742360/
https://movie.douban/subject/1292223/
https://movie.douban/subject/1298624/
https://movie.douban/subject/1299398/
https://movie.douban/subject/1292370/
https://movie.douban/subject/1307914/
https://movie.douban/subject/3442220/
https://movie.douban/subject/1292220/
https://movie.douban/subject/1291858/
https://movie.douban/subject/1306029/
https://movie.douban/subject/1291571/
https://movie.douban/subject/6786002/
https://movie.douban/subject/1291572/
https://movie.douban/subject/1291832/
https://movie.douban/subject/1851857/
https://movie.douban/subject/1652587/
https://movie.douban/subject/1294639/
https://movie.douban/subject/1292365/
https://movie.douban/subject/2131459/
https://movie.douban/subject/2129039/
https://movie.douban/subject/1900841/

'''

提取到子页面的url后,我们利用requests对子页面的url发送请求,解析获得的页面内容,通过xpath提取我们需要的内容。xpath的语法规则将在下一章中总结。

for u in urls:
    response = requests.get(url=u, headers=headers)
    selector = parsel.Selector(response.content.decode())
    title = selector.xpath('//div/h1/span[1]/text()').get()
    releaseTime = selector.xpath('//div/span[@property="v:initialReleaseDate"][1]/text()').get()
    runtime = selector.xpath('//div/span[@property="v:runtime"]/text()').get()
    print('电影名称为:', title, ',上映时间:', releaseTime, ',电影时常', runtime)

最中我们可以得到提取一页内容的爬虫代码。

import requests
import parsel

url = "https://www.douban/doulist/3936288/"
params = {
    'start':25,
    'sort':'time',
    'playable':0,
    'sub_type':''
}
headers = {
    'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/128.0.0.0 Safari/537.36'
}
response = requests.get(url=url,headers=headers,params=params)
# response.encoding = "utf-8"
# print(response.text)
# print(response.content.decode('utf-8'))

# 构建Selector对象
selector = parsel.Selector(response.text)
# 提取自页面的链接地址
urls = selector.xpath('//div[@class="title"]/a/@href').getall()
for u in urls:
    response = requests.get(url=u, headers=headers)
    selector = parsel.Selector(response.content.decode())
    title = selector.xpath('//div/h1/span[1]/text()').get()
    releaseTime = selector.xpath('//div/span[@property="v:initialReleaseDate"][1]/text()').get()
    runtime = selector.xpath('//div/span[@property="v:runtime"]/text()').get()
    print('电影名称为:', title, ',上映时间:', releaseTime, ',电影时常', runtime)

四、实现自动翻页抓取

翻页抓取需要分析每页url的变化规律。

'''
https://www.douban/doulist/3936288/?start=0&sort=time&playable=0&sub_type=
https://www.douban/doulist/3936288/?start=25&sort=time&playable=0&sub_type=
https://www.douban/doulist/3936288/?start=50&sort=time&playable=0&sub_type=
'''
# 前三页的url

这里给出了前三页的url地址,相信大家仔细观察之后能够发现其中的规律。只有start参数从0,25,50,的规律变化。通过此规律,如同文章开头的代码一样,利用for循环变换start参数的取值实现页面的翻页抓取。

我们以另外一种方式实现自动翻页抓取。假设我们不知道具体有多少页,但是通过观察网页结构可知,除最后一页外,每一页都有一个“后一页”的href。href在网页中代表链接。因此,可以通过判断每一页的“后一页”href是否存在来实现翻页查找。

import requests
import parsel
import time
import random

# 定义一个发送网络请求的方法
def get_response(url,headers):
    response = requests.get(url=url,headers=headers)
    return response

# 定义一个解析页面内容的方法
def response_analysis(response):
    # 构建Selector对象
    selector = parsel.Selector(response.text)
    # 提取自页面的链接地址
    urls = selector.xpath('//div[@class="title"]/a/@href').getall()
    # 提取子页面的内容
    for u in urls:
    #     response = requests.get(url=u, headers=headers)
    #     selector = parsel.Selector(response.content.decode())
    #     title = selector.xpath('//div/h1/span[1]/text()').get()
    #     releaseTime = selector.xpath('//div/span[@property="v:initialReleaseDate"][1]/text()').get()
    #     runtime = selector.xpath('//div/span[@property="v:runtime"]/text()').get()
    #     print('电影名称为:', title, ',上映时间:', releaseTime, ',电影时常', runtime)
          print('当前子页面{}信息已经抓取完毕'.format(u))
    # 提取下一页的链接
    next = selector.xpath('//span[@class="next"]/link/@href').get()
    # 返回下一页的链接,如果不存在下一页,返回值为None
    return next


if __name__ == '__main__':
    url = "https://www.douban/doulist/3936288/?start=0&sort=time&playable=0&sub_type="
    headers = {
        'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/128.0.0.0 Safari/537.36'
    }
    res = get_response(url,headers)
    next = response_analysis(res)
    print(next)

    while next:
        res = get_response(url=next, headers=headers)
        next = response_analysis(res)
        print(next)
        time.sleep(random.randint(3,5))

最后一页url的start参数值是225,说明通过while循环实现自动翻页。当抓取到最后一页时,判定对应的href为None,自动结束循环,实现整个网页电影信息的抓取。

本文标签: 爬虫 豆瓣 电影 信息 requests