scrapy 小节
1: 获取下一页的几种方法
total_number = int(response.xpath('//div[@class="p_in"]/span[@class="td"]/text()').re_first('\d+')) for number in range(1, total_number + 1): url = 'https://search.51job.com/list/170200,000000,0000,00,9,99,python,2,{}.html?lang=c&stype=&postchannel=0000&workyear=99&cotype=99°reefrom=99&jobterm=99&companysize=99&providesalary=99&lonlat=0%2C0&radius=-1&ord_field=0&confirmdate=9&fromType=&dibiaoid=0&address=&line=&specialarea=00&from=&welfare='.format( number) yield scrapy.Request(url, callback=self.parse_list_page)
[1]:获取到总页数, 利用.format的方法(格式化的方法)拿到next_href, 函数的调用也发生了改变
def parse(self, response): """ 解析首页源代码 1- 将当前页的数据提取出来。 2- 将后续页面 第2/3/4....页 url构造成Request,并保存到调度器中。 :param response: :return: """ # 获取下一页的url # re_first(): 从当前列表中根据正则提取第一个元素的内容 total_number = int(response.xpath('//div[@class="p_in"]/span[@class="td"]/text()').re_first('\d+')) for number in range(1, total_number + 1): url = 'https://search.51job.com/list/170200,000000,0000,00,9,99,python,2,{}.html?lang=c&stype=&postchannel=0000&workyear=99&cotype=99°reefrom=99&jobterm=99&companysize=99&providesalary=99&lonlat=0%2C0&radius=-1&ord_field=0&confirmdate=9&fromType=&dibiaoid=0&address=&line=&specialarea=00&from=&welfare='.format( number) yield scrapy.Request(url, callback=self.parse_list_page) def parse_list_page(self, response): # 提取详情页连接 detail_hrefs = response.xpath('//div[@class="el"]/p/span/a/@href').extract() for url in detail_hrefs: yield scrapy.Request(url, callback=self.parse_detail_page)
[2]:直接拿到下一页的真实地址next_href, 直接调用
def parse(self, response): next_href = response.xpath('//div[@class="pa"]/form/div/a[contains(.,"下")]/@href').extract_first(default='') next_href = 'https://weibo.cn' + next_href yield scrapy.Request(url=next_href, callback=self.parse, dont_filter=False)
[3]: 在不知道总页数的情况下, 可以尝试寻找最后一页
# 寻找下一页的url地址 try: next_page = response.xpath('//a[@class="nextpage"]/@href').extract_first('') except: print('最后一页') else: next_page = 'http://sc.chinaz.com/tubiao' + next_page yield scrapy.Request(next_page, callback=self.parse_category_page)[4]: 在写一页的url有规律时, 可以这样比较简单的查找写一页
# 获取下一页 next_page_url = 'https://www.hongxiu.com/all?pageNum={}'.format(self.page_num) if self.page_num < 3: self.page_num += 1 yield scrapy.Request(next_page_url, callback=self.parse)
2:关于主域名
allowed_domains = [" ", " "]
里面的值可以是一个, 亦可以是多个, 全局只允许含有主域名的网址, 能被识别到
3:处理select对象的几种方法
.extract()
.extract_first('')
.re_first() : 从当前列表中根据正则提取第一个元素的内容
需要注意的是:.extract() 和 .extract_first('') 这两种方法调用之后, 就不能再接着调用xpath(" ") 和 css(" ")了 !!!!
4:保存数据的方法
[1]: 保存到pymongo数据库中(这种方法比较简单)
[2]: 保存图片到指定位置
[3]: 保存数据到MySQL数据库中
import pymysql class HongxiuPipeline(object): # process_item() 从spider中yield过来的item, 都要执行这个函数。会被多次调用 def process_item(self, item, spider): insert_sql = "INSERT INTO hx(title, author, tags, total_word_num, keep_num, click_num, info) VALUES (%s, %s, %s, %s, %s, %s, %s)" self.cursor.execute(insert_sql, (item['title'], item['author'], item['tags'], item['total_word_num'], item['keep_num'], item['click_num'], item['info'])) self.connect.commit() # open_spider()和close_spider():只在爬虫被打开和关闭时,执行一次。 def open_spider(self, spider): self.connect = pymysql.connect( host='localhost', user='root', port=3306, passwd='123456', db='hongxiu', charset='utf8' ) self.cursor = self.connect.cursor() def close_spider(self, spider): self.cursor.close() self.connect.close()
5:处理数据的几种方法
[1]: .join() 将许多的单个数据组合成一份新的列表
[2]: .strip() 去掉数据两端的空格
[3]: .replace(" "," ") 用后面的来替换前面的数据
6:处理网页中数据的图片有无的问题
7:使用Item_Loaders方法对数据进行处理
from scrapy.loader import ItemLoader
def parse_detail_page(self, response): """ 解析详情页数据 :param response: :return: """ item_loader = ItemLoader(item=JobboleItem(), response=response) item_loader.add_xpath('title', '//div[@class="entry-header"]/h1/text()') item_loader.add_xpath('date_time', '//p[@class="entry-meta-hide-on-mobile"]/text()') item_loader.add_xpath('tags', '//p[@class="entry-meta-hide-on-mobile"]/a/text()') item_loader.add_xpath('content', '//div[@class="entry"]//text()') item_loader.add_xpath('zan_num', '//div[@class="post-adds"]/span[contains(@class, "vote-post-up")]//text()') item_loader.add_xpath('keep_num', '//div[@class="post-adds"]/span[contains(@class, "bookmark-btn")]/text()') item_loader.add_xpath('comment_num', '//div[@class="post-adds"]/a/span/text()') item_loader.add_value('img_src', [response.meta['img_src']]) item = item_loader.load_item() yield item
8:一些导入方法的使用
[1] : from datetime import datetime
目的是将字符串类型的时间转化成datetime类型的时间
9:post请求的处理方法