潘景

Request+正则表达式爬取猫眼电影
目标通过Request+正则表达式爬取猫眼电影TOP100电影的排名、名字、电影封面图片、主演、上映时间、猫眼评分...
扫描右侧二维码阅读全文
01
2018/10

Request+正则表达式爬取猫眼电影

目标

通过Request+正则表达式爬取猫眼电影TOP100电影的排名、名字、电影封面图片、主演、上映时间、猫眼评分,将爬取的内容写入文件中。

流程框架

进入到猫眼电影TOP100的页面,此时的URL为http://maoyan.com/board/4,点击第2页,会发现此时的URL为http://maoyan.com/board/4?offset=10,点击第3页,会发现URL变成了http://maoyan.com/board/4?offset=20,由此可以推断出offset参数为偏移量,如果偏移量为n,则显示电影序号就是n+1到n+10,每页显示10个,所以,如果想获取TOP100电影,只需要分开请求10次,而10次的offset参数分别设置为0、10、20......90即可,这样获取不同的页面之后,再用正则表达式提取出相关信息,就可以得到TOP100的所有电影信息了。获取信息后,可以将信息写入txt文件,当然可以存入数据库(此处为了偷懒,就不存入数据库了)。为了加快爬取网页的速度,可以开启循环和多线程(当需要爬取的信息很大时,这是一个不错的技巧)。

下图展示了具体的流程框架:

(1)抓取单页内容

# 获取单个页面的HTML代码
def get_one_page(url):
    try:
        # 此处如果不加headers进行伪装,将会返回403错误(拒绝访问)
        headers = {
            "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/54.0.2840.99 Safari/537.36"
        }
        response = requests.get(url, headers = headers)
        # 如果返回的状态码是200,表示请求正常,返回页面HTML代码
        # 否则,返回None
        if response.status_code == 200:
            return response.text
        return None
    except RequestException:
        return None

接下来测试一下是否可以获取页面内容:

if __name__ == '__main__':
    url = 'http://maoyan.com/board/4'
    html = get_one_page(url)
    print(html)

(2)正则表达式分析

可以对get_one_page(url)函数爬取的HTML代码进行分析(此处为了方便观看,直接在浏览器控制台分析),利用正则表达式获取到有用的信息(电影的排名、名字、电影封面图片、主演、上映时间、猫眼评分)。

# 解析单个页面的HTML代码,利用re模块提取出有效信息
def parse_one_page(html):
    # re.S:表示“.”的作用扩展到整个字符串,包括“\n”
    pattern = re.compile('<dd>.*?board-index.*?>(\d+)</i>.*?data-src="(.*?)".*?name"><a'
                +'.*?>(.*?)</a>.*?star">(.*?)</p>.*?releasetime">(.*?)</p>.*?integer">'
                +'(.*?)</i>.*?fraction">(.*?)</i>.*?</dd>', re.S)
    items = re.findall(pattern, html)
    for item in items:
        # 构造生成器函数
        yield{
            'index': item[0],
            'image': item[1],
            'title': item[2],
            'actor': item[3].strip()[3:],
            'time': item[4].strip()[5:],
            'score': item[5]+item[6]
        }

接下来测试一下是否可以得到我们想要的内容:

if __name__ == '__main__':
    url = 'http://maoyan.com/board/4'
    html = get_one_page(url)
    items = parse_one_page(html)
    for item in items:
        print(item)

控制台输出如下:

单个页面信息解析正确,那么,想要获得多个页面的信息,只需写一个循环遍历即可:

def main(offset):
    url = 'http://maoyan.com/board/4?offset=' + str(offset)
    html = get_one_page(url)
    for item in parse_one_page(html):
        print(item)

if __name__ == '__main__':
    for i in range(10):
        main(i*10)

(3)保存至文件

只需写一个简单的函数即可完成,但此处需要注意一点,为保证输出文件为中文,在读写文件时要添加参数endcoding="utf-8"

# 将解析出的内容写入文件
def write_to_file(content):
    # 添加endcoding="utf-8"确保输出到文件中为中文
    with open('result.txt', 'a', encoding='utf-8 ') as f:
        # 此处建议将解析出的内容编码为json格式再写入文件,json的好处在此不过多叙述
        # 如果使用了json进行编码,务必添加参数ensure_ascii=False确保编码数据为中文
        # json.dumps():编码json数据
        f.write(json.dumps(content, ensure_ascii=False) + '\n')
        f.close()

运行代码,目标信息被写入result.txt文件中:

(4)开启循环及多线程

为了加快页面爬取速度,可以使用多线程(针对大量数据时非常有效)。

if __name__ == '__main__':
    pool = Pool()
    pool.map(main, [i*10 for i in range(10)])

项目完整代码已托管到github:https://github.com/panjings/python-spider

Last modification:March 8th, 2019 at 03:44 pm
If you think my article is useful to you, please feel free to appreciate

Leave a Comment