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&degreefrom=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&degreefrom=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数据库中(这种方法比较简单)

scrapy 小节

           [2]: 保存图片到指定位置

scrapy 小节


       [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()  将许多的单个数据组合成一份新的列表

scrapy 小节

        [2]: .strip()  去掉数据两端的空格

scrapy 小节

        [3]: .replace(" "," ")  用后面的来替换前面的数据


6:处理网页中数据的图片有无的问题

        scrapy 小节


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类型的时间

scrapy 小节

scrapy 小节

scrapy 小节


9:post请求的处理方法

scrapy 小节