爬取豆瓣电影TOP250
我们要爬取的网址:https://movie.douban.com/top250
我们要爬取的内容是250部电影的基本信息:排名、电影名、导演、年份、评分;爬取后将这些电影的信息保存在一个csv文件中。
将页面滑到底部,可以看到一共10页,所以我们需要爬取一个页面,然后重复10次,每次爬取的方法相同,不同的是网址的某个参数。
1.使用requests库爬取页面源代码
这一步很简单,不需要登录,也不需要重新构造headers。
def getPage(url): try: headers = {'user-agent': 'Mozilla/5.0'} r = requests.get(url, headers=headers) return r.text except: print("爬取失败")
2.解析页面源代码
- 使用正则表达式对源代码进行解析:
pattern1 = re.compile('<em class="">(.*?)</em>', re.S)#排名 mov_list = re.findall(pattern1, html) pattern2 = re.compile('<img width="100" alt="(.*?)"', re.S)#电影名 mov_name = re.findall(pattern2, html) pattern3 = re.compile('导演:(.*?)&', re.S)#导演名 mov_d = re.findall(pattern3, html) pattern5 = re.compile('<br>\n(.*?)&', re.S)#上映时间 mov_year = re.findall(pattern5, html) pattern6 = re.compile('average">(.*?)</span>', re.S)#评分 mov_score=re.findall(pattern6, html) pattern7 = re.compile('"inq">(.*?)</span>', re.S)#评价 mov_review=re.findall(pattern7, html)
- 将这些内容保存到一个列表中,再将这个列表保存到一个全局列表(注意是全局列表,因为后边要将列表中的元素存入csv文件)
for i in range(25): is_item = [] is_item.append(mov_list[i]) is_item.append(mov_name[i]) is_item.append(mov_d[i]) #is_item.append(mov_zy[i]) is_item.append(mov_year[i]) is_item.append(mov_score[i]) is_item.append(mov_review) is_page.append(is_item)
3.分页操作
这250部电影分别保存在10个页面中,观察每一个页面的url可以发现:
这是前三页的URL,可以发现每次变化的只有start对应的值,所以我们可以通过改变start的值来构造网页的页数变化;
url = "https://movie.douban.com/top250?start=" + str(offset) + "&filter=" if __name__ == '__main__': for i in range(10): main(offset=i * 25) time.sleep(1)
4.保存到csv文件
使用pandas库的DataFrame方法进行保存,由于to_csv()方法每调用一次,就会重新生成一个新的文件,这样在运行的时候,由于分页操作使得最终csv文件保存的是最后一页的内容,而不是全局内容,所以应定义一个全局列表,在爬取每一页信息的时候将每一部电影的内容分别保存 到列表中,最后全部页面遍历完成后再将这个全局列表中的内容整体保存到文件中。
columns=['排名','电影名','导演','上映时间','评分','评价'] save_file=pd.DataFrame(columns=columns,data=ls_page) save_file.to_csv('douban1.csv', index=False, encoding="utf-8")
完整代码
import requests
import re
import time
import pandas as pd
is_page=[]
def getPage(url):
try:
headers = {'user-agent': 'Mozilla/5.0'}
r = requests.get(url, headers=headers)
return r.text
except:
print("爬取失败")
def parse_one_page(html):
pattern1 = re.compile('<em class="">(.*?)</em>', re.S)#排名
mov_list = re.findall(pattern1, html)
pattern2 = re.compile('<img width="100" alt="(.*?)"', re.S)#电影名
mov_name = re.findall(pattern2, html)
pattern3 = re.compile('导演:(.*?)&', re.S)#导演名
mov_d = re.findall(pattern3, html)
pattern5 = re.compile('<br>\n(.*?)&', re.S)#上映时间
mov_year = re.findall(pattern5, html)
pattern6 = re.compile('average">(.*?)</span>', re.S)#评分
mov_score=re.findall(pattern6, html)
pattern7 = re.compile('"inq">(.*?)</span>', re.S)#评价
mov_review=re.findall(pattern7, html)
for i in range(25):
is_item = []
is_item.append(mov_list[i])
is_item.append(mov_name[i])
is_item.append(mov_d[i])
#is_item.append(mov_zy[i])
is_item.append(mov_year[i])
is_item.append(mov_score[i])
is_item.append(mov_review)
is_page.append(is_item)
return is_page
def process_data(ls_page):
columns=['排名','电影名','导演','上映时间','评分','评价']
save_file=pd.DataFrame(columns=columns,data=ls_page)
save_file.to_csv('douban1.csv', index=False, encoding="utf-8")
def main(offset):
url = "https://movie.douban.com/top250?start=" + str(offset) + "&filter="
html = getPage(url)
data=parse_one_page(html)
if __name__ == '__main__':
for i in range(10):
main(offset=i * 25)
time.sleep(1)
process_data(is_page)