使用python爬取《长城》豆瓣影评

声明:这里参考了这篇博客的代码

爬取豆瓣影评时,不能使用最简单粗暴的爬虫策略,因为豆瓣服务器
是有反爬虫机制的。简单的粗暴的方式只能爬取四页就会被禁掉。所以这里必须要使用表头,伪装成使用浏览器进行访问。而且需要使用cookie信息。

刚开始使用urllib包来爬取,后来发现困难重重,尽管加了表头跟cookie,但是最多还是只能爬到几百条评论就被禁掉。不知道是因为
表头信息不够还是加的cookie有问题。总之使用这种方法不能爬取全部的
评论信息。给出代码如下,如有大神知道原因,望不吝赐教

#需要爬取的信息:['user_id','rating','comment_time','comment_vote','comment']
from bs4 import BeautifulSoup
import re
import urllib.request
from urllib.error import URLError
import xlwt
import mysql.connector
import time
import urllib.parse
import http.cookiejar
#添加表头信息
my_headers=["Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.95 Safari/537.36",
"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/35.0.1916.153 Safari/537.36",
"Mozilla/5.0 (Windows NT 6.1; WOW64; rv:30.0) Gecko/20100101 Firefox/30.0"
"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_2) AppleWebKit/537.75.14 (KHTML, like Gecko) Version/7.0.3 Safari/537.75.14"
]
#发送请求
def askURL(url):
    import random
    filename = 'cookie.txt'
    #randdom_header="Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/54.0.2840.99 Safari/537.36"
    randdom_header=random.choice(my_headers)
    cookie = http.cookiejar.MozillaCookieJar(filename)
    opener = urllib.request.build_opener(urllib.request.HTTPCookieProcessor(cookie))
    postdata = urllib.parse.urlencode({
      '账号':'***',
      '密码':'***'
    })
    postdata=postdata.encode(encoding='UTF8')
    LOGIN_URL = 'https://accounts.douban.com/login?source=movie'
    #模拟登录,并把cookie保存到变量
    request = urllib.request.Request(LOGIN_URL, postdata,randdom_header )

    try:
        response = opener.open(request)#取得响应
        html= response.read().decode()#获取网页内容
        print(html)
    except URLError as e:
        if hasattr(e,"code"):
            print (e.code)
        if hasattr(e,"reason"):
            print (e.reason)
    cookie.save(ignore_discard=True, ignore_expires=True)
    for item in cookie:
        print('Name = ' + item.name)
        print('Value = ' + item.value)
    get_request = urllib.request.Request(url, headers=headers)
    get_response = opener.open(get_request)
    return get_response
#获取相关内容
def getData(baseurl_1,baseurl_2):
    datalist=[]
    for i in range(0,300,26):
        url=baseurl_1+str(i)+baseurl_2#更新url
        html=askURL(url)
        time.sleep(1)
        soup = BeautifulSoup(html,'lxml')
        #找到每一个影评项

        for item in soup.find_all('div',class_='comment-item'):
            data=[]
            #user_id
            user_id=item.find('a',class_="").get('title')
            #print (user_id)
            data.append(user_id)

            #rating
            rating=item.find('span',class_="rating")
            if rating!=None:
                rating=rating.get('title')
            else:
                rating='无评分'
            #print(rating)
            data.append(rating)

            #comment_time
            comment_time=item.find('span',class_="comment-time").text.strip()
            #print(comment_time)
            data.append(comment_time)

            #comment_vote
            comment_vote=item.find('span',class_="votes pr5").text
            #print(comment_vote)
            data.append(comment_vote)#添加推荐等级

            #comment
            comment=item.find("p")
            #回应数可能为0,就找不到
            if(comment!= None):
                comment=comment.text.strip()
            else:
                comment=str(0)
            #print(comment)
            data.append(comment)#添加回应数
            datalist.append(data)
    return datalist
#保存数据到excel
def saveData(datalist,savepath):
    book=xlwt.Workbook(encoding='utf-8',style_compression=0)
    sheet=book.add_sheet(u'豆瓣影评',cell_overwrite_ok=True)
    col=['user_id','rating','comment_time','comment_vote','comment']

    for i in range(0,5):
        print(i)
        sheet.write(0,i,col[i])#列名

    for i in range(0,700):#总共700条影评,暂时只爬到700条
        data=datalist[i]
        for j in range(0,5):#此处需要注意,当评论中包含表情字符,是无法插入excel中的。同样也无法插入数据库中。这里我的解决方法是用正则表达式匹配评论中的汉字。代码在下一篇文章给出
            sheet.write(i+1,j,data[j])#数据
    book.save(savepath)#保存
def connDB():#连接数据库函数
    conn=mysql.connector.connect(user='root',passwd='123456',database='review',charset='utf8mb4')
    cursor=conn.cursor()
    return(conn,cursor)

def exitConn(conn,cursor):
    cursor.close()
    conn.close()
#保存数据到数据库    
def SaveMysql(datalist):
    conn,cursor=connDB();

    cursor.execute('create table movie_review2 \
       (title varchar(50) ,\
        author varchar(20),\
        moviename varchar(20),\
        movielink varchar(100),\
        star varchar(10),\
        response varchar(10),\
        reviewlink varchar(50),\
        useful varchar(10),\
        review varchar(8000))')  
    for i in range(0,50): 
        data=datalist[i]
        print('insert into movie_review2 values\
         (%s,%s,%s,%s,%s,%s,%s,%s,%s)',[data[0],data[1],data[2],data[3],data[4],data[5],data[6],data[7],data[8]])
        cursor.execute('insert into movie_review2 values\
         (%s,%s,%s,%s,%s,%s,%s,%s,%s)',[data[0],data[1],data[2],data[3],data[4],data[5],data[6],data[7],data[8]])
        conn.commit()
    exitConn(conn,cursor)
if __name__=='__main__':
    baseurl_1='https://movie.douban.com/subject/6982558/comments?start='
    baseurl_2='&limit=20&sort=new_score&status=P'
    datalist=getData(baseurl_1,baseurl_2)
    savepath='豆瓣最受欢迎影评.xls'
    saveData(datalist,savepath)
    SaveMysql(datalist)

这个程序目前只能抓取八页的影评数据,没有找到原因在哪?后来一哥们使用requests
包使问题得到了解决,而且程序代码要简单很多,下次把可以抓取全部评论数据的代码贴上来。

你可能感兴趣的:(使用python爬取《长城》豆瓣影评)