一、方法:
学习爬虫采用的是Requests+Xpath的方法,使用的requests+lxml库
二、步骤:
爬取网页基本结构为:
导入、下载网页、解析网页、获取元素Xpath信息并获得文本、打印获取的信息
三、实例:
实例一:爬取豆瓣图片top250为例
本实例要爬取豆瓣图书top250的书名、链接、评分、评分人数、简介
1.导入
import requests
from lxml import etree
import time
导入requests和lxml库以及time
2.下载网页
for a in range(10):
url = 'http://book.douban.com/top250?start={}'.format(a * 25)
data = requests.get(url).text
豆瓣top250每页25本图片,总共十页,观察每一页的url可以发现url的末尾start=‘’里的数字呈25递增,于是写循环以获取多个页面的信息。
3.解析网页
s = etree.HTML(data)
4.获取Xpath信息并获得文本
file = s.xpath('/html/body/div[3]/div[1]/div/div[1]/div/table')
for div in file:
title = div.xpath('./tr/td[2]/div[1]/a/@title')[0]
href = div.xpath('./tr/td[1]/a/@href')[0]
score = div.xpath('./tr/td[2]/div[2]/span[2]/text()')[0]
num = div.xpath('./tr/td[2]/div[2]/span[3]/text()')[0].strip("(").strip().strip(")")
scribe = div.xpath('./tr/td[2]/p[2]/span/text()')
time.sleep(1)
- 在网页定位元素位置后右键复制元素的xpath(直接路径,不建议)
- 图书的书名是title属性的值,但是在电影top页面,电影名为text类型,于是每个对象xpath后接的内容不完全相同。
- 因为获取的信息是列表,于是直接输出的话会出现[‘ ’]符号,所以[0]即取出内容直接输出
- num得到的信息有空格和双引号这种多余字符,strip()函数可以将其去除
- time.sleep是为了防止爬虫时怕的太快ip被封
5.打印获取的信息
if len(scribe) > 0:
print("{} {} {} {} {}".format(title, href, score, num, scribe[0]))
else:
print("{} {} {} {}".format(title, href, score, num))
由于有些图书没有介绍(scribe),如果直接输出就会报错,所以加一个判断。
此为最基础的爬虫实例,做完这个自己又尝试了爬豆瓣电影top250,成功。
豆瓣电影的电影名有多个部分,在多个span元素中,于是title部分添加一个循环:
title = div.xpath('./div[1]/a/span/text()')
for i in title:
print(i, end='')
实例二:小猪短租
爬取小猪短租成都城市页面,当时根据上面的方法爬取页面,但是返回空值,请教了学姐以后知道,url写直接路径容易出错,应采取相对路径,于是学习了一下有关xpath的详细知识,主要是路径表达式。
本例要爬取小猪短租页面房源的标题、描述、价格以及图片链接
file = s.xpath('//*[@id="page_list"]/ul/li')
for div in file:
title = div.xpath('./div[2]/div/a/span/text()')[0]
scribe = div.xpath('./div[2]/div/em/text()')[0].strip()
price = div.xpath('./div[2]/span[1]/i/text()')[0]
img = div.xpath('./a/img/@lazy_src')[0]
当时采取直接路径爬取时返回的全是空值,因为小猪页面会更新。
在页面的html文件中可以看到所有的所需信息都在一个id属性为page_list的div元素里,这个值是唯一的,相对路径定位到这里即可找到所需内容。
其余步骤用同样方法,该页面可爬取成功。
实例三:动态页面爬取
豆瓣电影励志分类。
此页面url不变,点击加载更多会显示更多的内容。
打开f12里面的js或者xhr可以发现刚开始为空,点击页面上的加载更多按钮以后会出现信息,右键在新标签页打开,返回了电影的各类信息。观察新打开的标签页的url,发现仍然是有规律的:
for a in range(3):
url = 'https://movie.douban.com/j/new_search_subjectssort=U&range=0,10&tags=%E5%8A%B1%E5%BF%97&start={}'.format(
a * 20)
file = requests.get(url).json()
time.sleep(2)
for i in range(20):
dict = file['data'][i]
urlname = dict['url']
title = dict['title']
rate = dict['rate']
cast = dict['casts']
- 因为返回的是json文件,get后接的是json()
- dict =file[‘data’][i] //取出文件中’data’下第i部电影的信息
urlname = dict[‘url’] //取出字典中的值,方括号里的是值对应的键
实例四:保存爬取的内容
爬取到的内容可以分txt格式和csv格式
Txt格式
with open('/Users/Kelll/PycharmProjects/test/movie.txt', 'w', encoding='utf-8') as f:
f.write('{} {} {} {}\n'.format(title, rate, ' '.join(cast), urlname))
在导入后,url前,with open函数中第一个参数是爬取下来的内容保存路径及保存为的文件名,第二个参数为写入模式(除此之外还有读模式,附加到文件末尾模式),第三个参数为数据的编码。As f为在代码中对文件的命名。
f.write函数将数据写入文件
csv格式
with open('/Users/Kelll/PycharmProjects/test/movie.csv', 'w', encoding='utf-8') as f:
f.write('{},{},{},{}\n'.format(title, rate, ' '.join(cast), urlname))
csv格式在excel中直接打开可能会乱码,可以先在记事本中打开,另存为时将文件编码改为ANSI。
保存的文件: