库
- requests库
- lxml
- csv
库的安装
1.pip install ****
2.pycharm中file->setting
+号添加库
爬取网页数据
1. requests库
可以说, Requests是用Python语言编写的简单易⽤的HTTP库
1.1基本操作
r=requests.get("http://www.baidu.com/") # 请求网页
print(r.status_code) # HTTP请求的返回状态,200表示连接成功,404表示失败
print(type(r))
print(r.headers) # 头部信息
print(r.encoding) # 头部可能编码形式
print(r.apparent_encoding) # 内容可能编码形式
r.encoding=r.apparent_encoding
print(r.text) # HTTP响应内容的字符串形式,即,url对应的页面内容
requests | |
---|---|
获取url | request = requests.get(“http://www…com”) |
获取状态码 | request.states_code |
返回html | request.text |
获得头部信息 | request.headers |
返回请求的url | request.url |
requests.get(‘url’) #GET请求,获取url位置上的资源
requests.post(“url”) #POST请求,在url位置的资源后附加新的数据
requests.put(“url”) #PUT请求,向url位置存储资源,覆盖原有的资源
requests.delete(“url”) #DELETE请求,删除url位置存储的资源
#PATCH请求,局部更新url位置的资源,改变该处资源的部分内容,优点是节省网络带宽
requests.head(“url”) #HEAD请求
requests.options(“url”) #OPTIONS请求
1.2 网页爬取通用框架
def getHTMLText(url):
try:
# kv={'user_agent':'Mozilla/5.0'} #更改头部信息,对于要求较高的网站
# r = requests.get(url, headers=kv)
r = requests.get(url, timeout=30)
r.raise_for_status() # 如果状态不是200, 引发HTTPError异常
r.encoding = r.apparent_encoding
return r.text
except:
return "产生异常"
if __name__ == "__main__":
url = "http://www.baidu.com"
print(getHTMLText(url))
2.XPath
XPath 是一门在 XML 文档中查找信息的语言
XML文档是被作为节点树来对待的,树的根被称为根节点或者文档节点
节点之间的关系有:父(parent)、子(children)、同胞(sibling)、先辈(ancestor,该节点的父,父的父等)、后代(decentant,该节点的子,子的子)
2.1 语法
a.选取节点
方式 | 描述 |
---|---|
/ | 绝对路径提取 |
// | 相对路径提取 |
@ | 指定属性提取 |
b.谓语
谓语用来查找某个特定的节点或者包含某个指定的值的节点。谓语被嵌在方括号中。
方式 | 描述 |
---|---|
/bookstore/book[1] | 选取属于 bookstore 子元素的第一个 book 元素。 |
/bookstore/book[last()] | 选取属于 bookstore 子元素的最后一个 book 元素。 |
/bookstore/book[last()-1] | 选取属于 bookstore 子元素的倒数第二个 book 元素。 |
/bookstore/book[position()< 3] | 选取最前面的两个属于 bookstore 元素的子元素的 book 元素。 |
//title[@lang] | 选取所有拥有名为 lang 的属性的 title 元素。 |
//title[@lang=‘eng’] | 选取所有 title 元素,且这些元素拥有值为 eng 的 lang 属性。 |
/bookstore/book[price>35.00] | 选取 bookstore 元素的所有 book 元素,且其中的 price 元素的值须大于 35.00。 |
/bookstore/book[price>35.00]/title | 选取 bookstore 元素中的 book 元素的所有 title 元素,且其中的 price 元素的值须大于 35.00。 |
c.选取未知节点
XPath 通配符可用来选取未知的 XML 元素
方法 | 描述 |
---|---|
* | 匹配任何元素节点。 |
@* | 匹配任何属性节点。 |
node() | 匹配任何类型的节点。 |
d.选取若干路径
通过在路径表达式中使用"|"运算符,您可以选取若干个路径。
如:/bookstore/book/title | //price: 选取属于 bookstore 元素的 book 元素的所有 title 元素,以及文档中所有的 price 元素。
2.2 查看网页
右击检查/(F12)
3. csv
csv文件格式是一种通用的电子表格和数据库导入导出格式。
# 读取csv文件
import csv
with open('some.csv', 'rb') as f: # 采用二进制的方式处理可以省去很多问题
reader = csv.reader(f)
for row in reader:
# do something with row, such as row[0],row[1]
# 如 print(row)
# 写入csv文件
import csv
with open('some.csv', 'wb') as f: # 采用二进制的方式处理可以省去很多问题
# 注意:如果打开csv文件出现空行的情况,那么需要添加一个参数 newline=” with open('some.csv','w',newline='')as f:
# 实例化csv.writer对象
writer = csv.writer(f)
# 用writerows方法将数据以指定形式保存
writer.writerows(someiterable)
# writerow(写入一行)writerows(写入多行)
# 在写入字典序列类型数据的时候,需要传入文件对象——f,字段名称——fieldnames
import csv
headers = ['class','name','sex','height','year']
rows = [
{'class':1,'name':'xiaoming','sex':'male','height':168,'year':23},
{'class':1,'name':'xiaohong','sex':'female','height':162,'year':22},
{'class':2,'name':'xiaozhang','sex':'female','height':163,'year':21},
{'class':2,'name':'xiaoli','sex':'male','height':158,'year':21},
]
with open('test2.csv','w',newline='')as f:
f_csv = csv.DictWriter(f,headers)
f_csv.writeheader() # 写表头
f_csv.writerows(rows) # 写入多行
获取豆瓣top250电影数据
每翻一页start+25
每部电影信息在 < li > 中
电影排名://div[@class=“item”]/div[1]/em/text()
同样在div[@class=“item”]下电影名字取第一个:div.xpath(‘div[2]/div[1]/a/span/text()’)[0]
导演主演信息:director = div.xpath(‘div[2]/div[2]/p/text()’)[0]
上映时间及国家和类型:
year_country =div.xpath(‘div[2]/div[2]/p/text()’)[1]
评分:grade = div.xpath(‘div[2]/div[2]/div/span[2]/text()’)[0]
评分人数:
div.xpath(‘div[2]/div[2]/div/span[4]/text()’)[0].replace(“人评价”,"")
短评:
div.xpath(‘div[2]/div[2]/p[2]/span/text()’)[0]
# split("/") 以“/”分割,得到年份、国家和分类
movie_year_string=str(year_country.replace('\n',"").replace("\xa0","").split("/")[0]) # split() 分割
movie_country_string=str(year_country.replace('\n',"").replace("\xa0","").split("/")[1])
movie_category_string=str(year_country.replace('\n',"").replace("\xa0","").split("/")[2])
#strip()方法从字符串中去掉在其左侧和右侧的空格时,括号内单引号里应保留空格,导演信息前有大量空格
movie_director_string=str(director.replace('\n',"").split('\xa0\xa0\xa0')[0]).strip(' ')
代码
import requests
from lxml import etree
import csv
with open("movie.csv","w",encoding="GB18030",newline="") as f:
writer = csv.DictWriter(f,fieldnames=["电影排名","电影名称","年份","国家","类型","导演","主演","电影评分","电影评论数","电影短评"])
writer.writeheader()
#拼接网址,发起请求
for x in range(0,226,25):
#拼接出来每一页的地址
url = "https://movie.douban.com/top250?start={}&filter=".format(x)
print("正在爬取--{}--网址的数据".format(url))
kv = {'User-Agent':'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.88 Safari/537.36'} # 更改头部信息,对于要求较高的网站
response = requests.get(url=url, headers=kv)
# print(response.headers)
html_obj = etree.HTML(response.text)
div_list = html_obj.xpath('//div[@class="item"]')
for div in div_list:
rank = div.xpath('div[1]/em/text()')[0]
movie_name = div.xpath('div[2]/div[1]/a/span/text()')[0]
director = div.xpath('div[2]/div[2]/p/text()')[0]
year_country = div.xpath('div[2]/div[2]/p/text()')[1]
# country=div.xpath('div[2]/div[2]/p/text()')[1].split("/")[0]
grade = div.xpath('div[2]/div[2]/div/span[2]/text()')[0]
#replace():把**字符替换成**
comment_num = div.xpath('div[2]/div[2]/div/span[4]/text()')[0].replace("人评价","")
#因为有的电影没有短评,强行匹配短评会报错!
try:
short_comment = div.xpath('div[2]/div[2]/p[2]/span/text()')[0]
except Exception as e:
short_comment="没有短评"
#定义一个字符串,存储清理过后的电影名称
movie_name_string = ''
for movie in movie_name:
#把电影名称中的\xa0替换成空,然后把处理过后的电影名称拼接起来
movie_name_string+=movie.replace("\xa0","") # \xa0 是不间断空白符  
# 定义字符串,存储清理过后的年份及国家
movie_year_string=str(year_country.replace('\n',"").replace("\xa0","").split("/")[0])
movie_country_string=str(year_country.replace('\n',"").replace("\xa0","").split("/")[1])
movie_category_string=str(year_country.replace('\n',"").replace("\xa0","").split("/")[2])
# 演员表中会遇到不完整情况
try:
movie_director_string=str(director.replace('\n',"").replace("导演:","").split('\xa0\xa0\xa0')[0]).strip(' ') #strip()方法从字符串中去掉在其左侧和右侧的空格时,括号内单引号里应保留空格
movie_actor_string = str(director.replace('\n', "").replace("主演:","").split('\xa0\xa0\xa0')[1])
except Exception as e:
movie_actor_string="..."
movie_dict = {"电影排名":rank,"电影名称":movie_name_string,"年份":movie_year_string,"国家":movie_country_string,"类型":movie_category_string,"导演":movie_director_string,"主演":movie_actor_string,"电影评分":grade,"电影评论数":comment_num,"电影短评":short_comment}
#一次写入一行数据
writer.writerow(movie_dict)
异常处理:
我们把可能发生错误的语句放在try模块里,用except来处理异常。每一个try,都必须至少有一个except
# except可以处理一个专门的异常,也可以处理一组圆括号中的异常,如果except后没有指定异常,则默认处理所有的异常
try:
c = b/ a
print c
except (IOError ,ZeroDivisionError),x:
print x
else:
print "no error"
print "done"
# 无论异常是否发生,在程序结束前,finally中的语句都会被执行
a=10
b=0
try:
print a/b
except:
print "error"
finally:
print "always excute"