爬虫
Python 爬虫是一种自动化工具,用于从互联网上抓取网页数据并提取有用的信息。Python 因其简洁的语法和丰富的库支持(如 requests、BeautifulSoup、Scrapy 等)而成为实现爬虫的首选语言之一。
Python爬虫获取浏览器中的信息,实际上是模仿浏览器上网的行为。上一篇中,我们尝试着爬取了一个网站的页面,完成获取信息需要完成三步:
- 指定url
- 发送请求
- 获取你想要的数据
那这次我们来试试爬取网页中的文本内容:我们再添加一步
- 数据解析
我们试着爬取一个以下网站页面内的电影名、导演、演员、上映时间、国家和剧情类型:
https://movie.douban.com/top250
我们按步骤一步一步来:
爬取文本
按步骤获取:
指定url
url = "https://movie.douban.com/top250"
发送请求
import fake_useragent#伪装身份发送请求
import requests
#UA伪装 让你认为我是一个浏览器
head = {
"User-Agent":fake_useragent.UserAgent().random
}
response = requests.get(url,headers=head)
获取想要的数据
res_text = response.text
#print(res_text)
数据解析
xpath语言
在Python中,XPath(XML Path Language)是一种在XML和HTML文档中查找信息的语言。它允许你通过指定元素的路径来定位和选择文档中的节点(如元素、属性等)。Python通过一些库支持XPath的使用,最著名的是lxml和BeautifulSoup(虽然BeautifulSoup本身不直接支持XPath,但可以通过lxml解析器来间接使用XPath)。
所以在使用xpath之前,我们需要先Python安装一个lxml包:
pip install lxml
安装完成后,导入包:
from lxml import etree
解析获得的数据内容:
tree = etree.HTML(res_text) #将HTML文本(通常是网页的源代码)解析
找出我们想要的文本内容,第一步点击元素Elements,接着点击第二步的箭头,点击我们想要得到的内容,右边开发者控制台会出现其所在的位置。
定位目标位置
从开发者控制台中我们能看到多个目录,索引定位,从1开始。
定位所有的li标签:
- 逐层定位:
xpath返回的都是列表:我们接受一下它:
li_list = tree.xpath("/body/div[3]/div[1]/div[1]/div[1]/ol/li")
这样逐层找很麻烦复杂。
- 属性定位
找到class属性,按ctrl+ "f"健查询开发者控制台中属性出现的个数。如果只有一个,可以直接越级定位。
li_list = tree.xpath("//ol[@class='grid_view']/li")
定位完成后,确定有没有解析到数据。打印li_list:
print(li_list) #返回是列表形式
--------------------------
[<Element li at 0x1b1d32e3f88>, <Element li at 0x1b1d32a23c8>, <Element li at 0x1b1d3289c88>, <Element li at 0x1b1d32e8148>, <Element li at 0x1b1d32e82c8>, <Element li at 0x1b1d32e81c8>, <Element li at 0x1b1d32e8208>, <Element li at 0x1b1d32e8248>, <Element li at 0x1b1d32e8188>, <Element li at 0x1b1d32e8288>, <Element li at 0x1b1d32e8348>, <Element li at 0x1b1d32e8f08>, <Element li at 0x1b1d3301208>, <Element li at 0x1b1d3301288>, <Element li at 0x1b1d3301f08>, <Element li at 0x1b1d3301fc8>, <Element li at 0x1b1d331bc88>, <Element li at 0x1b1d331bfc8>, <Element li at 0x1b1d331b488>, <Element li at 0x1b1d331bb88>, <Element li at 0x1b1d331b9c8>, <Element li at 0x1b1d331b748>, <Element li at 0x1b1d331b588>, <Element li at 0x1b1d331b648>, <Element li at 0x1b1d331b788>]
具体位置
接着我们来定位每篇电影的电影名、导演、演员、上映时间、国家和剧情类型的位置。
for li in li_list: #利用join方法将列表转化为字符串。
film_name = "".join(li.xpath(".//span[@class='title'][1]/text()")) #text()取标签下的文本
director_actor_y_country_type = "".join(li.xpath(".//div[@class='bd']/p[1]/text()"))
print(film_name,director_actor_y_country_type)
-----
肖申克的救赎
导演: 弗兰克·德拉邦特 Frank Darabont 主演: 蒂姆·罗宾斯 Tim Robbins /...
1994 / 美国 / 犯罪 剧情
霸王别姬
导演: 陈凯歌 Kaige Chen 主演: 张国荣 Leslie Cheung / 张丰毅 Fengyi Zha...
1993 / 中国大陆 中国香港 / 剧情 爱情 同性
……………………过多不展示…………
正则匹配
拿到内容后,我们发现有大量的空格和文本垃圾,我们要将他们处理干净,将我们的目标内容拿出来。
别忘记导入正则re包哦!
import re
new_str = director_actor_y_country_type.strip() #strip()去空格
y = re.match(r"([\s\S]+?)(\d+)(.*?)", new_str).group(2) #正则匹配,group(2)取出第二组
country = new_str.rsplit("/")[-2].strip() #rsplit("/")[-2]以"/"为分隔符分割文本,切片出倒数第二个
types = new_str.rsplit("/")[-1].strip()
director = re.match(r"导演: ([a-zA-Z\u4e00-\u9fa5·]+)(.*?)", new_str).group(1)
try: #由于有的主演不符合标准,做个正则判断
actor = re.match(r"(.*?)主演: ([a-zA-Z\u4e00-\u9fa5·]+)(.*?)", new_str).group(2)
except Exception as e:
actor = "no"
#用不常用的符号连接在一起,这样调用的时候只需要以特殊符号分割
print(film_name + "#" + y + "#" + country + "#" + types + "#" + director + "#" +actor + "\n")
----------------------
挑选两个结果展示:
肖申克的救赎#1994#美国#犯罪 剧情#弗兰克·德拉邦特#蒂姆·罗宾斯
寻梦环游记#2017#美国#喜剧 动画 奇幻 音乐#李·昂克里奇#no #此电影没有主演,不符合规则,输出"no"
完整爬取展示
完整的爬取过程,将爬取的内容写进文本中:
import fake_useragent
import requests
from lxml import etree
import re
if __name__ == '__main__':
#UA伪装 让你认为我是一个浏览器
head = {
"User-Agent":fake_useragent.UserAgent().random
}
# 打开一个文件写入数据
fp = open("./doubanFilm.txt", "w", encoding="utf8")
# 1、指定url
url = "https://movie.douban.com/top250"
# 2、发送请求 返回的数据在response对象内
response = requests.get(url,headers=head)
#3、获取想要的数据
res_text = response.text
# print(res_text)
tree = etree.HTML(res_text)
# 定位所有的li标签
li_list = tree.xpath("//ol[@class='grid_view']/li")
# print(li_list)
for li in li_list:
film_name = "".join(li.xpath(".//span[@class='title'][1]/text()"))
director_actor_y_country_type = "".join(li.xpath(".//div[@class='bd']/p[1]/text()"))
# print(film_name,director_actor_y_country_type)
new_str = director_actor_y_country_type.strip()
y = re.match(r"([\s\S]+?)(\d+)(.*?)", new_str).group(2)
country = new_str.rsplit("/")[-2].strip()
types = new_str.rsplit("/")[-1].strip()
director = re.match(r"导演: ([a-zA-Z\u4e00-\u9fa5·]+)(.*?)", new_str).group(1)
try:
actor = re.match(r"(.*?)主演: ([a-zA-Z\u4e00-\u9fa5·]+)(.*?)", new_str).group(2)
except Exception as e:
actor = "no"
fp.write(
film_name + "#" + y + "#" + country + "#" + types + "#" + director + "#" +
actor + "\n")
fp.close()
总结
本篇介绍了,如何将网页内想获取的文本内容爬虫出来:
- 指定url:找到网页地址
- 发送请求:requests请求
- 获取你想要的数据:文本接收,请求到的内容
- 数据解析:
- xpath语言:定位到目标位置
- re正则匹配:精准取出目标内容,去除杂质