要爬取内容的是豆瓣网的电影排行top250: https://movie.douban.com/top250, 将电影名和评分爬取下来并输出, 如下图:
使用了tkinter做了简单页面
首先分析要爬取的url, 发现每个页面有25条内容, 总共有十页, 第一页的URL为https://movie.douban.com/top250?start=0&filter=
第二页的url为https://movie.douban.com/top250?start=25&filter=
第三页第四页也是类似的URL, 只是修改了start后面的数字, 第一页是0, 往后每增加25, 所以url的格式为https://movie.douban.com/top250?start=+{ID}
然后分析如何爬取内容:
首先爬取标题:
查看源代码后, 发现标题是放在这样的代码:
<a href="https://movie.douban.com/subject/1292052/" class="">
<span class="title">肖申克的救赎</span>
<span class="title"> / The Shawshank Redemption</span>
<span class="other"> / 月黑高飞(港) / 刺激1995(台)</span>
</a>
发现电影的名称一般都放在
<span class="title">电影名称</span>
这样的标记对中, 所以根据这个可以写出正则表达式:
<span class="title">(.*?)</span>
不过在后面的测试中发现这样写的话, 每个电影名称能获取两个信息
<span class="title">肖申克的救赎</span>
<span class="title"> / The Shawshank Redemption</span>
显然第二条信息不是我们想要的, 经过对比发现第二条信息中都会有两个空格的代码, 所以把&给过滤掉就可以了:
<span class="title">(.[^&]*?)</span>
接下来爬取评分, 评分一般放在这样的代码中:
<div class="star">
<span class="rating5-t"></span>
<span class="rating_num" property="v:average">9.6</span>
<span property="v:best" content="10.0"></span>
<span>716019人评价</span>
</div>
这个正则就很好写了:
"v:average">(.*?)</span>
这样就ok啦, 这个程序还是非常简单的, 上源代码:
# -*- coding: utf-8 -*-
from Tkinter import *
from ScrolledText import ScrolledText
import requests, re, threading
def replite(ID):
varl.set('正在获取第%d页内容' % (ID / 25 + 1))
html = 'https://movie.douban.com/top250?start=' + str(ID)
response = requests.get(html).text
# response = unicode(response, 'GBK').encode('UTF-8')
response = response.encode('utf-8 ')
# print response
# reg = r'<span class="title">(.*?)</span>.*?"v:average">(.*?)</span>'
regTitle = r'<span class="title">(.[^&]*?)</span>'
regStars = r'.*?"v:average">(.*?)</span>'
regTitle = re.compile(regTitle)
regStars = re.compile(regStars)
titles = re.findall(regTitle, response)
stars = re.findall(regStars, response)
info = list(zip(titles, stars))
return info
def write():
varl.set('开始爬取内容')
ID = 0
nums = 1
while ID < 250:
res = replite(ID)
ID += 25
for each in res:
text.insert(END, 'No.%d\t%-30s%s分\n' % (nums, each[0], each[1]))
nums += 1
varl.set('获取内容成功')
def start():
t1 = threading.Thread(target=write)
t1.start()
def save():
content = text.get("0.0", "end").encode('GBK')
textfile = open(u'E:\\豆瓣电影排行250.txt', 'w')
textfile.write(content)
textfile.close()
root = Tk()
root.title('豆瓣电影top250')
root.geometry('820x500+400+200')
text = ScrolledText(root, font=('楷体', 15), width=80, height=20)
text.grid()
frame = Frame(root)
frame.grid()
# 启动爬虫功能
startButton = Button(frame, text='开始', font=('楷体', 18), command=start)
startButton.grid()
startButton.pack(side=LEFT)
# 保存爬取信息
saveButton = Button(frame, text='保存文件', font=('楷体', 18), command=save)
saveButton.grid()
saveButton.pack(side=LEFT)
# 退出程序
exitButton = Button(frame, text='退出', font=('楷体', 18), command=frame.quit)
exitButton.grid()
exitButton.pack(side=LEFT)
varl = StringVar()
info_label = Label(root, fg='red', textvariable=varl)
info_label.grid()
varl.set('准备中....')
root.mainloop()
不过有点小bug, 有时候tkinter会报TclError错误, 有没有大神知道怎么解决?