豆瓣电影爬取

豆瓣电影爬取遇到的问题–状态码418

使用requests库的get方法获取豆瓣电影的响应,结果返回的是None,打印状态码一看是418,一般以4开头的HTTP状态码都是请求错误:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-RPJMQxP8-1580745016435)(C:\Users\86152\AppData\Roaming\Typora\typora-user-images\image-20200203115813169.png)]

RFC2324中出现:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-VV6xb9PV-1580744743216)(C:\Users\86152\AppData\Roaming\Typora\typora-user-images\image-20200203120439879.png)]

任何尝试用茶壶冲泡咖啡的尝试都将导致错误代码“ 418我是茶壶”。生成的实体主体可能短而结实。

这听起来有些奇怪。

418 I’m a teapot: 这个响应状态码是在1998年定义的,是传统的IETF愚人节笑话之一。

一个笑话。。。

这应该是服务器的反爬虫措施,检测到爬虫就返回一个418.

要知道搜索引擎本质上也是一个爬虫,而我们在做的只是低配版的而已,浏览器里通过开发者模式可以看到有用户代理,头等信息,那么我们也使用requests库来添加用户代理来尝试一下。

解决418

# 豆瓣电影爬取
url = 'https://movie.douban.com/top250'
# 用于模拟http头的User-agent
user_list = (
    {'user-agent': "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv2.0.1) Gecko/20100101 Firefox/4.0.1"},
    {'user-agent': "Mozilla/5.0 (Windows NT 6.1; rv2.0.1) Gecko/20100101 Firefox/4.0.1"},
    {'user-agent': "Opera/9.80 (Macintosh; Intel Mac OS X 10.6.8; U; en) Presto/2.8.131 Version/11.11"},
    {'user-agent': "Opera/9.80 (Windows NT 6.1; U; en) Presto/2.8.131 Version/11.11"},
    {'user-agent': "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_7_0) AppleWebKit/535.11 (KHTML, like Gecko) Chrome/17.0.963.56 Safari/535.11"}
)
user_agent = random.choice(user_list)
response = requests.get(url, headers=user_agent)

构造用户代理元组,每次使用随即数选取一个代理,在get方法中填入用户代理。

random.choice()解析:

Choose a random element from a non-empty sequence.

从非空序列中选取一个随机元素。

打印看下结果(部分):

print(response.status_code)
print(response.text)
200
<!DOCTYPE html>
<html lang="zh-cmn-Hans" class="ua-mac ua-webkit">
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
    <meta name="renderer" content="webkit">
    <meta name="referrer" content="always">
    <meta name="google-site-verification" content="ok0wCgT20tBBgo9_zat2iAcimtN4Ftf5ccsh092Xeyw" />

问题解决了。

正文开始,爬取豆瓣电影

我们需要使用bs4和requests库,没有的直接装一下:

pip install -U bs4 -i "https://pypi.doubanio.com/simple/"
pip install -U requests -i "https://pypi.doubanio.com/simple/"

用的源是豆瓣的,下载速度比较快。

代码,python3.7测试可以了:

"""
:copyright: (c) 2020 by 人生苦短.
"""

import sys
from bs4 import BeautifulSoup
import requests
import random
import re
import xlsxwriter
# 豆瓣电影爬取

# 获取http响应
def get_url(url):
    # 用于模拟http头的User-agent
    user_list = (
        {'user-agent': "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv2.0.1) Gecko/20100101 Firefox/4.0.1"},
        {'user-agent': "Mozilla/5.0 (Windows NT 6.1; rv2.0.1) Gecko/20100101 Firefox/4.0.1"},
        {'user-agent': "Opera/9.80 (Macintosh; Intel Mac OS X 10.6.8; U; en) Presto/2.8.131 Version/11.11"},
        {'user-agent': "Opera/9.80 (Windows NT 6.1; U; en) Presto/2.8.131 Version/11.11"},
        {'user-agent': "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_7_0) AppleWebKit/535.11 (KHTML, like Gecko) Chrome/17.0.963.56 Safari/535.11"}
    )
    user_agent = random.choice(user_list)	# 随机选择一个代理
    response = requests.get(url, headers=user_agent)	# get()方法请求响应
    return response.text

# 获取每页的数据
def get_data(html):
    data, page_data = [], []
    # 获取 1-电影详情链接 2-图片链接 3-影片中文名 4-影片外国名 5-评分 6-评价数 7-概况 8-相关信息
    soup = BeautifulSoup(html, 'html.parser')
    for item in soup.select('ol li'):
        item = str(item)
        soup_sub = BeautifulSoup(item, 'html.parser')
        links = soup_sub.select('div div.pic a')[0]['href']  # 1-电影详情链接
        data.append(links)
        pictures = soup_sub.select('div div.pic a img')[0]['src']  # 2-图片链接
        data.append(pictures)
        names = soup_sub.find_all('span', class_='title')       # 3-4 电影名
        if 2 == len(names):
            cname = names[0].string             # 3-中文名
            ename = names[1].string.replace('/', '').lstrip()             # 4-英文名
        else:
            cname = names[0].string
            ename = ''
        data.append(cname)
        data.append(ename)
        scores = soup_sub.select('div div.bd div span.rating_num')[0].string  # 5-评分
        data.append(scores)
        judges = soup_sub.find_all('span', string=re.compile(r'(\d*)人评价'))[0].string  # 6-评价数
        judges = judges.replace("人评价", "")
        data.append(judges)
        contents = soup_sub.select('span.inq')[0].string  # 7-概况
        data.append(contents)
        infos = soup_sub.find_all('p', attrs={'class': ""})[0].get_text()  # 8-相关信息
        infos = infos.replace('\n', '').replace(' ', '')
        data.append(infos)
        page_data.append(data[:])
        data.clear()
    return page_data

# 保存数据
def save_data(all_data):
    col, row = 0, 0
    with xlsxwriter.Workbook('top250.xlsx') as workbook:
        bold = workbook.add_format({'bold': True})
        worksheet = workbook.add_worksheet('movie')
        col_name = ('电影详情链接', '图片链接', '影片中文名', '影片外国名', '评分', '评价数', '概况', '相关信息')
        worksheet.write_row('A1', col_name, bold)
        for data in all_data:
            for page_data in data:
                row += 1
                worksheet.write_row(row, col, page_data)

# 获取所有页的数据
def traverse_page(url):
    print('正在下载到EXCEL文件里...')
    data = []
    sub_url = ''
    while True:
        html = get_url(url)
        soup = BeautifulSoup(html, 'html.parser')
        data.append(get_data(html))
        print('len =', len(data))
        try:
            sub_url = soup.select('span.next a').pop()['href']
            if sub_url:
                url = 'https://movie.douban.com/top250' + sub_url
                continue
            else:
                break
        except IndexError:
            save_data(data)
            print('下载完成')
            return


def main():
    url = 'https://movie.douban.com/top250'
    html = get_url(url)
    traverse_page(url)


if __name__ == '__main__':
    main()
发布了12 篇原创文章 · 获赞 0 · 访问量 288

猜你喜欢

转载自blog.csdn.net/ASCE_S/article/details/104163716