上一篇已經講過怎樣獲取連接,怎樣得到參數了,詳情請看python爬取京東商城普通篇html
- 首先應該構造請求,這裏使用scrapy.Request,這個方法默認調用的是
start_urls
構造請求,若是要改變默認的請求,那麼必須重載該方法,這個方法的返回值必須是一個可迭代的對象,通常是用yield
返回,代碼以下:
def start_requests(self): for i in range(1,101): page=i*2-1 #這裏是構造請求url的page,表示奇數 url=self.start_url+str(page) yield scrapy.Request(url,meta={'search_page':page+1},callback=self.parse_url) #這裏使用meta想回調函數傳入數據,回調函數使用response.meta['search-page']接受數據
下面就是解析網頁了,從上面看出這裏的解析回調函數是
parse_url
,所以在此函數中解析網頁。這裏仍是和上面說的同樣,這個url
獲得的僅僅是前一半的信息,若是想要獲得後一半的信息還有再次請求,這裏還有注意的就是一個技巧:通常先解析出一個數據的數組,不急着取出第一個數,先要用if語句判斷,由於若是獲得的是[]
,那麼直接取出[0]
是會報錯的,這只是一個避免報錯的方法吧,代碼以下:python
def parse_url(self,response): if response.status==200: #判斷是否請求成功 # print response.url pids = set() #這個集合用於過濾和保存獲得的id,用於做爲後面的ajax請求的url構成 try: all_goods = response.xpath("//div[@id='J_goodsList']/ul/li") #首先獲得全部衣服的整個框架,而後從中抽取每個框架 for goods in all_goods: #從中解析每個 # scrapy.shell.inspect_response(response,self) #這是一個調試的方法,這裏會直接打開調試模式 items = JdSpiderItem() #定義要抓取的數據 img_url_src = goods.xpath("div/div[1]/a/img/@src").extract() # 若是不存在就是一個空數組[],所以不能在這裏取[0] img_url_delay = goods.xpath( "div/div[1]/a/img/@data-lazy-img").extract() # 這個是沒有加載出來的圖片,這裏不能寫上數組取第一個[0] price = goods.xpath("div/div[3]/strong/i/text()").extract() #價格 cloths_name = goods.xpath("div/div[4]/a/em/text()").extract() shop_id = goods.xpath("div/div[7]/@ data-shopid").extract() cloths_url = goods.xpath("div/div[1]/a/@href").extract() person_number = goods.xpath("div/div[5]/strong/a/text()").extract() pid = goods.xpath("@data-pid").extract() # product_id=goods.xpath("@data-sku").extract() if pid: pids.add(pid[0]) if img_url_src: # 若是img_url_src存在 print img_url_src[0] items['img_url'] = img_url_src[0] if img_url_delay: # 若是到了沒有加載完成的圖片,就取這個url print img_url_delay[0] items['img_url'] = img_url_delay[0] # 這裏若是數組不是空的,就能寫了 if price: items['price'] = price[0] if cloths_name: items['cloths_name'] = cloths_name[0] if shop_id: items['shop_id'] = shop_id[0] shop_url = "https://mall.jd.com/index-" + str(shop_id[0]) + ".html" items['shop_url'] = shop_url if cloths_url: items['cloths_url'] = cloths_url[0] if person_number: items['person_number'] = person_number[0] # if product_id: # print "************************************csdjkvjfskvnk***********************" # print self.comments_url.format(str(product_id[0]),str(self.count)) # yield scrapy.Request(url=self.comments_url.format(str(product_id[0]),str(self.count)),callback=self.comments) #yield scrapy.Request寫在這裏就是每解析一個鍵褲子就會調用回調函數一次 yield items except Exception: print "********************************************ERROR**********************************************************************" yield scrapy.Request(url=self.search_url.format(str(response.meta['search_page']),",".join(pids)),callback=self.next_half_parse) #再次請求,這裏是請求ajax加載的數據,必須放在這裏,由於只有等到獲得全部的pid才能構成這個請求,回調函數用於下面的解析
- 從上面代碼的最後能夠看出最後就是解析
ajax
加載的網頁了,這裏調用的next_half_parse
函數,和解析前面一個網頁同樣,這裏須要的注意的是,若是前面定義的數據沒有搜索完畢是不能使用yield items
的,必須將items經過meta傳入下一個回調函數繼續完善後才能yield items
,這裏就不須要了,代碼以下:
#分析異步加載的網頁 def next_half_parse(self,response): if response.status==200: print response.url items=JdSpiderItem() #scrapy.shell.inspect_response(response,self) #y用來調試的 try: lis=response.xpath("//li[@class='gl-item']") for li in lis: cloths_url=li.xpath("div/div[1]/a/@href").extract() img_url_1=li.xpath("div/div[1]/a/img/@src").extract() img_url_2=li.xpath("div/div[1]/a/img/@data-lazy-img").extract() cloths_name=li.xpath("div/div[4]/a/em/text()").extract() price=li.xpath("div/div[3]/strong/i/text()").extract() shop_id=li.xpath("div/div[7]/@data-shopid").extract() person_number=li.xpath("div/div[5]/strong/a/text()").extract() if cloths_url: print cloths_url[0] items['cloths_url']=cloths_url[0] if img_url_1: print img_url_1[0] items['img_url']=img_url_1 if img_url_2: print img_url_2[0] items['img_url']=img_url_2[0] if cloths_name: items['cloths_name']=cloths_name[0] if price: items['price']=price[0] if shop_id: items['shop_id']=shop_id[0] items['shop_url']="https://mall.jd.com/index-" + str(shop_id[0]) + ".html" if person_number: items['person_number']=person_number[0] yield items #又一次的生成,這裏是完整的數據,所以能夠yield items except Exception: print "**************************************************"
- 固然這裏還用到了設置請求池,
mysql
存儲,沒有使用到ip
代理,這個在我前面的博客中又講到,這裏就再也不贅述了,想看源代碼的朋友請點擊這裏
- 人們會抱怨爲何本身的爬蟲在中途斷開就要重頭開始爬,爲何不能從斷開那裏開始爬呢,這裏提供一個方法:在配置文件
settings.py
中加入JOBDIR=file_name
,這裏的file_name
是一個文件的名字
- 設置下載延遲防止被
ban
:DOWNLOAD_DELAY = 2
:設置每一次的間隔時間RANDOMIZE_DOWNLOAD_DELAY = True
:這個是隨機設置延遲時間 在設置的時間的0.5-1.5
倍之間,這樣能夠更有效的防止被ban,通常是配套使用的
ROBOTSTXT_OBEY = False
:這裏是表示不遵循robots.txt
文件,默認是True
表示遵循,這裏將之改爲False
CONCURRENT_REQUESTS
:設置最大請求數,這裏默認的時16
,咱們能夠根據本身電腦的配置改的大一點來加快請求的速度