admin管理员组

文章数量:1122854

Requests+Xpath 爬取豆瓣读书TOP并生成txt,csv,json,excel文件

说明:
##来源:.html

1 Requests+Xpath 爬取豆瓣读书TOP

‘’’
Requests+Xpath 爬取豆瓣读书TOP

安装 Python 应用包
pip install requests
pip install lxml

获取元素的Xpath信息并获得文本:

手动获取:定位目标元素,在网站上依次点击:右键 > 检查
file=s.xpath(‘元素的Xpath信息/text()’)

快捷键“shift+ctrl+c”,移动鼠标到对应的元素时即可看到对应网页代码:

在电影标题对应的代码上依次点击 右键 > Copy > Copy XPath,获取书名的Xpath:

‘’’

#注意:在浏览器上复制xpath 有时会多出多余的标签,则要删除,比如:tbody,这是因为浏览器为了规范。
‘’'分别复制《红楼梦》、《活着》、《百年孤独》、《1984》的 xpath 信息进行对比:

//[@id=“content”]/div/div[1]/div/table[1]/tbody/tr/td[2]/div[1]/a
//
[@id=“content”]/div/div[1]/div/table[2]/tbody/tr/td[2]/div[1]/a
//[@id=“content”]/div/div[1]/div/table[3]/tbody/tr/td[2]/div[1]/a
//
[@id=“content”]/div/div[1]/div/table[4]/tbody/tr/td[2]/div[1]/a

比较可以发现书名的 xpath 信息仅仅 table 后的序号不一样,并且跟书的序号一致,于是去掉序号(去掉 tbody),我们可以得到通用的 xpath 信息:

//*[@id=“content”]/div/div[1]/div/table/tr/td[2]/div[1]/a
‘’’

3 爬取页面多个信息时的数据准确匹配问题

strip(“(”) 表示删除括号, strip() 表示删除空白符。

‘’’

问题:我们默认书名和评分是正确的信息,如果某一项少爬或多爬了信息,匹配错误

思路:书名的标签肯定在这本书的框架内,以每本书为单位,分别取获取对应的信息,完全匹配

//[@id=“content”]/div/div[1]/div/table[1] #整本书
//
[@id=“content”]/div/div[1]/div/table[1]/tr/td[2]/div[1]/a #书名
//*[@id=“content”]/div/div[1]/div/table[1]/tr/td[2]/div[2]/span[2] #评分

我们发现,书名和评分 xpath 的前半部分和整本书的 xpath 一致的, 那我们可以通过这样写 xpath 的方式来定位信息:

file=s.xpath(“//*[@id=“content”]/div/div[1]/div/table[1]”)
title =div.xpath(“./tr/td[2]/div[1]/a/@title”)
score=div.xpath(“./tr/td[2]/div[2]/span[2]/text()”)

‘’’

4翻页

‘’’
=0 #第一页
=25 #第二页
=50 #第三页

以每页25为单位,递增25,只是 start=()的数字不一样

写一个循环

for a in range(3):
url = ‘={}’.format(a25)
#3个页面,用 a
25 保证以25为单位递增

‘’’

import requests
from requests.exceptions import RequestException
from lxml import etree
import time, json, csv,xlwt,xlrd
import pandas as pd
from xlutils.copy import copy# 第一步:#定义一个方法获取网页信息
def get_one_page(url):try:headers = {'User-Agent': 'Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N) AppleWebKit/537.36 (KHTML, like Gecko)''Chrome/91.0.4472.114 Mobile Safari/537.36',# 'Cookie':'bid=W55k4D_fSXM; __utmz=30149280.1625041982.1.1.utmcsr=baidu|utmccn=(organic)|utmcmd=organic; __gads=ID=8362a35481680256-22421ee50bca00f1:T=1625041983:RT=1625041983:S=ALNI_MZ0vPA34VtqtmD29r6pJirZIU8xWQ; __utmz=81379588.1625042017.1.1.utmcsr=baidu|utmccn=(organic)|utmcmd=organic; _gid=GA1.2.2054347723.1625042225; _ga=GA1.2.100943019.1625041982; __utma=30149280.100943019.1625041982.1625041982.1625125287.2; __utmc=30149280; __utmt_douban=1; __utma=81379588.444136571.1625042017.1625042017.1625125287.2; __utmc=81379588; __utmt=1; ap_v=0,6.0; _pk_ref.100001.3ac3=%5B%22%22%2C%22%22%2C1625125288%2C%22https%3A%2F%2Fwww.baidu%2Flink%3Furl%3Dz7cq9P4PInnWSErPqMmM4Lb6ZcQs4UjgaqSRLtPLfprPNKb3wDCbQYp3ZwLXM4BG%26wd%3D%26eqid%3Dd7960ea80001906f0000000560dc2c5b%22%5D; _pk_ses.100001.3ac3=*; __utmb=30149280.4.10.1625125287; __utmb=81379588.4.10.1625125287; _pk_id.100001.3ac3=6f14de07186baf65.1625042017.2.1625125324.1625042755.; dbcl2="207739408:CqN+9NKe/JI"'}response = requests.get(url, headers=headers)if response.status_code == 200:# print(response.text)'''with open('douban_dushu_top.html', 'a', encoding='utf-8') as f:f.write(response.text)'''return response.textelse:return Noneexcept RequestException:return None# 第二步:#定义一个方法使用xpath解析
def parse_one_page(html):s = etree.HTML(html)file = s.xpath('//*[@id="content"]/div/div[1]/div/table')time.sleep(3)result_lists = []for div in file:result_list = []title = div.xpath("./tr/td[2]/div[1]/a/@title")[0]href = div.xpath("./tr/td[2]/div[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(")").strip()scrible = div.xpath("./tr/td[2]/p[2]/span/text()")###以列表形式保存为txt格式if len(scrible) > 0:result_list = [title, href, score, num, scrible[0]]#print(result_list)else:result_list = [title, href, score, num]result_lists.append(result_list)#print(result_lists)return result_lists'''##以字典形式保存if len(scrible) > 0:# 字典形式yield {  # yield 生成器'title': title,'href': href,'score': score,'num': num,'scrible':scrible[0]}else:# 字典形式yield {  # yield 生成器'title': title,'href': href,'score': score,'num': num,}'''# 第三步: 写入文件txt
def write_to_file_txt(conent):# 写入文件with open('douban_dushu_top1.txt', 'a', encoding='utf-8') as f:# 以列表形式保存#f.write(','.join(conent))#f.write('\n' + '=' * 50 + '\n')# 以字典形式保存f.write(json.dumps(conent, indent=2, ensure_ascii=False))# 第三步: 写入文件json
def write_to_file_json(conent):with open('douban_dushu_top1.json', 'a', encoding='utf-8') as f:# print(type(json.dump(conent)))# ensure_ascii=False设置可以输出中文f.write(json.dumps(conent, indent=2, ensure_ascii=False))# 第三步: 写入文件csv
def write_to_file_csv(conent):''':param conent::return:'''#以pd方式写入csv时会出现编号,也是以字典形式传递'''df=pd.DataFrame(conent)df.to_csv('douban_dushu_top1.csv',encoding='utf-8')'''#以字典形式写入csvheader = ['title','href','score','num','scrible']with open('douban_dushu_top1.csv', 'a', encoding='utf-8', newline='') as f:writer = csv.DictWriter(f,header)writer.writeheader()writer.writerows(conent)#以列表形式写入csv'''header = ['title', 'href', 'score', 'num', 'scrible']with open('douban_dushu_top.csv','a',encoding='utf-8') as f:writer= csv.writer(f,dialect='excel')writer.writerow(header)for item in conent:writer.writerow(item)'''# 第三步: 写入文件excel
def write_excel_xls_hotal(path,sheet_name,content):index = len(content)# 获取需要写入数据的行数# 新建一个工作簿workbook=xlwt.Workbook()# 在工作簿中新建一个表格sheet = workbook.add_sheet(sheet_name)# 像表格中写入数据(对应的行和列)for i in range(0,index):for j in range(0, len(content[i])):sheet.write(i,j,content[i][j])# 保存工作簿workbook.save(path)print("xls格式表格写入数据成功!")#追加数据
def write_excel_xls_append(path, content):index = len(content)  # 获取需要写入数据的行数workbook = xlrd.open_workbook(path)  # 打开工作簿sheets = workbook.sheet_names()  # 获取工作簿中的所有表格worksheet = workbook.sheet_by_name(sheets[0])  # 获取工作簿中所有表格中的的第一个表格rows_old = worksheet.nrows  # 获取表格中已存在的数据的行数new_workbook = copy(workbook)  # 将xlrd对象拷贝转化为xlwt对象new_worksheet = new_workbook.get_sheet(0)  # 获取转化后工作簿中的第一个表格for i in range(0, index):for j in range(0, len(content[i])):new_worksheet.write(i + rows_old, j, content[i][j])  # 追加写入数据,注意是从i+rows_old行开始写入new_workbook.save(path)  # 保存工作簿print("xls格式表格【追加】写入数据成功!")# 第四步:翻页
def main(offset):# 每一页都是有规律的变化,都是offset的值在改变url = '={}'.format(offset * 25)print(url)html = get_one_page(url)items = parse_one_page(html)#以字典形式保存成csv格式#write_to_file_csv(items)#save_excel(items)return itemsif __name__ == '__main__':#以列表形式写入excelbook_name_xls = 'douban_dushu_top1.xlsx'sheet_name_xls = 'douban_dushu_top'value_title = [['title', 'href', 'score', 'num', 'scrible'], ]write_excel_xls_hotal(book_name_xls, sheet_name_xls, value_title)for i in range(6):item=main(i)write_excel_xls_append(book_name_xls, item)time.sleep(2)#保存成json格式'''for i in range(2):items = main(i)#write_to_file_json(items)#以列表形式保存for item in items:#以字典形式保存write_to_file_json(item)time.sleep(2)'''# 保存成csv格式'''for i in range(2):items = main(i)write_to_file_csv(items)#以列表或者字典形式保存time.sleep(2)'''# 保存成txt格式'''for i in range(2):items = main(i)for item in items:write_to_file_txt(item)#以列表或者字典形式保存time.sleep(2)'''

本文标签: RequestsXpath 爬取豆瓣读书TOP并生成txtcsvJsonExcel文件