Python爬虫之爬取静态网页实践
通过上一篇的学习,对网页文件的结构有了初步的了解,下面实战爬取某网页的知识问答语料:
1、使用库文件
request:用于get请求
threading:多线程
bs4:网页解析
re:正则表达式
os:系统相关操作
time:获取时间
2、对网页文件进行解析
打开谷歌浏览器,按F12进入开发者工具,并定位到自己想爬取的内容,如图
3、获取网页请求的头文件,一般网上有User-Agent大全:
4、分析需要爬取的网页结构
本着从特殊到一般的思路进行搜索,通过一个需爬取文件信息进行分析,找出所有的共性。通过分析发现,我们需要的标题信息是一个a标签对应的内容,然后我们需要向上进行搜索,可见标题信息的上一级是一个h3标签,h3标签的上一级是一个li标签。用通过同样的思路对来源信息进行分析,我们发现,标题信息和来源信息都在一个li标签下面,进一步可以发现,其他的新闻信息都在这类li标签下,这些li标签都在class属性值为mt10的div标签下,而且整片文档中,class属性值为mt10的div标签也只有这一个。
因此,我们可以从这个div入手,找到这个标签下的每一个li标签,对每一个li标签进行遍历,每一个li标签下有唯一的h3标签,该标签的文本即为我们要找的标题信息;另外,每一个li标签下有两个class属性值,一个class属性值为mr20的span标签,该span标签中对应的文本就是发布日期;另一个class属性值为s-c358的em标签,该em标签中对应的文本就是当前热度。分析结束之后,我们就可以通过bs4进行信息提取了。
当然这只是首页的信息,没有点击进去进入内容页面,所以我们需要查看点击进去的内容,但上面的页面解析中的网址只有后面一段,前面的没有,这时候怎么办呢?办法就是进行网址拼接,将前半段网址(一般固定的)与我们提取的后半段网址进行拼接即可。拼接好之后并打开该网页可以查看内容,内容的网页解析和上面的解析一样,即可获取里面的想要的内容。
分析完成之后,该代码实战提取了:
在本节的例子里面,我们将对某网站的知识问答进行爬取。首先我们导入我们所需要的requests和bs4模块,然后向目标url发出get请求获取首页的html文档。具体如下:
import requests
from bs4 import BeautifulSoup
f=open("write.txt","w",encoding="utf-8")
headers = {
'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/65.0.3325.146 Safari/537.36'
}
url = '网址链接' #
res = requests.get(url, headers=headers)
soup = BeautifulSoup(res.text, 'lxml')
我们的目的是提取新闻的标题和答案,所以根据上面的DOM结构分析。代码如下:
# 找出class属性值为mt10的div
news_list = soup.find('div', {'class': 'mt10'})
# 找出news_list下的所有li标签
news = news_list.find_all('li')
news_titles = []
news_source = []
news_hot = []
news_website = []
# 遍历news
for i in news:
try:
# 提取标题
title = i.find('h3').get_text().strip()
# 提取网址
href = i.find('h3').find_all('a')
for item in href:
website = item.get('href')
urlsite = '前半段网址'+ website #拼接网址
news_website.append(urlsite)
#提取日期
# source = i.find('span', {'class': 'mr20'}).find('a').get_text().strip()
source = i.find('span', {'class': 'mr20'}).get_text().strip()
# 提取热度
hot = i.find('em', {'class': 's-c358'}).get_text().strip()
# 存储爬取结果
news_titles.append(title)
news_source.append(source)
news_hot.append(hot)
# print('问答标题:', title)
# print('问答网址:', urlsite)
# print('发布日期:', source)
# print('热度:', hot)
# print()
except AttributeError as e:
continue
for i in news_website:
res1 = requests.get(i, headers=headers)
soup1 = BeautifulSoup(res1.text, 'lxml')
news_list1 = soup1.find('div', {'class': 'detail'})
# 提取标题
title1 = news_list1.find('h1').get_text().strip()
# 提取日期
source1 = news_list1.find('div', {'class': 'det-info'}).get_text().strip()
content = news_list1.find('div', {'class': 'det-nr'}).get_text().strip()
f.write(title1+'\n'+source1+'\n'+content)
f.write('\n')
f.flush()
提取的结果:
当然,后续还要进行换页,写个循环即可,另外加个随机的睡眠时间,不然会禁掉你的IP或者远程终止你的爬虫进程,固定的死时间也容易被发现非人为操作,最后并存到csv文件中,结果如下: