scrapy翻页

酥酥 发布于 2021-09-18 117 次阅读


一、翻页的方式复习

观察网页结构通过获取下一页的href的值在进行适当的url拼接
				
					if response.xpath('//a[text()="Next »"]/@href'):   
        next_page = response.xpath('//a[text()="Next»"]/@href').extract()[0]   
        print('next_page',next_page)   
        next_page = response.urljoin(next_page)   
        # print(next_page)   
        yield Request(next_page, callback=self.parse_second, meta={'item': item})
				
			

二、观察querystring然后凭借不同页不同的querystring去访问

				
					for next_page in range(0,166):   
     next_page = 'http://tochka3evlj3sxdv.com/?page={}&city=0&category=0&sortby=popularity&account=all&shipping-to=&shipping-from=&query='.format(next_page)   
     next_page = response.urljoin(next_page)   
     yield Request(next_page, callback=self.parse_sencond,meta={'item': item})
				
			

三、post来说,要通过表单去实现翻页

				
					u = response.url 
cat = re.findall(r'&cat=([\s|\S]+)', u)[0]
print(cat) page = response.xpath('//button[@class="btn btn-primary"][last()]/@value').extract()[0] 
print(page) 
for i in range(1, int(page)):   
    print(i)   
    formdata = {       
    'title':'',      
    'search':'1',       
    'searchcat':'1',      
    'dator':'9Ac3^nYrdUjEUa8LRdV7RVHchwj6pC(u',   
    'type':'all',       
    'payment':'all',       
    'priceMin':'',       
    'priceMax':'',       
    'shipsfrom':'all',       
    'shipsto':'all',       
    'field':'all',       
    'order':'all',       
    'displayname':'',       
    'cat':cat,      
    'page':str(i)   }  
    yield FormRequest(u, formdata=formdata,callback=self.parse_third, meta={'item': item})
				
			

四、selenium实现翻页

				
					res = etree.HTML(self.browser.page_source) 
page = res.xpath('//div[@id="page"]/a/@href') 
for u in page:   
    next_url = 'https://www.baidu.com' + u   
    print(next_url)   
    self.browser.get(next_url)
				
			

二、scrapy翻页

主要是在spider,py的parse方法中搞

翻页要判断是不是最后一段,有的网站即使是最后一页,下一页也会有href属性,所以要取出href属性进行if判断

				
					next_url=response.xpath(...../@href).extract_first()
if next_url="xx":
    url=response.urljoin(BASE_URL+next_url) 
    yield scrapy.Request(url,callback=self.parse)##不同页相同的回调执行,类似递归,如果想采用不同的回调函数,可以在下方自定义
    def parse1(self,response) 
else: ....
				
			

三、useragent配置

settings.py 中有关于useragent的注释,取消后可以自己改相应useragent

四、不同解析函数的参数传递

关键字meta
				
					def parse(self,response): 
    yield item
#item为要传的参数
    yield scrapy.Request(url,callback=self.parse1,meta={"item",item})
    #还有一个参数dont_filter是scrapy的去重功能,默认请求过的url不会再被请求,所以如果要继续请求还需要设置为True,比如同url在不同时间效果不一样比如百度贴吧这样的,要定时去重新访问的,要搞到true
    def parse1(self,resoponse): response.meta['item']#获取到了item
				
			

五、items.py的使用

items.py的使用

				
					import scrapy
class TencentItem(scrapy.Item):  
    # define the fields for your item here like:  
    title=scrapy.Field()  
    name=scrapy.Field()##为要爬取的字段占位   
    pass
				
			

在items定义完了以后,在spider中引入对应类,然后创建一个items对象,这个items对象就是类似一个字典,可以采用字典操作给入键,然后值则是要爬取的内容。

采用以上方式由于item已经不是一个字典了,所以要使用mongodb插入字典类型数据则需要insert(dict(item))

而且在items中可以定义多个类,在pipeline中引入后 通过if isinstance判断传来的item是属于哪个类,进而判断是那个爬虫对应的item字段,插入到不同的数据库

Final

请务必在meta传参时对item进行深拷贝

				
					meta={“item”:deepcopy(itrm)} 在多进程的情况下,后面爬的item的某些key在前面使用时会被修改,因为我们传参都是传引用,所以后面的item值也会变, print获取的是一瞬间的所有item值,很容易错拼的
				
			

案例

				
					# -*- coding: utf-8 -*-
import request
import scrapy
from ..items import InformationItem,GameItem
from copy import deepcopy
class ScrapygameSpider(scrapy.Spider):
    name = 'scrapygame'
    allowed_domains = ['4399.com']
    start_urls = ['http://4399.com/']
    def parse(self, response):
        BASE_URL = 'http://4399.com'
        lilist=response.xpath("//*[@id='skinbody']/div[10]/div[1]/div[1]/ul/li")
        for li in lilist:
            item1=GameItem()
            item1["gamename"]=li.xpath("./a/text()").extract_first()
            item1["next_page"]=li.xpath("./a/@href").extract_first()
            yield item1
            new_url=BASE_URL+item1["next_page"]
            yield scrapy.Request(new_url,callback=self.parse_date,meta={"gamename":deepcopy(item1["gamename"])})
    def parse_date(self,response):
        item2 = InformationItem()
        gamename=response.meta["gamename"]
        date=response.css("div .cls::text").extract_first()
        yield item2