爬取猫眼top100电影

一、前言

其实爬取页面的思路都差不多,观察爬取页面源码,获取页面内容,根据源码的格式规律将自己需要的内容提取出来,提取后美化输出或者保存!
之前写过了如何爬取淘宝和京东的评论,其实这个可以不写的!!但是又遇到坑了所以还是写下来,记录一下错误!!

二、代码与问题

先上代码再说一下自己遇到的问题!

# -*- coding:utf-8 -*-
import requests
from requests.exceptions import RequestException
import re
import json
import time
from multiprocessing import Pool

"""
url= 'https://maoyan.com/board/4'
repsponse = requests.get(url)
print(repsponse.headers['content-type'])
print(repsponse.encoding)#response内容的编码
print(repsponse.apparent_encoding)#response headers里设置的编码
print(requests.utils.get_encodings_from_content(repsponse.text))#response返回的html header标签里设置的编码


"""
def get_url(url):
    try:
        #说明headers信息,不然一下就403错误了!
        heards = {'user-agent':'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.108 Safari/537.36'}
        #获取页面信息
        response = requests.get(url,headers=heards)
        #页面返回的status_code码为200则是爬取成功
        if response.status_code == 200:
            #声明页面返回内容的编码格式,不然一般是ISO-8859-1,就乱码了
            response.encoding = 'utf-8'
            return response.text
        return print("爬取失败")
    except RequestException:
        return print("爬取失败")

def parge_html(html):
    #编写正则表达式的格式
    #compile() 函数将一个字符串编译为字节代码
    pattern = re.compile('<dd>.*?board-index.*?(\d+).*?name.*?<a.*?>(.*?)</a>.*?star">(.*?)</p>.*?releasetime">'
                         +'(.*?)</p>.*?integer">(.*?)</i>.*?fraction">(\d+)</i>.*?</dd>',re.S)
    #利用正则表达式获取需要的内容
    items = re.findall(pattern,html)
    #print(items)
    #将内容转化为一个字典使其更容易观看
    for item in items:
        yield{
            'index':item[0],
            'name':item[1],
            'star':item[2].strip()[3:],    #strip() 方法用于移除字符串头尾指定的字符(默认为空格或换行符)或字符序列。
            'time':item[3][5:],
            'score':item[4]+item[5]
        }
        
def write_to_file(content):
    with open('result1.txt', 'a', encoding='utf-8') as f:
        #ensure_ascii=False,说明输出的内容不要用ASCII编码,这样结果才是中文
        f.write(json.dumps(content,ensure_ascii=False) + '\n')    #利用json.dumps将字典转为字符串
        f.close()

def main(offset):
    #切换页面观察URL的变化
    url  = 'https://maoyan.com/board/4?offset=' + str(offset)
    html = get_url(url)
    for item in parge_html(html):
        print(item)
        write_to_file(item)
    #print(html)

if __name__ == "__main__":
    #单线程爬取
    """
    for i in range(10):
        time.sleep(10)
        main(i*10)
    """
    #多线程
    pool = Pool(processes = 10)    #默认的话进程数为cpu_count()的值
    pool.map(main,[i*10 for i in range(10)])
问题1:

我最开始写的是爬取一页的电影内容,没有用正则表达式转化提取,但是输出的内容是乱码的!
既然乱码就是编码问题了,由于我是已经声明utf-8的编码模式了,我以为是软件问题,我是用pycharm(第一次用我也不知道它初始编码是什么,之前一直用Spyder),我查了一下怎么修改pycharm的编码,file—>settings—>Editor—>File Encoding,一看那里有一个是gbk,我就都改为了utf-8!

image.png

但是重新输出后还是乱码!!
在网上找了好久,终于看到有一篇说到点了,其他大部分要么教我修改pycharm编码要么在程序一开始声明utf-8但是都没用!
原来是因为在你调用Response.text时对响应进行解码,如果http头部有声明则基本上按声明进行解码,没用它就会猜!使用默认的 ISO-8859-1解码,有时http头部声明了也还是按照这个解码!

print(repsponse.encoding)#response内容的编码
print(repsponse.apparent_encoding)#response headers里设置的编码
print(requests.utils.get_encodings_from_content(repsponse.text))#response返回的html header标签里设置的编码

可以输入上面的代码看一下是不是编码出问题,我的输出是:ISO-8859-1,utf-8,utf-8请求返回的内容变成了ISO-8859-1肯定乱码!
可以在获取内容后先输入:

response.encoding = 'utf-8'

声明请求返回内容是utf-8编码。

问题2:

问题1解决后我又爬了一次!这次没有乱码,但是因为我在调整编码的时候一直测试一直爬,猫眼觉得我的请求很可疑!禁止了我的请求,出现了403错误!
这个通过增加一个头部信息就好了,之前淘宝比较严格,头部信息比较多。这次就加了一个请求的浏览器类型就可以了!

问题3:

问题2解决后,我接着完善,刚刚是爬取一页,现在是十页!但是又出问题了爬的太频繁太快被要求验证身份了,也就是类似拼图,但是我爬取的内容还没完呢!少了一页,所以我又加了睡眠信息,每十秒爬一次,终于成功了!这是单线程!

接下来是多线程爬取:多线程一般默认是cpu_count()数,我的是8,但是我自己定义开了十个进程。
天下武功唯快不破!!!用了十个进程秒爬,估计猫眼没反应过来,最后爬取内容缺了一个而已!
但是多线程有一个缺点,就是爬取的内容不是按顺序的,本来是top100的电影从1-100,多线程的话内容有点乱!但是问题不大,因为它很快就好了。

参考:https://www.bilibili.com/video/BV1Si4y1s7S4?p=14
https://www.runoob.com/python/python-func-compile.html
https://www.runoob.com/python/att-string-strip.html
https://www.cnblogs.com/biangbiang/archive/2013/02/19/2916780.html
https://blog.csdn.net/a491057947/article/details/47292923
https://blog.csdn.net/weixin_43877278/article/details/103880644

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。