回家之后就不想学习了…
这次用的是lxml库,因为听说比起BeautifulSoup它的速度更快,然后就想了解一下。(全部的代码在最下面)
import库
from lxml import etree
import requests
import json
# from time import sleep
这是要用到的库。requests请求html,lxml解析html文档,然后得到的数据通过json存储在json文件。
豆瓣网页">分析豆瓣网页
第一页:https://movie.douban.com/top250
第二页:https://movie.douban.com/top250?start=25&filter=
第三页:https://movie.douban.com/top250?start=50&filter=
发现一页有25个电影介绍,每多一页start=的数目迁移25。因此尝试:
发现成功后,分析网页源代码。
这次抓取的只是电影名、排名、分数、和简介。还是跟之前那样子通过Chrome的审查元素抓取Xpath路径。
分别有:
# info
# //*[@id="content"]/div/div[1]/ol/li[1]/div/div[1]/em index
# //*[@id="content"]/div/div[1]/ol/li[1]/div/div[2]/div[1]/a/span[1] name
# //*[@id="content"]/div/div[1]/ol/li[1]/div/div[2]/div[2]/div/span[2] rate
# //*[@id="content"]/div/div[1]/ol/li[1]/div/div[2]/div[2]/p[2]/span quote
这是第一个电影的信息,可以看出来我们要抓取的内容都在一个统一的节点div
上。而每个电影都在不同的li
里面。
重点代码
def get_one_page(url):
try:
response = requests.get(url)
if response.status_code == 200:
return response.content
return None
except requests.RequestException:
return None
这是通过request
来请求一个页面的函数。使用的RequestException
是request
库自带的,代表连接出错。status_code
等于200时代表连接正常,这时候我们返回页面。
更多状态码可以上菜鸟:http://www.runoob.com/http/http-status-codes.html
def parse_one_page(content):
html = etree.HTML(content)
films = html.xpath('//div[@class="article"]/ol/li')
for film in films:
yield{
'name': film.xpath('./div//span[@class="title"][1]/text()'),
'index': film.xpath('./div//div[@class="pic"]/em/text()'),
'quote': film.xpath('./div//span[@class="inq"]/text()'),
'rating_num': film.xpath('./div//span[@class="rating_num"]/text()'),
}
xpath用法中,//表示搜索所有的子孙节点,而/是直接的子节点。我们先通过class属性选择对应的div
,再选择它分支的所有li
节点。这个时候,我们再迭代所有的li
节点。
需要注意的是,我们在迭代的时候只操作当前节点,所以我们路径都有个./
最后选择的是yield,这样子这个函数就是个迭代器了。在主函数中,我们迭代这个函数收集信息就可以了。
def write(data):
with open('douban_top250.json', 'a', encoding='utf-8') as f:
f.write(json.dumps(data, ensure_ascii=False) + '\n')
这里把信息写到自己建的文件douban_top250.json
中。
if __name__ == '__main__':
douban_films = 'https://movie.douban.com/top250?start='
for i in range(0, 226, 25):
# print(i)
page = douban_films + str(i)
content = get_one_page(page)
if content is not None:
for item in parse_one_page(content):
# print(item)
write(item)
else:
print('Request Error')
# sleep(5)
这个是总的过程。自己设置i
遍历25个页面,然后通过自己构造的函数来解析信息,最后输入到文件中。需要解释的是,这里注释掉的三个语句是我在测试的时候检查错误先写上去的。
最终的代码如下(好简短):
from lxml import etree
import requests
import json
def get_one_page(url):
try:
response = requests.get(url)
if response.status_code == 200:
return response.content
return None
except requests.RequestException:
return None
def parse_one_page(content):
html = etree.HTML(content)
films = html.xpath('//div[@class="article"]/ol/li')
for film in films:
yield{
'name': film.xpath('./div//span[@class="title"][1]/text()'),
'index': film.xpath('./div//div[@class="pic"]/em/text()'),
'quote': film.xpath('./div//span[@class="inq"]/text()'),
'rating_num': film.xpath('./div//span[@class="rating_num"]/text()'),
}
def write(data):
with open('douban_top250.json', 'a', encoding='utf-8') as f:
f.write(json.dumps(data, ensure_ascii=False) + '\n')
if __name__ == '__main__':
douban_films = 'https://movie.douban.com/top250?start='
for i in range(0, 226, 25):
page = douban_films + str(i)
content = get_one_page(page)
if content is not None:
for item in parse_one_page(content):
write(item)
else:
print('Request Error')
效果如图: