#导包 import requests from bs4 import BeautifulSoup import pandas as pd第一步:下载所有页面(共10个)的HTML 【1】构造分页数字列表page_indexs 【2】构造函数download_all_htmls,下载列表所有页面的HTML
1、先添加请求头headers(爬取的网站有反爬虫机制,要向服务器发出爬虫请求,需要添加请求头headers。不然响应状态是418,正常情况应该是200。)
2、利用for循环取到页面列表中的每一个页面的网址url
3、用requests.get函数获取html网页(构造一个向服务器请求资源的url对象,并添加headers参数。返回的是一个包含服务器资源的Response对象。)
4、r.status_code返回http请求的返回状态:200表示连接成功,返回418表示爬取的网站有反爬虫机制,要向服务器发出爬虫请求,需要添加请求头headers
5、htmls.append(r.text)添加每个url对应的页面内容到列表htmls
text()方法:返回文本内容
第二步:解析HTML得到数据 【1】构造函数parse_single_html,用于解析单个html得到数据 1、找到每部电影:find()方法:只返回第一个匹配到的对象
find(name, attrs, recursive, text, **wargs) # recursive 递归的,循环的
find_all()方法:返回所有匹配到的结果
find_all(name, attrs, recursive, text, limit, **kwargs)
此处形参用class_的原因:
参考:(13条消息) BeautifulSoup中find和find_all的使用_OCISLU的博客-CSDN博客
soup.find("div",class_="article").find("ol",class_="grid_view").find_all("div",class_="item")
2、用for循环对每部电影取相应类型的数据:
get_text()方法:获取文本内容
#排名
rank=article_item.find("div",class_="pic").find("em").get_text()
#电影名称
title=info.find("div",class_="hd").find("span",class_="title").get_text()
stars=(
info.find("div",class_="bd")
.find("div",class_="star")
.find_all("span") #stars里含有4个span,返回一个列表
)
#5星评分
rating_star=stars[0]["class"][0] #第一个span中的class属性的第一个值
#10分评分
rating_num=stars[1].get_text()
#评论人数
comments=stars[3].get_text()
3、将每部电影的信息存到字典中,并作为列表的一个元素添加到datas列表中去
字符串替换replace()方法:
datas.append({
"排名":rank,
"电影名":title,
"5星评价":rating_star.replace("rating","").replace("-t",""),
"10分评分":rating_num,
"评价人数":comments.replace("人评价","")
})
【2】执行所有HTML页面的解析
#对每一个HTML页面进行解析,并将结果添加到列表all_datas
all_datas=[]
for html in htmls:
all_datas.extend(parse_single_html(html))
第三步:将结果存入Excel
df=pd.Dataframe(all_datas)
df.to_excel("豆瓣top250电影榜单.xlsx")
第四步:Dataframe数据导入MySQL
import sqlalchemy
from sqlalchemy import create_engine
#建立连接
conn = create_engine('mysql+pymysql://root:123@localhost:3306/crawl?charset=utf8')
#写入数据,‘replace’表示如果同名表存在就替换掉
df.to_sql(name='douban', con=conn,if_exists='replace',index=False,index_label='排名',
dtype={'排名': sqlalchemy.types.BigInteger(),
'电影名': sqlalchemy.types.String(length=20),
'5星评价': sqlalchemy.types.BigInteger(),
'10分评分': sqlalchemy.types.BigInteger(),
'评价人数': sqlalchemy.types.BigInteger(),
})
【完整代码】
import requests
from bs4 import BeautifulSoup
import pandas as pd
page_indexs=range(0,250,25)
def download_all_htmls():
#先添加请求头headers
headers={'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/94.0.4606.71 Safari/537.36 Edg/94.0.992.38'}
htmls=[] #存放各个url对应的页面内容
for idx in page_indexs:
url=f"https://movie.douban.com/top250?start={idx}&filter="
print("crawl html:",url) #url是通过http协议存取资源的一个路径,它就像我们电脑里面的一个文件的路径一样
r=requests.get(url,headers = headers) #获取html网页(构造一个向服务器请求资源的url对象),并添加headers参数。r返回的是一个包含服务器资源的Response对象,包含从服务器返回的所有相关资源。
if r.status_code!=200: # r.status_code 返回http请求的返回状态(200表示连接成功)
raise Exception("error") # 返回418表示:爬取的网站有反爬虫机制,要向服务器发出爬虫请求,需要添加请求头headers
#print(r.status_code)
htmls.append(r.text) # r.text 获取url对应的页面内容
return htmls
htmls=download_all_htmls()
def parse_single_html(html):
soup=BeautifulSoup(html,'html.parser') #构建BeautifulSoup实例(第一个参数是要匹配的内容;第二个参数是要采用的模块,即规则)
article_items=( #返回一个列表,代表每个article的信息
soup.find("div",class_="article") # find() 只返回第一个匹配到的对象
.find("ol",class_="grid_view")
.find_all("div",class_="item") # find_all() 返回所有匹配到的结果(此处返回所有电影)
)
datas=[] #将数据存到列表里面
for article_item in article_items:
rank=article_item.find("div",class_="pic").find("em").get_text() #获取排名
info=article_item.find("div",class_="info")
title=info.find("div",class_="hd").find("span",class_="title").get_text() #获取电影名称
stars=(
info.find("div",class_="bd")
.find("div",class_="star")
.find_all("span") #stars里含有4个span
)
#print(stars)
rating_star=stars[0]["class"][0] #获取5星评分
rating_num=stars[1].get_text() #获取10分评分
comments=stars[3].get_text() #获取评论人数
datas.append({
"排名":rank,
"电影名":title,
"5星评价":rating_star.replace("rating","").replace("-t",""),
"10分评分":rating_num,
"评价人数":comments.replace("人评价","")
})
return datas
all_datas=[]
for html in htmls:
all_datas.extend(parse_single_html(html))
df=pd.Dataframe(all_datas)
import sqlalchemy
from sqlalchemy import create_engine
#建立连接
conn = create_engine('mysql+pymysql://root:123@localhost:3306/crawl?charset=utf8')
#写入数据,t_stock_trade_date为数据库表名,‘replace’表示如果同名表存在就替换掉
df.to_sql(name='douban', con=conn,if_exists='replace',index=False,index_label='排名',
dtype={'排名': sqlalchemy.types.BigInteger(),
'电影名': sqlalchemy.types.String(length=20),
'5星评价': sqlalchemy.types.BigInteger(),
'10分评分': sqlalchemy.types.BigInteger(),
'评价人数': sqlalchemy.types.BigInteger(),
})
print('ok')



