爬虫实战 - 爬取豆瓣top250
1 from bs4 import BeautifulSoup 2 import urllib.request 3 import urllib.parse 4 import urllib.error 5 import xlwt 6 import re 7 8 9 # Excel文件保存路径 10 save_path = '豆瓣Top250.xls' 11 12 # headers数据包 13 head_package = {} 14 head_package[ 15 'User-Agent'] = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.82 Safari/537.36' 16 # head_package['Cookie'] = 'll="118226"; bid=Qfmj76DkrD8; __utmv=30149280.20459; douban-profile-remind=1; gr_user_id=a58b8c23-ff09-4e14-91d7-599fd84a9682; _vwo_uuid_v2=D007BD5CC7E89E79A31FD5B37908B75EB|9cfed6ff673a9ef600e186fcb321944d; douban-fav-remind=1; viewed="3671502"; _vwo_uuid_v2=D007BD5CC7E89E79A31FD5B37908B75EB|9cfed6ff673a9ef600e186fcb321944d; ap_v=0,6.0; __utmc=30149280; __utmz=30149280.1618040804.22.19.utmcsr=douban.com|utmccn=(referral)|utmcmd=referral|utmcct=/; __utmc=223695111; __utmz=223695111.1618040804.3.3.utmcsr=douban.com|utmccn=(referral)|utmcmd=referral|utmcct=/; __utma=30149280.756924018.1591256763.1618040804.1618043277.23; __utmb=30149280.0.10.1618043277; __utma=223695111.748862546.1609985591.1618040804.1618043277.4; __utmb=223695111.0.10.1618043277; _pk_ref.100001.4cf6=["","",1618043277,"https://www.douban.com/"]; _pk_ses.100001.4cf6=*; _pk_id.100001.4cf6=73809205b31654d3.1609985591.4.1618043308.1618041207.' 17 18 # 正则表达式 - 规则 - 模板 字符串之前记得写 r 19 # 链接 20 re_link = re.compile(r'<a href="(.*?)">') # 正则表达式中,()表示一个组-整体,该表达式是任意字符重复大于等于0次,并且有0或1个这样的字符串 21 22 # 图片 23 re_img = re.compile(r'<img .*src="(.*?)"', re.S) # 忽略换行符 24 25 # 片名 26 re_title = re.compile(r'<span class="title">(.*)</span>') 27 28 # 评分 29 re_rating = re.compile(r'<span class="rating_num" property="v:average">(.*)</span>') 30 31 # 评分人数 32 re_people = re.compile(r'<span>(\d*人评价)</span>') # 注意反斜杠 \d 33 34 # 一句话 35 re_quote = re.compile(r'<span class="inq">(.*)</span>') 36 37 # 影片简介 38 re_background = re.compile(r'<p class="">(.*?)</p>', re.S) # 这里的 ?必须要加,原因见笔记 39 40 41 def ask_url(para_url, para_head): 42 request = urllib.request.Request(url=para_url, headers=para_head) 43 para_html = '' # response对象被 read后是二进制数据 44 try: 45 response = urllib.request.urlopen(request) 46 para_html = response.read() 47 except urllib.error as e: 48 print(e.reason) 49 50 return para_html 51 52 53 def save_data(para_datalist, para_savepath): 54 my_workbook = xlwt.Workbook(encoding='utf-8', style_compression=0) # workbook对象 55 my_sheet1 = my_workbook.add_sheet('sheet1', cell_overwrite_ok=True) # 工作表;cell_overwrite_ok表示是否以新内容覆盖单元格内原有的内容 56 first_row = ('影片链接', '图片链接', '中文名', '外国名', '影片评分', '评分人数', '一句话评价', '影片简介') # 写入Excel的第一行标题 57 for i in range(0, 8): 58 my_sheet1.write(0, i, first_row[i]) 59 60 # 写入爬取的250条内容 61 count_movie = 0 # 计数:第几个电影 62 for i in range(0, 250): 63 # 每条中有8种信息 64 for j in range(0, 8): 65 my_sheet1.write(i+1, j, para_datalist[count_movie+j]) 66 67 print('正在爬取第%d条电影' % (i+1)) 68 count_movie += 8 # 切换到下一部电影 69 70 # 保存Excel文件 71 my_workbook.save(para_savepath) 72 print('爬取完成!') 73 74 75 def get_data(para_url, para_head): 76 datalist = [] 77 78 # 顺序爬取豆瓣电影top250的10个网页 79 for i in range(0, 10): 80 temp = 'start=' + str(i * 25) 81 pre_url = para_url.replace('start=0', temp) 82 temp_html = ask_url(pre_url, para_head).decode('utf-8') 83 84 # 爬取完成后对数据(temp_html)进行解析 85 soup = BeautifulSoup(temp_html, 'html.parser') 86 # find_all的新方法,标签名与类名同时查找(笔记中的 *kwargs) 87 # 找到了所有的 item 标签,并将标签及其内容返回到了 temp 88 for temp in soup.find_all('div', class_='item'): 89 # print(type(temp)) # 在 bs4中找到的标签等均是bs4的文件类型:bs4.element.Tag 90 # 所以在下面的正则查找时要转换成 string 类型才可以 91 str_temp = str(temp) 92 93 # 链接 94 temp_link = re.findall(re_link, str_temp)[0] # 有可能在一个item中找到多个,我们只打印一个 95 datalist.append(temp_link) 96 # findall最后只返回组内元素 - 连接 97 98 # 图片 99 temp_img = re.findall(re_img, str_temp)[0] 100 datalist.append(temp_img) 101 102 # 名称 - 注意其中包含中文名与外国名两个元素 103 temp_title = re.findall(re_title, str_temp) 104 if len(temp_title) == 2: 105 datalist.append(temp_title[0]) # 中文名 106 datalist.append(temp_title[1].replace('/', '').strip()) # 英文名, 并且把英文名前的斜杠消除 107 else: 108 datalist.append(temp_title[0]) 109 datalist.append(' ') # 若没有英文名,则必须置为空,保证顺序 110 111 # 评分 112 temp_score = re.findall(re_rating, str_temp) 113 datalist.append(temp_score[0]) 114 115 # 评分人数 116 temp_people = re.findall(re_people, str_temp)[0] 117 datalist.append(temp_people) 118 119 # 一句话 120 temp_quote = re.findall(re_quote, str_temp) 121 if temp_quote: 122 datalist.append(temp_quote[0].replace('。', '')) 123 else: 124 datalist.append(' ') 125 126 # 简介 127 temp_background = re.findall(re_background, str_temp)[0] 128 # 去掉<br/> 129 temp_background = re.sub(r'<br(\s+)?/>(\s+)?', '', temp_background) # \s匹配空格、空白、tab 130 # 去掉 / 131 temp_background = re.sub(r'/', ' ', temp_background) 132 # 去掉两个及以上的不间断空白符 \xa0或空格 133 temp_background = re.sub('(\xa0| )+', ' ', temp_background) 134 datalist.append(temp_background.strip()) # strip函数去掉开头结尾的换行符和空格 135 print(datalist) # 测试 datalist 136 return datalist 137 138 139 natural_url = 'http://movie.douban.com/top250?start=0&filter=' 140 douban_dataList = get_data(natural_url, head_package) 141 save_data(douban_dataList, save_path)
记得认真看注释!
最终结果:


浙公网安备 33010602011771号