初学python学习笔记——爬取天猫电影TOP100

我们利用requests库和正则表达式来抓取猫眼电影TOP100的相关内容。requests比urllib使用更加方便,这里就选用正则表达式来作为解析工具。

(1)明确目标

   我们要提取出猫眼电影TOP100的电影名称、时间、评分、图片等信息,提取的站点URL为http://maoyan.com/board/4,提取的结果会以文件形式保存下来。

(2)抓取网页

我们需要抓取的目标站点为http://maoyan.com/board/4,打开之后便可以查看到榜单信息。

初学python学习笔记——爬取天猫电影TOP100_第1张图片

将网页滚动到最下方,可以发现有分页的列表,直接点击第2页,观察页面的URL和内容发生了怎样的变化,如下图所示。

初学python学习笔记——爬取天猫电影TOP100_第2张图片

可以发现页面的URL变成http://maoyan.com/board/4?offset=10,比之前的URL多了一个参数,那就是offset=10,而目前显示的结果是排行11~20名的电影,初步推断这是一个偏移量的参数。再点击下一页,发现页面的URL变成了http://maoyan.com/board/4?offset=20,参数offset变成了20,而显示的结果是排行21~30的电影。

由此可以总结出规律,offset代表偏移量值,如果偏移量为n,则显示的电影序号就是n+1到n+10,每页显示10个。所以,如果想获取TOP100电影,只需要分开请求10次,而10次的offset参数分别设置为0、10、20、…90即可,这样获取不同的页面之后,再用正则表达式提取出相关信息,就可以得到TOP100的所有电影信息了。

(3)抓取首页

接下来用代码实现这个过程。首先抓取第一页的内容。我们实现了get_one_page()方法,并给它传入url参数。然后将抓取的页面结果返回,再通过main()方法调用。初步代码实现如下:

import requests
def get_one_page(url):
    headers = {
        'User-Agent': 'Mozilla/5.0 (Windows NT 6.2; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/68.0.3440.106 Safari/537.36'
    }
    response = requests.get(url, headers=headers)
    if response.status_code == 200:
        return response.text
    return None
def main():
    url = 'http://maoyan.com/board/4'
    html = get_one_page(url)
    print(html)
main()

运行结果(部分内容)

初学python学习笔记——爬取天猫电影TOP100_第3张图片

(4)正则提取

可以看到,一部电影信息对应的源代码是一个dd节点,我们用正则表达式来提取这里面的一些电影信息。

  • 提取它的排名信息

而它的排名信息是在class为board-index的i节点内,这里利用非贪婪匹配来提取i节点内的信息,正则表达式写为:

.*?board-index.*?>(.*?)
  • 提取图片

后面有a节点,其内部有两个img节点。经过检查后发现,第二个img节点的data-src属性是图片的链接。这里提取第二个img节点的data-src属性,正则表达式可以改写如下:

.*?board-index.*?>(.*?).*?data-src="(.*?)"
  • 提取电影名称

电影名称在后面的p节点内,class为name,正则表达式可以改写如下:

.*?board-index.*?>(.*?).*?data-src="(.*?)".*?name.*?a.*?>(.*?)
  • 提取主演名称

.*?board-index.*?>(.*?).*?data-src="(.*?)".*?name.*?a.*?>(.*?).*?star.*?>(.*?)

  • 提取发布时间

.*?board-index.*?>(.*?).*?data-src="(.*?)".*?name.*?a.*?>(.*?).*?star.*?>(.*?)

.*?releasetime.*?>(.*?)

  • 提取分数

注意分数由两部分组成,整数和小数部分,具体正则表达式如下

.*?board-index.*?>(.*?).*?data-src="(.*?)".*?name.*?a.*?>(.*?).*?star.*?>(.*?)

.*?releasetime.*?>(.*?)

.*?integer.*?>(.*?).*?fraction.*?>(.*?).*?

这样一个正则表达式可以匹配一个电影的结果,里面匹配了7个信息。接下来,通过调用findall()方法提取出所有的内容。

接下来,我们再定义解析页面的方法parse_one_page(),主要是通过正则表达式来从结果中提取出我们想要的内容,实现代码如下:

def parse_one_page(html):
    pattern = re.compile(
        '
.*?board-index.*?>(.*?).*?data-src="(.*?)".*?name.*?a.*?>(.*?).*?star.*?>(.*?)

.*?releasetime.*?>(.*?)

.*?integer.*?>(.*?).*?fraction.*?>(.*?).*?
',re.S) items = re.findall(pattern, html) print(items)

最后把这个函数,放在main函数中执行。

def main():
    url = 'http://maoyan.com/board/4'
    html = get_one_page(url)
    parse_one_page(html)

main()

运行结果(部分结果)

以上格式规范,如分数还是两部分,需要进一步规范,把这些数据输入到一个字典中,实现代码如下:

在parse_one_page(html)函数中插入

#整理信息
for item in items:
    yield {
        'index': item[0],
        'image': item[1],
        'title': item[2].strip(),
        'actor': item[3].strip()[3:] if len(item[3]) > 30 else '',
        'time': item[4].strip()[5:] if len(item[4]) > 5 else '',
        'score': item[5].strip() + item[6].strip()
    }

主函数修改为:

def main():
    url = 'http://maoyan.com/board/4'
    html = get_one_page(url)
    for item in parse_one_page(html):
        print(item)
  • 把结果写入到文件中

这里直接写入到一个文本文件中。这里通过JSON库的dumps()方法实现字典的序列化,并指定ensure_ascii参数为False,这样可以保证输出结果是中文形式而不是Unicode编码。代码如下:

   def write_to_json(content):
    with open('result.csv', 'a',encoding='utf-8') as f:
        f.write(json.dumps(content, ensure_ascii=False)+'\n')

main函数改为:

def main():
    url = 'http://maoyan.com/board/4'
    html = get_one_page(url)
    for item in parse_one_page(html):
        write_to_json(item)
  • 分页抓取

因为我们需要抓取的是TOP100的电影,所以还需要遍历一下,给这个链接传入offset参数,实现其他90部电影的爬取,此时添加如下调用即可。

def main(filter):
    ulr='https://movie.douban.com/top250?start='+str(filter)+'&filter='
    html=get_one_page(ulr)
    for item in parse_one_page(html):
        write_to_json(item)
        print(item)

执行语句如下:

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

结果如图【部分结果】:

 

你可能感兴趣的:(python,爬虫)