Python 抓取豆瓣电影 Top250 的电影名称

77 阅读2分钟

import requests from bs4 import BeautifulSoup for i in range(0,9): url=f'movie.douban.com/top250?star…' Headers={ "User-Agent":("Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/139.0.0.0 Safari/537.36"), "Accept-Language":"zh-CN,zh;q=0.9,en;q=0.8", "Referer": "movie.douban.com/top250" } s=requests.Session() s.headers.update(Headers) s.trust_env=False r=s.get(url,timeout=(4,10)).text soup=BeautifulSoup(r,"html.parser") lis=soup.select("#content div.article ol li") for idx,f in enumerate(lis,start=1+i*25): movie=f.select_one(" div div.info div.hd a span:nth-child(1)") print(idx,movie.get_text(strip=True)) 我这样写行不行,playwright 又是什么,从来没有听到过

ChatGPT 说:

已思考 19s

燎然,你这版思路对,但有 4 个细节需要改一下:

  1. range(0,9) 只抓 9 页(225 条),Top250 有 10 页 → 用 range(0,10)

  2. 不要在循环里反复新建 Session(),放到外面用同一个会更稳更快

  3. 选择器用 :nth-of-type(1):nth-child(1) 更稳(避免被文本节点干扰)

  4. select_one(...) 可能拿不到元素,要判空;另外你写的选择器前面的空格和冗余层级可以简化

✅ 修正后的 requests 版本(推荐)

import time
import requests
from bs4 import BeautifulSoup

BASE = "https://movie.douban.com/top250"
headers = {
    "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/139.0.0.0 Safari/537.36",
    "Accept-Language": "zh-CN,zh;q=0.9,en;q=0.8",
    "Referer": BASE,
}

s = requests.Session()
s.headers.update(headers)
s.trust_env = False

for page in range(0, 10):  # 0..9 共10页 = 250部
    url = f"{BASE}?start={page*25}&filter="
    html = s.get(url, timeout=(6, 15)).text
    soup = BeautifulSoup(html, "html.parser")

    lis = soup.select("#content div.article ol li")
    for idx, li in enumerate(lis, start=1 + page*25):
        # 只取中文名 = 标题里的第一个 span
        el = li.select_one("div.info > div.hd > a > span:nth-of-type(1)")
        if el:
            print(idx, el.get_text(strip=True))

    time.sleep(1.2)  # 留点间隔,减轻风控

说明:

  • 选择器简化为相对路径,且用了 :nth-of-type(1)

  • start=1 + page*25 让序号跨页递增;

  • 如果你还想抓评分/年份/评价人数,也是在 li 里继续 select_one(...) 取即可。

🧭 Playwright 是什么?

Playwright 是微软出的浏览器自动化库(和 Selenium 类似,但更现代、更稳):

  • 支持 Chromium/Firefox/WebKit 三大内核

  • 自带智能等待(元素出现/网络空闲),不容易“还没渲染好就找元素报错”

  • API 简洁、稳定,适合需要“真的点按钮、滚动加载、登录后才能看”的场景

怎么装?

pip install playwright
python -m playwright install

用 Playwright “点下一页”的最小示例

from playwright.sync_api import sync_playwright

with sync_playwright() as p:
    browser = p.chromium.launch(headless=False)
    page = browser.new_page()
    page.goto("https://movie.douban.com/top250")

    all_titles = []
    while True:
        page.wait_for_selector("#content div.article ol li")
        for li in page.locator("#content div.article ol li").all():
            t = li.locator("div.info >> div.hd >> a >> span:nth-of-type(1)").inner_text().strip()
            all_titles.append(t)
        # 尝试点“下一页”
        next_btn = page.locator("#content div.article div.paginator span.next > a")
        if next_btn.count() == 0:
            break
        next_btn.click()

    print(len(all_titles), all_titles[:5])
    browser.close()

实话实说

  • 这种可用参数翻页的场景(?start=0,25,50...),首选 requests,更快、更稳。

  • 只有在必须执行 JS(滚动加载、验证码、复杂登录)时,才上 Playwright/Selenium。

  • 豆瓣有一定风控,真被限了就:放慢(sleep 随机 1.5~3s)、换时间段、或用代理。