网址:青春爱情文学_畅销青春爱情文学类图书【推荐 正版 价格】_青春文学-当当网
dangdang.py import scrapy from..items import DangdangBookItem # 定义名为DangdangSpider的爬虫类,继承自scrapy.Spider类 class DangdangSpider(scrapy.Spider): # 爬虫的名称,用于在Scrapy项目中唯一标识这个爬虫 name = "dangdang" # 当当网图书分类页面的基础URL,这里指向了某个图书分类页面(具体分类由URL中的参数决定) base_url = "https://category.dangdang.com/cp01.01.02.00.00.00.html" # 起始URL列表,爬虫开始抓取的页面,这里只设置了基础URL作为起始页面 start_urls = [base_url] # 用于记录当前正在抓取的页码,初始化为1 page_num = 1 def parse(self, response): """ 解析函数,用于处理抓取到的页面内容(response),提取图书相关信息,并生成数据项(item), 同时处理翻页逻辑,继续抓取后续页面内容。 参数: response: 抓取到的页面响应对象,包含了页面的HTML内容等信息。 """ # 使用CSS选择器选取页面中包含图书信息的每个li元素(每个li通常对应一本书的信息展示块) books = response.css('ul.bigimg li') for book in books: item = DangdangBookItem() # 使用CSS选择器选取图书标题对应的元素(a标签) title_element = book.css('p.name a') # 进一步获取标题文本内容,如果获取到则去除两端空白字符后赋值给item['title'], # 如果没获取到则设置默认值 "Title not found" title = title_element.css('::text').get() if title: item['title'] = title.strip() else: item['title'] = "Title not found" # 使用CSS选择器选取图书当前价格对应的元素,并获取文本内容, # 如果获取到则去除价格符号'¥'和两端空白字符后赋值给item['price'], # 如果没获取到则设置默认值 "Price not found" price_text = book.css('span.search_now_price::text').get() if price_text: item['price'] = price_text.replace('¥', '').strip() else: item['price'] = "Price not found" # 使用CSS选择器选取图书原价对应的元素,并获取文本内容, # 如果获取到则去除价格符号'¥'和两端空白字符后赋值给item['original_price'], # 如果没获取到则设置默认值 "Original price not found" original_price_text = book.css('span.search_pre_price::text').get() if original_price_text: item['original_price'] = original_price_text.replace('¥', '').strip() else: item['original_price'] = "Original price not found" # 使用CSS选择器选取图书折扣对应的元素,并获取文本内容, # 如果获取到则通过字符串处理提取折扣数值(去除括号等多余字符)后赋值给item['discount'], # 如果没获取到则设置默认值 "Discount not found" discount_text = book.css('span.search_discount::text').get() if discount_text: item['discount'] = discount_text.split('(')[1].split(')')[0].strip() else: item['discount'] = "Discount not found" # 使用CSS选择器选取图书作者对应的元素(a标签),获取所有作者文本内容列表, # 如果获取到则用逗号连接作者名字并去除两端空白字符后赋值给item['author'], # 如果没获取到则设置默认值 "Author not found" authors = book.css('p.search_book_author a:first-child::text').getall() if authors: item['author'] = ', '.join(authors).strip() else: item['author'] = "Author not found" # 使用CSS选择器选取图书出版社对应的元素(a标签),获取出版社文本内容, # 如果获取到则去除两端空白字符后赋值给item['publisher'], # 如果没获取到则设置默认值 "Publisher not found" publisher = book.css('p.search_book_author a:last-child::text').get() if publisher: item['publisher'] = publisher.strip() else: item['publisher'] = "Publisher not found" # 使用CSS选择器选取图书评论数量对应的元素(a标签),获取文本内容, # 如果获取到则去除"条评论"字样和两端空白字符后赋值给item['comment_num'], # 如果没获取到则设置默认值 "Comment number not found" comment_num_element = book.css('p.search_star_line a') comment_num = comment_num_element.css('::text').get() if comment_num: item['comment_num'] = comment_num.replace('条评论', '').strip() else: item['comment_num'] = "Comment number not found" # 使用CSS选择器选取图书描述对应的元素(p.detail),获取所有描述文本内容列表, # 如果获取到则合并文本内容并去除两端空白字符后赋值给item['description'], # 如果没获取到则设置默认值 "Description not found" description_element = book.css('p.detail') description = description_element.css('::text').getall() if description: item['description'] = ' '.join([desc.strip() for desc in description]).strip() else: item['description'] = "Description not found" # 使用CSS选择器选取图书出版日期对应的元素(span元素),获取文本内容, # 如果获取到则去除两端空白字符后赋值给item['release_date'], # 如果没获取到则设置默认值 "Release date not found" release_date_element = book.css('p.search_book_author span:nth-child(2)::text').get() if release_date_element: item['release_date'] = release_date_element.strip() else: item['release_date'] = "Release date not found" # 将提取好信息的item(数据项)通过生成器返回,交给后续的管道(pipeline)处理 yield item # 初始化下一页的URL为None next_page_url = None # 使用CSS选择器选取页面中指向“下一页”的链接元素(a标签) next_page_links = response.css('div.paging li.next a') if next_page_links: # 如果存在“下一页”链接,则获取第一个链接的href属性值作为下一页的URL next_page_url = next_page_links[0].attrib['href'] if next_page_url: # 如果获取到了下一页的URL,则构造一个新的Scrapy请求,使用当前的解析函数(self.parse) # 作为回调函数继续处理下一页的内容,这样可以实现自动翻页抓取 yield scrapy.Request(response.urljoin(next_page_url), callback=self.parse)
pipelines.py
import csv from scrapy.exceptions import DropItem # 定义名为DangdangBooksPipeline的管道类,用于处理爬虫提取到的数据项(item), # 这里主要功能是将图书信息写入CSV文件。 class DangdangBooksPipeline: def open_spider(self, spider): """ 在爬虫启动时被调用,用于初始化文件相关操作,比如打开文件、决定写入模式(追加或覆盖), 以及初始化CSV写入器等。 参数: spider: 当前正在运行的爬虫对象实例。 """ try: # 尝试以读模式打开名为'dangdang_books.csv'的文件(用于检查文件是否已存在) with open('dangdang_books.csv', 'r', newline='', encoding='utf-8') as f: # 提示用户输入,决定是否追加数据到已存在的文件中 choice = input("文件已存在,是否追加数据?(y/n): ") if choice.lower() == 'y': # 如果用户选择追加(输入'y'),则以追加模式打开文件,并初始化CSV写入器, # 指定写入的字段名(列名) self.file = open('dangdang_books.csv', 'a', newline='', encoding='utf-8') self.writer = csv.DictWriter(self.file, fieldnames=['书名', '价格', '原价', '折扣', '作者', '出版社', '评论数量', '描述', '出版日期']) else: # 如果用户选择不追加(输入其他字符),则以覆盖写入模式打开文件, # 并初始化CSV写入器,同时写入表头(字段名) self.file = open('dangdang_books.csv', 'w', newline='', encoding='utf-8') self.writer = csv.DictWriter(self.file, fieldnames=['书名', '价格', '原价', '折扣', '作者', '出版社', '评论数量', '描述', '出版日期']) self.writer.writeheader() except FileNotFoundError: # 如果文件不存在,则以写入模式打开文件(相当于新建文件), # 初始化CSV写入器并写入表头(字段名) self.file = open('dangdang_books.csv', 'w', newline='', encoding='utf-8') self.writer = csv.DictWriter(self.file, fieldnames=['书名', '价格', '原价', '折扣', '作者', '出版社', '评论数量', '描述', '出版日期']) self.writer.writeheader() def process_item(self, item, spider): """ 处理每个数据项(item)的方法,在这里会对数据项进行验证, 如果各项关键信息都存在,则进行格式转换后写入CSV文件,并返回该数据项让后续管道继续处理, 如果有关键信息缺失,则丢弃该数据项。 参数: item: 爬虫提取到的一个数据项,包含图书的各项信息。 spider: 当前正在运行的爬虫对象实例。 """ # 检查数据项中各项关键信息是否都存在(不为空) if item['title'] and item['price'] and item['original_price'] and item['discount'] and item['author'] and item[ 'publisher'] and item['comment_num'] and item['description'] and item['release_date']: # 如果各项关键信息都存在,则构造一个新的字典,将英文键名转换为中文键名(对应CSV的列名) new_item = { '书名': item['title'], '价格': item['price'], '原价': item['original_price'], '折扣': item['discount'], '作者': item['author'], '出版社': item['publisher'], '评论数量': item['comment_num'], '描述': item['description'], '出版日期': item['release_date'] } # 使用CSV写入器将转换后的字典数据写入CSV文件 self.writer.writerow(new_item) return item else: # 如果有关键信息缺失,则抛出DropItem异常,表示丢弃这个无效的数据项 raise DropItem(f"Invalid item: {item}") def close_spider(self, spider): """ 在爬虫关闭时被调用,用于关闭之前打开的文件资源。 参数: spider: 当前正在运行的爬虫对象实例。 """ self.file.close()
返回结果
标签:获取,text,price,当当网,爬取,item,scrapy,found,self From: https://blog.csdn.net/qq_68809241/article/details/143597483