⽤Python实现爬取百度热搜信息
⽬录
前⾔
库函数准备
数据爬取
⽹页爬取
数据解析
数据保存
总结
前⾔
何为爬⾍,其实就是利⽤计算机模拟⼈对⽹页的操作
例如模拟⼈类浏览购物⽹站
使⽤爬⾍前⼀定要看⽬标⽹站可刑不可刑:-)
可以在⽬标⽹站添加/ 查看⽹页具体信息
User-agent 代表发送请求的对象
星号*代表任何搜索引擎
Disallow 代表不允许访问的部分
/代表从根⽬录开始
Allow代表允许访问的部分
在本例中我爬取的百度热搜前30的新闻(本⼈原本打算爬取英雄联盟主页数据中⼼⼤乱⽃胜率前五⼗的英雄信息奈何不会实现延时爬取⽹页的操作⽆奈只能爬百度热搜)并且其⼤致信息放到Excel表格以及Flask⽹页中实现数据可视化感兴趣的同学也可以对其它内容进⾏爬取
由于本⼈⽔平有限本⽂章中的爬⾍都是⽐较基础的东西
库函数准备
Python库的安装⽅法:
打开cmd命令提⽰符输⼊pip install XXX(这个是你要装的库名称)
关于这些库的具体使⽤可以接下来看我的操作
只需要简单掌握⼏个常⽤的函数即可
bs4
即BeautifulSoup
⽤来解析HTML⽹页,提取指定数据的。
其中详细的⽤法待会看我的演⽰。
re
正则表达式⽤来匹配字符串中响应的字串。
关于正则表达式可以去看菜鸟教程⾥边讲的很详细
urllib
是⼀个Python⾃带的HTTP请求库,可以操作⼀系列URL。
xlwt/xlrt
⽤于写⼊(write) / 读取(read),Excel表中的数据。
flask
这个库是⽤来只做⼀个简单的Web框架即⽹站,⽤于数据的可视化。
其实本⼈对于数据可视化的掌握也很浅薄,只是简单的将数据导⼊Web⽹页中。
jinja2
这个库的作⽤是为了实现在HTML⽹页中的字符中插⼊⾃变量的功能。
后端:
name="HQ"
前端:
<p>{{name}}长得真帅!</p>
显⽰:
HQ长得真帅!
markupsafe
与Jinja共⽤在渲染页⾯时⽤于避免不可信的输⼊,防⽌注⼊攻击(虽然没⼈会攻击你....)数据爬取
数据爬取和数据可视化两个py⽂件是分开的
数据爬取需要导⼊re bs4 urllib xlwt 四个库⽂件
⽹页爬取
使⽤⼀下的⽅法调⽤函数可以使函数调⽤关系更加清晰
if __name__=="__main__":  #当程序执⾏时调⽤⼀下函数
main()
def askurl(url):
head={
"User-Agent":'''Mozilla/5.0 (Windows NT 10.0; Win64; x64)
AppleWebKit/537.36 (KHTML, like Gecko) Chrome/97.0.4692.71 Safari/537.36 Edg/97.0.1072.55'''
}
#⽤户代理告诉服务器我只是⼀个普普通通的浏览器
quest.Request(url)
#发送请求
quest.urlopen(requset)
#响应的为⼀个request对象
#通过read()转化为 bytes类型字符串
#再通过decode()转化为 str类型的字符串
#接受响应
ad().decode('utf-8')
将抓取到的⽹页存⼊⽂档中⽅便观察
path=r"C:\Users\XXX\Desktop\"
#这⾥在字符串前加⼊r 防⽌字符串中的\发⽣转义
f=open(r"path",'w',encoding='utf-8')
f.write(html)
f.close()
#这样在txt⽂件中就可以查看⽹页的源码
return html
headers的值可以在⽹页中按F12
然后点击⽹络变化对于任意⼀个请求标头下拉到最下⽅即为 user-agent 代理信息
值得注意的是请求中如果不设置headers 则服务器会返回⼀个418的状态码
代表服务器识别出来你是⼀个爬⾍并且表⽰:“ I'm a teapot ”
表明服务器拒绝冲煮咖啡,因为它永远是⼀个茶壶(这是⼀个梗)
数据解析
将抓取的txt⽂件后缀改为html后打开即为⼀个本地的⽹页
如果在vscode中因为⾏过长⽽产⽣报错可以参考以下博客
打开后的⽹页如图所⽰
使⽤这个功能查看需要爬取信息的位置
在本项⽬中我们抓取⽬标信息的标题内容热度以及链接
我们可以发现我们需要的信息全部在class为以下类型的表中
于是我们⽤Beautifulsoup对⽹页进⾏解析
def getData(html):
datalist=[]
soup=BeautifulSoup(html,"html.parser")  #定义⼀个解析对象
#soup.find_all(a,b) 其中a为标签的类型 class_ 对div的class进⾏匹配
#返回的是所有class为category-wrap_iQLoo horizontal_1eKyQ的列表
for item in soup.find_all('div',class_="category-wrap_iQLoo horizontal_1eKyQ"):        item=str(item)
#将列表中每⼀个⼦标签转换为字符串⽤于re匹配
接下来对每⼀个item进⾏re匹配
⾸先使⽤repile()创建匹配规则然后⽤findall进⾏匹配
匹配规则的创建⽅式为在HTML⽂件中查看⽬标信息前后的特殊字符
⽽(.*?)即为要匹配的字符串其中*后加?代表⾮贪婪匹配
例如
标题前后信息即为ellipsis">和</div> <div cla
其它同理
#匹配规则
#链接
findlink=repile(r' href="(.*?)" rel="external nofollow"  target="_blank')
#标题
findtitle=repile(r'ellipsis"> (.*?) </div> <div cla')
#内容
findcontent1=repile(r'ellipsis_DupbZ"> (.*?) <a class=')
findcontent2=repile(r'small_Uvkd3"> (.*?) <a class=')
#热度
findnumber=repile(r'ex_1Bl1a"> (.*?) </div>')
⽽内容部分我在后续运⾏的时候发现报错原因是
部分内容前缀为'ellipsis_DupbZ">  部分内容前缀为small_Uvkd3">因此我编写了两种匹配⽅式
具体代码如下
def getData(html):
datalist=[]
soup=BeautifulSoup(html,"html.parser")  #定义⼀个解析对象
#soup.find_all(a,b) 其中a为标签的类型 class_ 对div的class进⾏匹配
#返回的是所有class为category-wrap_iQLoo horizontal_1eKyQ的列表
for item in soup.find_all('div',class_="category-wrap_iQLoo horizontal_1eKyQ"):        item=str(item)
#将列表中每⼀个⼦标签转换为字符串⽤于re匹配
data=[]
python菜鸟教程文档
#标题
title=re.findall(findtitle,item)[0]
#简介
#判断是否对第⼀种匹配如果不是的话返回为空列表此时应采⽤第⼆种匹配        if (len(re.findall(findcontent1,item))!=0):
content=re.findall(findcontent1,item)[0]
else:
content=re.findall(findcontent2,item)[0]
#热度
number=re.findall(findnumber,item)[0]
#链接
link=re.findall(findlink,item)[0]
#将数据存⼊数组
data.append(title)
data.append(number)
data.append(content)
data.append(link)
datalist.append(data)
print(datalist)
return datalist
数据保存
def Savedata(datalist):
#存⼊数据的⽬标路径
path=r'C:\Users\XXX\Desktop\Python\爬⾍\data.xls'
workbook=xlwt.Workbook(encoding='utf-8')
#创建⼯作表对象